Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(356)

Side by Side Diff: Tools/TestResultServer/static-dashboards/flakiness_dashboard.js

Issue 359533004: Group flakiness results by blink revision (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Address reviewer comments Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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, blinkRevisions)
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 var cells = [];
561 for (var index = 0; index < blinkRevisions.length; index++)
562 cells.push({revision: blinkRevisions[index]});
563
554 var indexToReplaceCurrentResult = -1; 564 var indexToReplaceCurrentResult = -1;
555 var indexToReplaceCurrentTime = -1; 565 var indexToReplaceCurrentTime = -1;
556 for (var i = 0; i < buildNumbers.length; i++) { 566 for (var i = 0; i < buildNumbers.length; i++) {
557 var currentResultArray, currentTimeArray, innerHTML, resultString; 567 var currentResultArray, currentTimeArray, currentTime, resultString;
558 568
559 if (i > indexToReplaceCurrentResult) { 569 if (i > indexToReplaceCurrentResult) {
560 currentResultArray = testResults.shift(); 570 currentResultArray = testResults.shift();
561 if (currentResultArray) { 571 if (currentResultArray) {
562 resultString = g_resultsByBuilder[builder][results.FAILURE_MAP][ currentResultArray[results.RLE.VALUE]]; 572 resultString = g_resultsByBuilder[builder][results.FAILURE_MAP][ currentResultArray[results.RLE.VALUE]];
563 indexToReplaceCurrentResult += currentResultArray[results.RLE.LE NGTH]; 573 indexToReplaceCurrentResult += currentResultArray[results.RLE.LE NGTH];
564 } else { 574 } else {
565 resultString = results.NO_DATA; 575 resultString = results.NO_DATA;
566 indexToReplaceCurrentResult += buildNumbers.length; 576 indexToReplaceCurrentResult += buildNumbers.length;
567 } 577 }
568 } 578 }
569 579
570 if (i > indexToReplaceCurrentTime) { 580 if (i > indexToReplaceCurrentTime) {
571 currentTimeArray = times.shift(); 581 currentTimeArray = times.shift();
572 var currentTime = 0;
ojan 2014/07/14 23:40:39 I think deleting this caused the bug we found earl
pdr. 2014/07/17 14:50:28 Ack. Fixed.
573 if (currentResultArray) { 582 if (currentResultArray) {
574 currentTime = currentTimeArray[results.RLE.VALUE]; 583 currentTime = currentTimeArray[results.RLE.VALUE];
575 indexToReplaceCurrentTime += currentTimeArray[results.RLE.LENGTH]; 584 indexToReplaceCurrentTime += currentTimeArray[results.RLE.LENGTH];
576 } else 585 } else
577 indexToReplaceCurrentTime += buildNumbers.length; 586 indexToReplaceCurrentTime += buildNumbers.length;
578
579 innerHTML = currentTime || '&nbsp;';
580 } 587 }
581 588
582 html += '<td title="' + resultString + '. Click for more info." class="r esults ' + classNameForFailureString(resultString) + 589 var revision = parseInt(
583 '" onclick=\'showPopupForBuild(event, "' + builder + '",' + i + ',"' + test.test + '")\'>' + innerHTML; 590 g_resultsByBuilder[builder][results.BLINK_REVISIONS][i], 10);
591
592 // Locate the empty cell corresponding to this blink revision.
593 var cell = undefined;
ojan 2014/07/14 23:40:38 nit: use find and get rid of the comment. var cel
pdr. 2014/07/17 14:50:28 Unfortunately, it looks like find isn't available
594 for (var index = 0; index < cells.length; index++) {
595 if (cells[index].revision == revision && !cells[index].html) {
596 cell = cells[index];
597 break;
598 }
599 }
600
601 cell.className = classNameForFailureString(resultString);
602 cell.hasResult =
603 resultString !== results.NO_DATA && resultString !== results.NOTRUN;
604 cell.html = '<td'
605 + ' title="' + resultString + '. Click for more info."'
606 + ' class="results ' + cell.className + '"'
607 + ' onclick=\'showPopupForBuild(event,'
608 + ' "' + builder + '",' + i + ',"' + test.test + '")\'>'
609 + (currentTime || (cell.hasResult ? '&nbsp;' : '?')) + '</td>';
ojan 2014/07/14 23:40:38 As discussed in person, lets show a #bbb question
pdr. 2014/07/17 14:50:28 Done.
584 } 610 }
611
612 populateEmptyCells(cells);
613
614 for (var index = 0; index < cells.length; index++)
615 html += cells[index].html;
616
585 return html; 617 return html;
586 } 618 }
587 619
620 // Fill in cells where no test data is available with a question mark.
621 // If the next and previous runs were equal, an "interpolated" result is shown.
622 function populateEmptyCells(cells)
623 {
624 for (var index = 1; index < cells.length; index++) {
625 var prevCell = cells[index - 1];
626 cells[index].nextClassName =
627 prevCell.hasResult ? prevCell.className : prevCell.nextClassName;
628 }
629
630 for (var index = cells.length - 2; index >= 0; --index) {
631 var nextCell = cells[index + 1];
632 cells[index].prevClassName =
633 nextCell.hasResult ? nextCell.className : nextCell.prevClassName;
634 }
635
636 cells.forEach(function(cell) {
637 if (!cell.html) {
638 var interpolateResult =
639 cell.nextClassName && cell.nextClassName == cell.prevClassName;
640 cell.className = interpolateResult ? cell.nextClassName : "NODATA";
641 cell.html = '<td'
642 + ' title="Unknown result. Did not run tests."'
643 + ' onclick=\'showPopupForInterpolatedResult(event,'
644 + ' ' + cell.revision + ')\''
645 + ' class="results interpolatedResults ' + cell.className + '"'
646 + ' >?</td>';
647 }
648 });
649 }
650
588 function shouldShowTest(testResult) 651 function shouldShowTest(testResult)
589 { 652 {
590 if (!g_history.isLayoutTestResults()) 653 if (!g_history.isLayoutTestResults())
591 return true; 654 return true;
592 655
593 if (testResult.expectations == 'WONTFIX') 656 if (testResult.expectations == 'WONTFIX')
594 return g_history.dashboardSpecificState.showWontFix; 657 return g_history.dashboardSpecificState.showWontFix;
595 658
596 if (testResult.expectations == results.SKIP) 659 if (testResult.expectations == results.SKIP)
597 return g_history.dashboardSpecificState.showSkip; 660 return g_history.dashboardSpecificState.showSkip;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 var bugHtml; 705 var bugHtml;
643 if (string.startsWith(bug, 'Bug(')) 706 if (string.startsWith(bug, 'Bug('))
644 bugHtml = bug; 707 bugHtml = bug;
645 else 708 else
646 bugHtml = '<a href="http://' + bug + '">' + bug + '</a>'; 709 bugHtml = '<a href="http://' + bug + '">' + bug + '</a>';
647 html += '<div>' + bugHtml + '</div>' 710 html += '<div>' + bugHtml + '</div>'
648 }); 711 });
649 return html; 712 return html;
650 } 713 }
651 714
652 function htmlForSingleTestRow(test, showBuilderNames) 715 function htmlForSingleTestRow(test, showBuilderNames, revisions)
653 { 716 {
654 var headers = tableHeaders(); 717 var headers = tableHeaders();
655 var html = ''; 718 var html = '';
656 for (var i = 0; i < headers.length; i++) { 719 for (var i = 0; i < headers.length; i++) {
657 var header = headers[i]; 720 var header = headers[i];
658 if (string.startsWith(header, 'test') || string.startsWith(header, 'buil der')) { 721 if (string.startsWith(header, 'test') || string.startsWith(header, 'buil der')) {
659 var testCellClassName = 'test-link' + (showBuilderNames ? ' builder- name' : ''); 722 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>'; 723 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; 724 html += '<tr><td class="' + testCellClassName + '">' + testCellHTML;
662 } else if (string.startsWith(header, 'bugs')) 725 } else if (string.startsWith(header, 'bugs'))
663 // FIXME: linkify bugs. 726 // FIXME: linkify bugs.
664 html += '<td class=options-container>' + (linkifyBugs(test.bugs) || createBugHTML(test)); 727 html += '<td class=options-container>' + (linkifyBugs(test.bugs) || createBugHTML(test));
665 else if (string.startsWith(header, 'expectations')) 728 else if (string.startsWith(header, 'expectations'))
666 html += '<td class=options-container>' + test.expectations; 729 html += '<td class=options-container>' + test.expectations;
667 else if (string.startsWith(header, 'slowest')) 730 else if (string.startsWith(header, 'slowest'))
668 html += '<td>' + (test.slowestTime ? test.slowestTime + 's' : ''); 731 html += '<td>' + (test.slowestTime ? test.slowestTime + 's' : '');
669 else if (string.startsWith(header, 'flakiness')) 732 else if (string.startsWith(header, 'flakiness'))
670 html += htmlForTestResults(test); 733 html += htmlForTestResults(test, revisions);
671 } 734 }
672 return html; 735 return html;
673 } 736 }
674 737
675 function sortColumnFromTableHeader(headerText) 738 function sortColumnFromTableHeader(headerText)
676 { 739 {
677 return headerText.split(' ', 1)[0]; 740 return headerText.split(' ', 1)[0];
678 } 741 }
679 742
680 function htmlForTableColumnHeader(headerName, opt_fillColSpan) 743 function htmlForTableColumnHeader(headerName, opt_fillColSpan)
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 sortFunctionGetter = numericSort; 839 sortFunctionGetter = numericSort;
777 resultsProperty = 'slowestTime'; 840 resultsProperty = 'slowestTime';
778 } else { 841 } else {
779 sortFunctionGetter = alphanumericCompare; 842 sortFunctionGetter = alphanumericCompare;
780 resultsProperty = column; 843 resultsProperty = column;
781 } 844 }
782 845
783 tests.sort(sortFunctionGetter(resultsProperty, order == BACKWARD)); 846 tests.sort(sortFunctionGetter(resultsProperty, order == BACKWARD));
784 } 847 }
785 848
849 // Return an array of the unique blink build revisions across all builders.
850 // Each entry will correspond to one column of results. Note that the revisions
851 // may not be unique: a builder can test the same blink revision but with
852 // different chrome revisions and this will result in multiple entries of a
853 // single blink revision in the returned array.
854 function blinkBuildRevisions(testResults)
ojan 2014/07/14 23:40:39 As discussed in person, we should only do this for
pdr. 2014/07/17 14:50:28 Done.
855 {
856 var revisionsCountedSet = {};
857 for (var resultIndex = 0; resultIndex < testResults.length; resultIndex++) {
858 var builder = testResults[resultIndex].builder;
859 var build = g_resultsByBuilder[builder];
860 var buildNumbers = build.buildNumbers;
861 var builderRevisionsCountedSet = {};
862 for (var i = 0; i < buildNumbers.length; i++) {
863 var blinkRevision = build[results.BLINK_REVISIONS][i];
864 builderRevisionsCountedSet[blinkRevision] = (builderRevisionsCounted Set[blinkRevision] || 0) + 1;
865 }
866
867 // Join the builder's revisions with the total revisions for all builder s.
868 for (var revision in builderRevisionsCountedSet)
869 revisionsCountedSet[revision] = Math.max(revisionsCountedSet[revisio n] || 0, builderRevisionsCountedSet[revision]);
870 }
871
872 var revisionsArray = [];
873 for (var revision in revisionsCountedSet) {
874 for (var i = revisionsCountedSet[revision] - 1; i >= 0; --i)
875 revisionsArray.push(revision);
876 }
877
878 revisionsArray.sort(function(a, b) {
879 return (b - a);
880 });
881 return revisionsArray;
882 }
883
786 function htmlForIndividualTestOnAllBuilders(test) 884 function htmlForIndividualTestOnAllBuilders(test)
787 { 885 {
788 processTestRunsForAllBuilders(); 886 processTestRunsForAllBuilders();
789 887
790 var testResults = g_testToResultsMap[test]; 888 var testResults = g_testToResultsMap[test];
791 if (!testResults) 889 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>'; 890 return '<div class="not-found">Test not found. Either it does not exist, is skipped or passes on all recorded runs.</div>';
793 891
794 var html = ''; 892 var html = '';
795 var shownBuilders = []; 893 var shownBuilders = [];
894 var blinkRevisions = blinkBuildRevisions(testResults);
796 for (var j = 0; j < testResults.length; j++) { 895 for (var j = 0; j < testResults.length; j++) {
797 shownBuilders.push(testResults[j].builder); 896 shownBuilders.push(testResults[j].builder);
798 var showBuilderNames = true; 897 var showBuilderNames = true;
799 html += htmlForSingleTestRow(testResults[j], showBuilderNames); 898 html += htmlForSingleTestRow(testResults[j], showBuilderNames, blinkRevi sions);
800 } 899 }
801 900
802 var skippedBuilders = [] 901 var skippedBuilders = []
803 for (builder in currentBuilders()) { 902 for (builder in currentBuilders()) {
804 if (shownBuilders.indexOf(builder) == -1) 903 if (shownBuilders.indexOf(builder) == -1)
805 skippedBuilders.push(builder); 904 skippedBuilders.push(builder);
806 } 905 }
807 906
808 var skippedBuildersHtml = ''; 907 var skippedBuildersHtml = '';
809 if (skippedBuilders.length) { 908 if (skippedBuilders.length) {
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after
1254 { 1353 {
1255 processTestRunsForBuilder(builderName); 1354 processTestRunsForBuilder(builderName);
1256 1355
1257 var filteredResults = g_perBuilderFailures[builderName].filter(shouldShowTes t); 1356 var filteredResults = g_perBuilderFailures[builderName].filter(shouldShowTes t);
1258 sortTests(filteredResults, g_history.dashboardSpecificState.sortColumn, g_hi story.dashboardSpecificState.sortOrder); 1357 sortTests(filteredResults, g_history.dashboardSpecificState.sortColumn, g_hi story.dashboardSpecificState.sortOrder);
1259 1358
1260 var testsHTML = ''; 1359 var testsHTML = '';
1261 if (filteredResults.length) { 1360 if (filteredResults.length) {
1262 var tableRowsHTML = ''; 1361 var tableRowsHTML = '';
1263 var showBuilderNames = false; 1362 var showBuilderNames = false;
1363 var blinkRevisions = blinkBuildRevisions(filteredResults);
1264 for (var i = 0; i < filteredResults.length; i++) 1364 for (var i = 0; i < filteredResults.length; i++)
1265 tableRowsHTML += htmlForSingleTestRow(filteredResults[i], showBuilde rNames) 1365 tableRowsHTML += htmlForSingleTestRow(filteredResults[i], showBuilde rNames, blinkRevisions)
1266 testsHTML = htmlForTestTable(tableRowsHTML); 1366 testsHTML = htmlForTestTable(tableRowsHTML);
1267 } else { 1367 } else {
1268 if (g_history.isLayoutTestResults()) 1368 if (g_history.isLayoutTestResults())
1269 testsHTML += '<div>Fill in one of the text inputs or checkboxes abov e to show failures.</div>'; 1369 testsHTML += '<div>Fill in one of the text inputs or checkboxes abov e to show failures.</div>';
1270 else 1370 else
1271 testsHTML += '<div>No tests have failed!</div>'; 1371 testsHTML += '<div>No tests have failed!</div>';
1272 } 1372 }
1273 1373
1274 var html = htmlForNavBar(); 1374 var html = htmlForNavBar();
1275 1375
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1380 // escape key 1480 // escape key
1381 hideLegend(); 1481 hideLegend();
1382 ui.popup.hide(); 1482 ui.popup.hide();
1383 } 1483 }
1384 }, false); 1484 }, false);
1385 1485
1386 window.addEventListener('load', function() { 1486 window.addEventListener('load', function() {
1387 resourceLoader = new loader.Loader(); 1487 resourceLoader = new loader.Loader();
1388 resourceLoader.load(); 1488 resourceLoader.load();
1389 }, false); 1489 }, false);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698