| OLD | NEW |
| 1 // Copyright (C) 2012 Google Inc. All rights reserved. | 1 // Copyright (C) 2012 Google Inc. All rights reserved. |
| 2 // | 2 // |
| 3 // Redistribution and use in source and binary forms, with or without | 3 // Redistribution and use in source and binary forms, with or without |
| 4 // modification, are permitted provided that the following conditions are | 4 // modification, are permitted provided that the following conditions are |
| 5 // met: | 5 // met: |
| 6 // | 6 // |
| 7 // * Redistributions of source code must retain the above copyright | 7 // * Redistributions of source code must retain the above copyright |
| 8 // notice, this list of conditions and the following disclaimer. | 8 // notice, this list of conditions and the following disclaimer. |
| 9 // * Redistributions in binary form must reproduce the above | 9 // * Redistributions in binary form must reproduce the above |
| 10 // copyright notice, this list of conditions and the following disclaimer | 10 // copyright notice, this list of conditions and the following disclaimer |
| (...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 '/' + buildNumber + '/layout-test-results.zip">layout-test-results.z
ip</a></li>'; | 530 '/' + buildNumber + '/layout-test-results.zip">layout-test-results.z
ip</a></li>'; |
| 531 } | 531 } |
| 532 | 532 |
| 533 if (!g_history.isLayoutTestResults() && opt_testName && isFailure(builder, o
pt_testName, index)) | 533 if (!g_history.isLayoutTestResults() && opt_testName && isFailure(builder, o
pt_testName, index)) |
| 534 html += '<li>' + linkHTMLToOpenWindow(buildBasePath + pathToFailureLog(o
pt_testName), 'Failure log') + '</li>'; | 534 html += '<li>' + linkHTMLToOpenWindow(buildBasePath + pathToFailureLog(o
pt_testName), 'Failure log') + '</li>'; |
| 535 | 535 |
| 536 html += '</ul>'; | 536 html += '</ul>'; |
| 537 ui.popup.show(e.target, html); | 537 ui.popup.show(e.target, html); |
| 538 } | 538 } |
| 539 | 539 |
| 540 function showPopupForInterpolatedResult(e, revision) |
| 541 { |
| 542 var html = 'This bot did not run the test for r' + revision + '.'; |
| 543 ui.popup.show(e.target, html); |
| 544 } |
| 545 |
| 540 function classNameForFailureString(failure) | 546 function classNameForFailureString(failure) |
| 541 { | 547 { |
| 542 return failure.replace(/(\+|\ )/, ''); | 548 return failure.replace(/(\+|\ )/, ''); |
| 543 } | 549 } |
| 544 | 550 |
| 545 function htmlForTestResults(test) | 551 function htmlForTestResults(test, revisions) |
| 546 { | 552 { |
| 547 var html = ''; | 553 var html = ''; |
| 548 var testResults = test.rawResults.concat(); | 554 var testResults = test.rawResults.concat(); |
| 549 var times = test.rawTimes.concat(); | 555 var times = test.rawTimes.concat(); |
| 550 var builder = test.builder; | 556 var builder = test.builder; |
| 551 var master = builders.master(builder); | 557 var master = builders.master(builder); |
| 552 var buildNumbers = g_resultsByBuilder[builder].buildNumbers; | 558 var buildNumbers = g_resultsByBuilder[builder].buildNumbers; |
| 553 | 559 |
| 560 // FIXME: Support other revision types instead of just chrome/blink. |
| 561 var revisionType = g_history.isBlinkGroup() ? |
| 562 results.BLINK_REVISIONS : results.CHROME_REVISIONS; |
| 563 |
| 564 var cells = []; |
| 565 for (var index = 0; index < revisions.length; index++) |
| 566 cells.push({revision: revisions[index]}); |
| 567 |
| 554 var indexToReplaceCurrentResult = -1; | 568 var indexToReplaceCurrentResult = -1; |
| 555 var indexToReplaceCurrentTime = -1; | 569 var indexToReplaceCurrentTime = -1; |
| 556 for (var i = 0; i < buildNumbers.length; i++) { | 570 for (var i = 0; i < buildNumbers.length; i++) { |
| 557 var currentResultArray, currentTimeArray, innerHTML, resultString; | 571 var currentResultArray, currentTimeArray, currentTime, resultString; |
| 558 | 572 |
| 559 if (i > indexToReplaceCurrentResult) { | 573 if (i > indexToReplaceCurrentResult) { |
| 560 currentResultArray = testResults.shift(); | 574 currentResultArray = testResults.shift(); |
| 561 if (currentResultArray) { | 575 if (currentResultArray) { |
| 562 resultString = g_resultsByBuilder[builder][results.FAILURE_MAP][
currentResultArray[results.RLE.VALUE]]; | 576 resultString = g_resultsByBuilder[builder][results.FAILURE_MAP][
currentResultArray[results.RLE.VALUE]]; |
| 563 indexToReplaceCurrentResult += currentResultArray[results.RLE.LE
NGTH]; | 577 indexToReplaceCurrentResult += currentResultArray[results.RLE.LE
NGTH]; |
| 564 } else { | 578 } else { |
| 565 resultString = results.NO_DATA; | 579 resultString = results.NO_DATA; |
| 566 indexToReplaceCurrentResult += buildNumbers.length; | 580 indexToReplaceCurrentResult += buildNumbers.length; |
| 567 } | 581 } |
| 568 } | 582 } |
| 569 | 583 |
| 570 if (i > indexToReplaceCurrentTime) { | 584 if (i > indexToReplaceCurrentTime) { |
| 571 currentTimeArray = times.shift(); | 585 currentTimeArray = times.shift(); |
| 572 var currentTime = 0; | 586 currentTime = 0; |
| 573 if (currentResultArray) { | 587 if (currentResultArray) { |
| 574 currentTime = currentTimeArray[results.RLE.VALUE]; | 588 currentTime = currentTimeArray[results.RLE.VALUE]; |
| 575 indexToReplaceCurrentTime += currentTimeArray[results.RLE.LENGTH]; | 589 indexToReplaceCurrentTime += currentTimeArray[results.RLE.LENGTH]; |
| 576 } else | 590 } else |
| 577 indexToReplaceCurrentTime += buildNumbers.length; | 591 indexToReplaceCurrentTime += buildNumbers.length; |
| 578 | |
| 579 innerHTML = currentTime || ' '; | |
| 580 } | 592 } |
| 581 | 593 |
| 582 html += '<td title="' + resultString + '. Click for more info." class="r
esults ' + classNameForFailureString(resultString) + | 594 var revision = parseInt( |
| 583 '" onclick=\'showPopupForBuild(event, "' + builder + '",' + i + ',"' +
test.test + '")\'>' + innerHTML; | 595 g_resultsByBuilder[builder][revisionType][i], 10); |
| 596 |
| 597 // Locate the empty cell corresponding to this blink revision. |
| 598 var cell = undefined; |
| 599 for (var index = 0; index < cells.length; index++) { |
| 600 if (cells[index].revision == revision && !cells[index].html) { |
| 601 cell = cells[index]; |
| 602 break; |
| 603 } |
| 604 } |
| 605 |
| 606 cell.className = classNameForFailureString(resultString); |
| 607 cell.hasResult = |
| 608 resultString !== results.NO_DATA && resultString !== results.NOTRUN; |
| 609 cell.html = '<td' |
| 610 + ' title="' + resultString + '. Click for more info."' |
| 611 + ' class="results ' + cell.className + '"' |
| 612 + ' onclick=\'showPopupForBuild(event,' |
| 613 + ' "' + builder + '",' + i + ',"' + test.test + '")\'>' |
| 614 + (currentTime || (cell.hasResult ? '' : '?')) + '</td>'; |
| 584 } | 615 } |
| 616 |
| 617 populateEmptyCells(cells); |
| 618 |
| 619 for (var index = 0; index < cells.length; index++) |
| 620 html += cells[index].html; |
| 621 |
| 585 return html; | 622 return html; |
| 586 } | 623 } |
| 587 | 624 |
| 625 // Fill in cells where no test data is available with a question mark. |
| 626 // If the next and previous runs were equal, an "interpolated" result is shown. |
| 627 function populateEmptyCells(cells) |
| 628 { |
| 629 for (var index = 1; index < cells.length; index++) { |
| 630 var prevCell = cells[index - 1]; |
| 631 cells[index].nextClassName = |
| 632 prevCell.hasResult ? prevCell.className : prevCell.nextClassName; |
| 633 } |
| 634 |
| 635 for (var index = cells.length - 2; index >= 0; --index) { |
| 636 var nextCell = cells[index + 1]; |
| 637 cells[index].prevClassName = |
| 638 nextCell.hasResult ? nextCell.className : nextCell.prevClassName; |
| 639 } |
| 640 |
| 641 cells.forEach(function(cell) { |
| 642 if (!cell.html) { |
| 643 var interpolateResult = |
| 644 cell.nextClassName && cell.nextClassName == cell.prevClassName; |
| 645 cell.className = interpolateResult ? cell.nextClassName : "NODATA"; |
| 646 cell.html = '<td' |
| 647 + ' title="Unknown result. Did not run tests."' |
| 648 + ' onclick=\'showPopupForInterpolatedResult(event,' |
| 649 + ' ' + cell.revision + ')\'' |
| 650 + ' class="results interpolatedResult ' + cell.className + '"' |
| 651 + ' >?</td>'; |
| 652 } |
| 653 }); |
| 654 } |
| 655 |
| 588 function shouldShowTest(testResult) | 656 function shouldShowTest(testResult) |
| 589 { | 657 { |
| 590 if (!g_history.isLayoutTestResults()) | 658 if (!g_history.isLayoutTestResults()) |
| 591 return true; | 659 return true; |
| 592 | 660 |
| 593 if (testResult.expectations == 'WONTFIX') | 661 if (testResult.expectations == 'WONTFIX') |
| 594 return g_history.dashboardSpecificState.showWontFix; | 662 return g_history.dashboardSpecificState.showWontFix; |
| 595 | 663 |
| 596 if (testResult.expectations == results.SKIP) | 664 if (testResult.expectations == results.SKIP) |
| 597 return g_history.dashboardSpecificState.showSkip; | 665 return g_history.dashboardSpecificState.showSkip; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 var bugHtml; | 710 var bugHtml; |
| 643 if (string.startsWith(bug, 'Bug(')) | 711 if (string.startsWith(bug, 'Bug(')) |
| 644 bugHtml = bug; | 712 bugHtml = bug; |
| 645 else | 713 else |
| 646 bugHtml = '<a href="http://' + bug + '">' + bug + '</a>'; | 714 bugHtml = '<a href="http://' + bug + '">' + bug + '</a>'; |
| 647 html += '<div>' + bugHtml + '</div>' | 715 html += '<div>' + bugHtml + '</div>' |
| 648 }); | 716 }); |
| 649 return html; | 717 return html; |
| 650 } | 718 } |
| 651 | 719 |
| 652 function htmlForSingleTestRow(test, showBuilderNames) | 720 function htmlForSingleTestRow(test, showBuilderNames, revisions) |
| 653 { | 721 { |
| 654 var headers = tableHeaders(); | 722 var headers = tableHeaders(); |
| 655 var html = ''; | 723 var html = ''; |
| 656 for (var i = 0; i < headers.length; i++) { | 724 for (var i = 0; i < headers.length; i++) { |
| 657 var header = headers[i]; | 725 var header = headers[i]; |
| 658 if (string.startsWith(header, 'test') || string.startsWith(header, 'buil
der')) { | 726 if (string.startsWith(header, 'test') || string.startsWith(header, 'buil
der')) { |
| 659 var testCellClassName = 'test-link' + (showBuilderNames ? ' builder-
name' : ''); | 727 var testCellClassName = 'test-link' + (showBuilderNames ? ' builder-
name' : ''); |
| 660 var testCellHTML = showBuilderNames ? test.builder : '<span class="l
ink" onclick="g_history.setQueryParameter(\'tests\',\'' + test.test +'\');">' +
test.test + '</span>'; | 728 var testCellHTML = showBuilderNames ? test.builder : '<span class="l
ink" onclick="g_history.setQueryParameter(\'tests\',\'' + test.test +'\');">' +
test.test + '</span>'; |
| 661 html += '<tr><td class="' + testCellClassName + '">' + testCellHTML; | 729 html += '<tr><td class="' + testCellClassName + '">' + testCellHTML; |
| 662 } else if (string.startsWith(header, 'bugs')) | 730 } else if (string.startsWith(header, 'bugs')) |
| 663 // FIXME: linkify bugs. | 731 // FIXME: linkify bugs. |
| 664 html += '<td class=options-container>' + (linkifyBugs(test.bugs) ||
createBugHTML(test)); | 732 html += '<td class=options-container>' + (linkifyBugs(test.bugs) ||
createBugHTML(test)); |
| 665 else if (string.startsWith(header, 'expectations')) | 733 else if (string.startsWith(header, 'expectations')) |
| 666 html += '<td class=options-container>' + test.expectations; | 734 html += '<td class=options-container>' + test.expectations; |
| 667 else if (string.startsWith(header, 'slowest')) | 735 else if (string.startsWith(header, 'slowest')) |
| 668 html += '<td>' + (test.slowestTime ? test.slowestTime + 's' : ''); | 736 html += '<td>' + (test.slowestTime ? test.slowestTime + 's' : ''); |
| 669 else if (string.startsWith(header, 'flakiness')) | 737 else if (string.startsWith(header, 'flakiness')) |
| 670 html += htmlForTestResults(test); | 738 html += htmlForTestResults(test, revisions); |
| 671 } | 739 } |
| 672 return html; | 740 return html; |
| 673 } | 741 } |
| 674 | 742 |
| 675 function sortColumnFromTableHeader(headerText) | 743 function sortColumnFromTableHeader(headerText) |
| 676 { | 744 { |
| 677 return headerText.split(' ', 1)[0]; | 745 return headerText.split(' ', 1)[0]; |
| 678 } | 746 } |
| 679 | 747 |
| 680 function htmlForTableColumnHeader(headerName, opt_fillColSpan) | 748 function htmlForTableColumnHeader(headerName, opt_fillColSpan) |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 776 sortFunctionGetter = numericSort; | 844 sortFunctionGetter = numericSort; |
| 777 resultsProperty = 'slowestTime'; | 845 resultsProperty = 'slowestTime'; |
| 778 } else { | 846 } else { |
| 779 sortFunctionGetter = alphanumericCompare; | 847 sortFunctionGetter = alphanumericCompare; |
| 780 resultsProperty = column; | 848 resultsProperty = column; |
| 781 } | 849 } |
| 782 | 850 |
| 783 tests.sort(sortFunctionGetter(resultsProperty, order == BACKWARD)); | 851 tests.sort(sortFunctionGetter(resultsProperty, order == BACKWARD)); |
| 784 } | 852 } |
| 785 | 853 |
| 854 // Return an array of revisions across all builders such that all of a builder's |
| 855 // builds have a unique entry in the list. The currently selected group |
| 856 // (e.g., @ToT Chromium) determines which revision type is not collapsed. |
| 857 // Note that revisions may not be unique: a single builder can have two runs at |
| 858 // the same blink revision but different chrome revisions which will result in |
| 859 // multiple entries of the same blink revision. |
| 860 function collapsedRevisionList(testResults) |
| 861 { |
| 862 // FIXME: Support other revision types instead of just chrome/blink. |
| 863 var revisionType = g_history.isBlinkGroup() ? |
| 864 results.BLINK_REVISIONS : results.CHROME_REVISIONS; |
| 865 |
| 866 var revisionsCountedSet = {}; |
| 867 for (var resultIndex = 0; resultIndex < testResults.length; resultIndex++) { |
| 868 var builder = testResults[resultIndex].builder; |
| 869 var build = g_resultsByBuilder[builder]; |
| 870 var buildNumbers = build.buildNumbers; |
| 871 var builderRevisionsCountedSet = {}; |
| 872 for (var i = 0; i < buildNumbers.length; i++) { |
| 873 var revision = build[revisionType][i]; |
| 874 builderRevisionsCountedSet[revision] = |
| 875 (builderRevisionsCountedSet[revision] || 0) + 1; |
| 876 } |
| 877 |
| 878 // Join builder's revisions with the total revisions for all builders. |
| 879 for (var revision in builderRevisionsCountedSet) |
| 880 revisionsCountedSet[revision] = Math.max(revisionsCountedSet[revisio
n] || 0, builderRevisionsCountedSet[revision]); |
| 881 } |
| 882 |
| 883 var revisionsArray = []; |
| 884 for (var revision in revisionsCountedSet) { |
| 885 for (var i = revisionsCountedSet[revision] - 1; i >= 0; --i) |
| 886 revisionsArray.push(revision); |
| 887 } |
| 888 |
| 889 revisionsArray.sort(function(a, b) { |
| 890 return (b - a); |
| 891 }); |
| 892 return revisionsArray; |
| 893 } |
| 894 |
| 786 function htmlForIndividualTestOnAllBuilders(test) | 895 function htmlForIndividualTestOnAllBuilders(test) |
| 787 { | 896 { |
| 788 processTestRunsForAllBuilders(); | 897 processTestRunsForAllBuilders(); |
| 789 | 898 |
| 790 var testResults = g_testToResultsMap[test]; | 899 var testResults = g_testToResultsMap[test]; |
| 791 if (!testResults) | 900 if (!testResults) |
| 792 return '<div class="not-found">Test not found. Either it does not exist,
is skipped or passes on all recorded runs.</div>'; | 901 return '<div class="not-found">Test not found. Either it does not exist,
is skipped or passes on all recorded runs.</div>'; |
| 793 | 902 |
| 794 var html = ''; | 903 var html = ''; |
| 795 var shownBuilders = []; | 904 var shownBuilders = []; |
| 905 var revisions = collapsedRevisionList(testResults); |
| 796 for (var j = 0; j < testResults.length; j++) { | 906 for (var j = 0; j < testResults.length; j++) { |
| 797 shownBuilders.push(testResults[j].builder); | 907 shownBuilders.push(testResults[j].builder); |
| 798 var showBuilderNames = true; | 908 var showBuilderNames = true; |
| 799 html += htmlForSingleTestRow(testResults[j], showBuilderNames); | 909 html += htmlForSingleTestRow(testResults[j], showBuilderNames, revisions
); |
| 800 } | 910 } |
| 801 | 911 |
| 802 var skippedBuilders = [] | 912 var skippedBuilders = [] |
| 803 for (builder in currentBuilders()) { | 913 for (builder in currentBuilders()) { |
| 804 if (shownBuilders.indexOf(builder) == -1) | 914 if (shownBuilders.indexOf(builder) == -1) |
| 805 skippedBuilders.push(builder); | 915 skippedBuilders.push(builder); |
| 806 } | 916 } |
| 807 | 917 |
| 808 var skippedBuildersHtml = ''; | 918 var skippedBuildersHtml = ''; |
| 809 if (skippedBuilders.length) { | 919 if (skippedBuilders.length) { |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1254 { | 1364 { |
| 1255 processTestRunsForBuilder(builderName); | 1365 processTestRunsForBuilder(builderName); |
| 1256 | 1366 |
| 1257 var filteredResults = g_perBuilderFailures[builderName].filter(shouldShowTes
t); | 1367 var filteredResults = g_perBuilderFailures[builderName].filter(shouldShowTes
t); |
| 1258 sortTests(filteredResults, g_history.dashboardSpecificState.sortColumn, g_hi
story.dashboardSpecificState.sortOrder); | 1368 sortTests(filteredResults, g_history.dashboardSpecificState.sortColumn, g_hi
story.dashboardSpecificState.sortOrder); |
| 1259 | 1369 |
| 1260 var testsHTML = ''; | 1370 var testsHTML = ''; |
| 1261 if (filteredResults.length) { | 1371 if (filteredResults.length) { |
| 1262 var tableRowsHTML = ''; | 1372 var tableRowsHTML = ''; |
| 1263 var showBuilderNames = false; | 1373 var showBuilderNames = false; |
| 1374 var revisions = collapsedRevisionList(filteredResults); |
| 1264 for (var i = 0; i < filteredResults.length; i++) | 1375 for (var i = 0; i < filteredResults.length; i++) |
| 1265 tableRowsHTML += htmlForSingleTestRow(filteredResults[i], showBuilde
rNames) | 1376 tableRowsHTML += htmlForSingleTestRow(filteredResults[i], showBuilde
rNames, revisions); |
| 1266 testsHTML = htmlForTestTable(tableRowsHTML); | 1377 testsHTML = htmlForTestTable(tableRowsHTML); |
| 1267 } else { | 1378 } else { |
| 1268 if (g_history.isLayoutTestResults()) | 1379 if (g_history.isLayoutTestResults()) |
| 1269 testsHTML += '<div>Fill in one of the text inputs or checkboxes abov
e to show failures.</div>'; | 1380 testsHTML += '<div>Fill in one of the text inputs or checkboxes abov
e to show failures.</div>'; |
| 1270 else | 1381 else |
| 1271 testsHTML += '<div>No tests have failed!</div>'; | 1382 testsHTML += '<div>No tests have failed!</div>'; |
| 1272 } | 1383 } |
| 1273 | 1384 |
| 1274 var html = htmlForNavBar(); | 1385 var html = htmlForNavBar(); |
| 1275 | 1386 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1380 // escape key | 1491 // escape key |
| 1381 hideLegend(); | 1492 hideLegend(); |
| 1382 ui.popup.hide(); | 1493 ui.popup.hide(); |
| 1383 } | 1494 } |
| 1384 }, false); | 1495 }, false); |
| 1385 | 1496 |
| 1386 window.addEventListener('load', function() { | 1497 window.addEventListener('load', function() { |
| 1387 resourceLoader = new loader.Loader(); | 1498 resourceLoader = new loader.Loader(); |
| 1388 resourceLoader.load(); | 1499 resourceLoader.load(); |
| 1389 }, false); | 1500 }, false); |
| OLD | NEW |