Changeset 90866 in webkit


Ignore:
Timestamp:
Jul 12, 2011 4:31:05 PM (13 years ago)
Author:
abarth@webkit.org
Message:

garden-o-matic should display regression ranges
https://bugs.webkit.org/show_bug.cgi?id=64407

Reviewed by Dimitri Glazkov.

This patch computes a regression range for a failure by intersecting
the regression ranges seen by the various bots. We make the underlying
assumption that a test is only failing due to one revision at any given
moment. If that's not true, this code probably explodes.

The regression ranges appear asynchronously, which might be a jarring
UI. We'll have to experiment to see.

  • Scripts/webkitpy/tool/servers/data/gardeningserver/base.js:
  • Scripts/webkitpy/tool/servers/data/gardeningserver/base_unittests.js:
  • Scripts/webkitpy/tool/servers/data/gardeningserver/main.js:
  • Scripts/webkitpy/tool/servers/data/gardeningserver/results.js:
  • Scripts/webkitpy/tool/servers/data/gardeningserver/results_unittests.js:
  • Scripts/webkitpy/tool/servers/data/gardeningserver/ui.js:
  • Scripts/webkitpy/tool/servers/data/gardeningserver/ui_unittests.js:
Location:
trunk/Tools
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Tools/ChangeLog

    r90864 r90866  
     12011-07-12  Adam Barth  <abarth@webkit.org>
     2
     3        garden-o-matic should display regression ranges
     4        https://bugs.webkit.org/show_bug.cgi?id=64407
     5
     6        Reviewed by Dimitri Glazkov.
     7
     8        This patch computes a regression range for a failure by intersecting
     9        the regression ranges seen by the various bots.  We make the underlying
     10        assumption that a test is only failing due to one revision at any given
     11        moment.  If that's not true, this code probably explodes.
     12
     13        The regression ranges appear asynchronously, which might be a jarring
     14        UI.  We'll have to experiment to see.
     15
     16        * Scripts/webkitpy/tool/servers/data/gardeningserver/base.js:
     17        * Scripts/webkitpy/tool/servers/data/gardeningserver/base_unittests.js:
     18        * Scripts/webkitpy/tool/servers/data/gardeningserver/main.js:
     19        * Scripts/webkitpy/tool/servers/data/gardeningserver/results.js:
     20        * Scripts/webkitpy/tool/servers/data/gardeningserver/results_unittests.js:
     21        * Scripts/webkitpy/tool/servers/data/gardeningserver/ui.js:
     22        * Scripts/webkitpy/tool/servers/data/gardeningserver/ui_unittests.js:
     23
    1242011-07-12  Adam Barth  <abarth@webkit.org>
    225
  • trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/base.js

    r90822 r90866  
    3737    });
    3838    return result;
     39};
     40
     41base.keys = function(dictionary)
     42{
     43    var keys = [];
     44    $.each(dictionary, function(key, value) {
     45        keys.push(key);
     46    });
     47    return keys;
    3948};
    4049
  • trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/base_unittests.js

    r90822 r90866  
    3838    deepEqual(base.uniquifyArray(["a", "b", "b"]), ["a", "b"]);
    3939    deepEqual(base.uniquifyArray(["a", "b", "b", "a"]), ["a", "b"]);
     40});
     41
     42test("keys", 4, function() {
     43    deepEqual(base.keys({}), []);
     44    deepEqual(base.keys({"a": 1}), ["a"]);
     45    deepEqual(base.keys({"a": 1, "b": 0}), ["a", "b"]);
     46    deepEqual(base.keys({"a": 1, "b": { "c" : 1}}), ["a", "b"]);
    4047});
    4148
  • trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/main.js

    r90846 r90866  
    2323            partyTime.fadeIn(1200).delay(7000).fadeOut();
    2424        } else {
    25             var resultsSummary = ui.summarizeResultsByTest(unexpectedFailures);
    26             $('.results').append($(resultsSummary).addClass('regression'));
     25            var regressions = $('<div class="results-summary regression"></div>');
     26            $.each(resultsByTest, function(testName, resultNodesByBuilder) {
     27                var testSummary = ui.summarizeTest(testName, resultNodesByBuilder);
     28                regressions.append(testSummary);
     29
     30                var builderNameList = base.keys(resultNodesByBuilder);
     31                results.unifyRegressionRanges(builderNameList, testName, function(oldestFailingRevision, newestPassingRevision) {
     32                    $('.when', regressions).append(ui.summarizeRegressionRange(oldestFailingRevision, newestPassingRevision));
     33                });
     34            });
     35            $('.results').append(regressions);
    2736        }
    2837        setIconState(hasFailures);
  • trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/results.js

    r90822 r90866  
    258258};
    259259
     260function mergeRegressionRanges(regressionRanges)
     261{
     262    var mergedRange = {};
     263
     264    mergedRange.oldestFailingRevision = 0;
     265    mergedRange.newestPassingRevision = 0;
     266
     267    $.each(regressionRanges, function(builderName, range) {
     268        if (!mergedRange.oldestFailingRevision)
     269            mergedRange.oldestFailingRevision = range.oldestFailingRevision;
     270        if (!mergedRange.newestPassingRevision)
     271            mergedRange.newestPassingRevision = range.newestPassingRevision;
     272
     273        if (range.oldestFailingRevision < mergedRange.oldestFailingRevision)
     274            mergedRange.oldestFailingRevision = range.oldestFailingRevision;
     275        if (range.newestPassingRevision > mergedRange.newestPassingRevision)
     276            mergedRange.newestPassingRevision = range.newestPassingRevision;
     277    });
     278    return mergedRange;
     279}
     280
     281results.unifyRegressionRanges = function(builderNameList, testName, callback)
     282{
     283    var queriesInFlight = builderNameList.length;
     284    if (!queriesInFlight)
     285        callback(0, 0);
     286
     287    var regressionRanges = {};
     288    $.each(builderNameList, function(index, builderName) {
     289        results.regressionRangeForFailure(builderName, testName, function(oldestFailingRevision, newestPassingRevision) {
     290            var range = {};
     291            range.oldestFailingRevision = oldestFailingRevision;
     292            range.newestPassingRevision = newestPassingRevision;
     293            regressionRanges[builderName] = range;
     294
     295            --queriesInFlight;
     296            if (!queriesInFlight) {
     297                var mergedRange = mergeRegressionRanges(regressionRanges);
     298                callback(mergedRange.oldestFailingRevision, mergedRange.newestPassingRevision);
     299            }
     300        });
     301    });
     302};
     303
    260304results.resultNodeForTest = function(resultsTree, testName)
    261305{
  • trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/results_unittests.js

    r90822 r90866  
    138138}
    139139
    140 test("regressionRangeForFailure", 3, function() {
     140test("regressionRangeForFailure", 5, function() {
    141141    var simulator = new NetworkSimulator();
    142142
     
    189189            },
    190190            "revision": "90424"
     191        },
     192        "abc":{
     193            "tests": {
     194                "userscripts": {
     195                    "another-test.html": {
     196                        "expected": "PASS",
     197                        "actual": "TEXT"
     198                    }
     199                },
     200            },
     201            "revision": "90426"
     202        },
     203        "xyz":{
     204            "tests": {
     205            },
     206            "revision": "90425"
    191207        }
    192208    };
     
    195211        simulator.scheduleCallback(function() {
    196212            if (/dir=1/.test(url)) {
    197                 callback([
    198                     { "key": "agx0ZXN0LXJlc3VsdHNyEAsSCFRlc3RGaWxlGLncUAw" },
    199                     { "key": "agx0ZXN0LXJlc3VsdHNyEAsSCFRlc3RGaWxlGNfTUAw" },
    200                     { "key": "agx0ZXN0LXJlc3VsdHNyEAsSCFRlc3RGaWxlGJWCUQw" },
    201                     { "key": "agx0ZXN0LXJlc3VsdHNyEAsSCFRlc3RGaWxlGKbLUAw" },
    202                     { "key": "agx0ZXN0LXJlc3VsdHNyEAsSCFRlc3RGaWxlGOj5UAw" },
    203                     { "key": "agx0ZXN0LXJlc3VsdHNyEAsSCFRlc3RGaWxlGP-AUQw" },
    204                     { "key": "agx0ZXN0LXJlc3VsdHNyEAsSCFRlc3RGaWxlGPL3UAw" },
    205                     { "key": "agx0ZXN0LXJlc3VsdHNyEAsSCFRlc3RGaWxlGNHJQAw" },
    206                 ]);
     213                if (/builder=Mock/.test(url)) {
     214                    callback([
     215                        { "key": "agx0ZXN0LXJlc3VsdHNyEAsSCFRlc3RGaWxlGLncUAw" },
     216                        { "key": "agx0ZXN0LXJlc3VsdHNyEAsSCFRlc3RGaWxlGNfTUAw" },
     217                        { "key": "agx0ZXN0LXJlc3VsdHNyEAsSCFRlc3RGaWxlGJWCUQw" },
     218                        { "key": "agx0ZXN0LXJlc3VsdHNyEAsSCFRlc3RGaWxlGKbLUAw" },
     219                        { "key": "agx0ZXN0LXJlc3VsdHNyEAsSCFRlc3RGaWxlGOj5UAw" },
     220                        { "key": "agx0ZXN0LXJlc3VsdHNyEAsSCFRlc3RGaWxlGP-AUQw" },
     221                        { "key": "agx0ZXN0LXJlc3VsdHNyEAsSCFRlc3RGaWxlGPL3UAw" },
     222                        { "key": "agx0ZXN0LXJlc3VsdHNyEAsSCFRlc3RGaWxlGNHJQAw" },
     223                    ]);
     224                } else if (/builder=Another/.test(url)) {
     225                    callback([
     226                        { "key": "abc" },
     227                        { "key": "xyz" },
     228                    ]);
     229                } else {
     230                    ok(false, 'Unexpected URL: ' + url);
     231                }
    207232            } else {
    208233                var key = url.match(/key=([^&]+)/)[1];
     
    215240            equals(oldestFailingRevision, 90426);
    216241            equals(newestPassingRevision, 90424);
     242        });
     243
     244        results.unifyRegressionRanges(["Mock Builder", "Another Builder"], "userscripts/another-test.html", function(oldestFailingRevision, newestPassingRevision) {
     245            equals(oldestFailingRevision, 90426);
     246            equals(newestPassingRevision, 90425);
    217247        });
    218248    });
  • trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/ui.js

    r90822 r90866  
    1313}
    1414
     15ui.urlForRevisionRange = function(firstRevision, lastRevision)
     16{
     17    if (firstRevision != lastRevision)
     18        return 'http://trac.webkit.org/log/trunk/?rev=' + firstRevision + '&stop_rev=' + lastRevision + '&limit=100&verbose=on';
     19    return 'http://trac.webkit.org/changeset/' + firstRevision;
     20};
     21
    1522ui.summarizeTest = function(testName, resultNodesByBuilder)
    1623{
     
    2128          '<span>fails on</span>' +
    2229          '<ul class="where"></ul>' +
     30          '<div class="when"></div>' +
    2331        '</div>');
    2432    $('.what a', block).text(testName).attr('href', ui.urlForTest(testName)).attr('class', unexpectedResults.join(' '));
     
    3240};
    3341
    34 ui.summarizeResultsByTest = function(resultsByTest)
     42ui.summarizeRegressionRange = function(oldestFailingRevision, newestPassingRevision)
    3543{
    36     var block = $('<div class="results-summary"></div>');
    37     $.each(resultsByTest, function(testName, resultNodesByBuilder) {
    38         block.append(ui.summarizeTest(testName, resultNodesByBuilder));
    39     });
    40     return block;
     44    if (!oldestFailingRevision || !newestPassingRevision)
     45        return $();
     46
     47    var impliedFirstFailingRevision = newestPassingRevision + 1;
     48
     49    var href = ui.urlForRevisionRange(impliedFirstFailingRevision, oldestFailingRevision);
     50    var textForRevisionRange = impliedFirstFailingRevision == oldestFailingRevision ? impliedFirstFailingRevision : impliedFirstFailingRevision + ':' + oldestFailingRevision;
     51    var text = 'Regression ' + textForRevisionRange;
     52
     53    return $('<a class="regression-range"></a>').attr('href', href).text(text);
    4154};
    4255
  • trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/ui_unittests.js

    r90822 r90866  
    2020}
    2121
    22 test("summarizeResultsByTest", 3, function() {
    23     var resultsSummary = ui.summarizeResultsByTest(kExampleResultsByTest);
    24     var resultsSummaryHTML = resultsSummary.html();
    25     ok(resultsSummaryHTML.indexOf('scrollbars/custom-scrollbar-with-incomplete-style.html') != -1);
    26     ok(resultsSummaryHTML.indexOf('userscripts/another-test.html') != -1);
    27     ok(resultsSummaryHTML.indexOf('Mock Builder') != -1);
     22test("summarizeTest", 3, function() {
     23    var testName = 'userscripts/another-test.html';
     24    var summary = ui.summarizeTest(testName, kExampleResultsByTest[testName]);
     25    var summaryHTML = summary.html();
     26    ok(summaryHTML.indexOf('scrollbars/custom-scrollbar-with-incomplete-style.html') == -1);
     27    ok(summaryHTML.indexOf('userscripts/another-test.html') != -1);
     28    ok(summaryHTML.indexOf('Mock Builder') != -1);
     29});
     30
     31test("summarizeRegressionRange", 2, function() {
     32    var summaryWithMultipleRevisions = ui.summarizeRegressionRange(90424, 90426);
     33    summaryWithMultipleRevisions.wrap('<wrapper></wrapper>');
     34    equal(summaryWithMultipleRevisions.parent().html(), '<a class="regression-range" href="http://trac.webkit.org/log/trunk/?rev=90427&amp;stop_rev=90424&amp;limit=100&amp;verbose=on">Regression 90427:90424</a>');
     35
     36    var summaryWithOneRevision = ui.summarizeRegressionRange(90425, 90426);
     37    summaryWithOneRevision.wrap('<wrapper></wrapper>');
     38    equal(summaryWithOneRevision.parent().html(), '<a class="regression-range" href="http://trac.webkit.org/log/trunk/?rev=90427&amp;stop_rev=90425&amp;limit=100&amp;verbose=on">Regression 90427:90425</a>');
    2839});
    2940
Note: See TracChangeset for help on using the changeset viewer.