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

Side by Side Diff: webkit/tools/layout_tests/flakiness_dashboard.html

Issue 215019: Dashboard UI changes.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 11 years, 3 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 <!DOCTYPE HTML> 1 <!DOCTYPE HTML>
2 <html> 2 <html>
3 3
4 <head> 4 <head>
5 <title>Webkit Layout Test History</title> 5 <title>Webkit Layout Test History</title>
6 <script> 6 <script>
7 var pageLoadStartTime = Date.now(); 7 var pageLoadStartTime = Date.now();
8 </script> 8 </script>
9 <style> 9 <style>
10 body { 10 body {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 text-align: center; 81 text-align: center;
82 } 82 }
83 #legend { 83 #legend {
84 position: fixed; 84 position: fixed;
85 top: 5px; 85 top: 5px;
86 right: 5px; 86 right: 5px;
87 width: 130px; 87 width: 130px;
88 border: 2px solid grey; 88 border: 2px solid grey;
89 background-color: white; 89 background-color: white;
90 } 90 }
91 #legend * { 91 #legend-contents * {
92 margin: 3px; 92 margin: 3px;
93 padding: 0 2px; 93 padding: 0 2px;
94 } 94 }
95 body > div > :not(#legend) { 95 body > div > :not(#legend) {
96 margin-right: 145px; 96 margin-right: 145px;
97 } 97 }
98 #builders * { 98 #builders * {
99 margin: 0 5px; 99 margin: 0 5px;
100 display: inline-block; 100 display: inline-block;
101 white-space: nowrap; 101 white-space: nowrap;
(...skipping 22 matching lines...) Expand all
124 } 124 }
125 .F { 125 .F {
126 background-color: #e98080; 126 background-color: #e98080;
127 } 127 }
128 .O { 128 .O {
129 background-color: #69f; 129 background-color: #69f;
130 } 130 }
131 .merge { 131 .merge {
132 background-color: green; 132 background-color: green;
133 } 133 }
134 :not(#legend) > .merge { 134 :not(#legend-contents) > .merge {
135 width: 1px; 135 width: 1px;
136 } 136 }
137 .separator { 137 .separator {
138 border: 1px solid lightgray; 138 border: 1px solid lightgray;
139 height: 0px; 139 height: 0px;
140 } 140 }
141 .different-platform { 141 .different-platform {
142 color: gray; 142 color: gray;
143 font-size: 10px; 143 font-size: 10px;
144 } 144 }
(...skipping 17 matching lines...) Expand all
162 position: fixed; 162 position: fixed;
163 top: 0; 163 top: 0;
164 left: 0; 164 left: 0;
165 background-color: yellow; 165 background-color: yellow;
166 padding: 5px; 166 padding: 5px;
167 text-align: center; 167 text-align: center;
168 font-weight: bold; 168 font-weight: bold;
169 } 169 }
170 #popup { 170 #popup {
171 background-color: white; 171 background-color: white;
172 overflow: hidden;
173 width: 250px;
174 z-index: 1; 172 z-index: 1;
175 position: absolute; 173 position: absolute;
176 border: 3px solid grey; 174 border: 3px solid grey;
177 padding: 3px; 175 padding: 3px;
178 -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5); 176 -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5);
179 -moz-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5); 177 -moz-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5);
180 -webkit-border-radius: 5px; 178 -webkit-border-radius: 5px;
181 -moz-border-radius: 5px; 179 -moz-border-radius: 5px;
182 } 180 }
183 #popup > * { 181 #popup > * {
arv (Not doing code reviews) 2009/09/18 02:35:24 remove empty rule?
184 width: 100%;
185 } 182 }
186 #popup > ul { 183 #popup > ul {
187 margin: 0; 184 margin: 0;
188 padding-left: 20px; 185 padding-left: 20px;
189 } 186 }
190 </style> 187 </style>
191 188
192 <script> 189 <script>
193 /** 190 /**
194 * @fileoverview Creates a dashboard for multiple runs of a given set of tests 191 * @fileoverview Creates a dashboard for multiple runs of a given set of tests
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 'flakiness (numbers are runtimes in seconds)']; 234 'flakiness (numbers are runtimes in seconds)'];
238 var perBuilderPlatformAndBuildType = {}; 235 var perBuilderPlatformAndBuildType = {};
239 var perBuilderFailures = {}; 236 var perBuilderFailures = {};
240 // Map of builder to arrays of tests that are listed in the expectations file 237 // Map of builder to arrays of tests that are listed in the expectations file
241 // but have for that builder. 238 // but have for that builder.
242 var perBuilderWithExpectationsButNoFailures = {}; 239 var perBuilderWithExpectationsButNoFailures = {};
243 // Map of builder to arrays of paths that are skipped. This shows the raw 240 // Map of builder to arrays of paths that are skipped. This shows the raw
244 // path used in test_expectations.txt rather than the test path since we 241 // path used in test_expectations.txt rather than the test path since we
245 // don't actually have any data here for skipped tests. 242 // don't actually have any data here for skipped tests.
246 var perBuilderSkippedPaths = {}; 243 var perBuilderSkippedPaths = {};
244 // Maps test path to an array of {builder, testResults} objects.
245 var testToResultsMap = {};
247 246
248 // Generic utility functions. 247 // Generic utility functions.
249 function $(id) { 248 function $(id) {
250 return document.getElementById(id); 249 return document.getElementById(id);
251 } 250 }
252 251
253 function stringContains(a, b) { 252 function stringContains(a, b) {
254 return a.indexOf(b) != -1; 253 return a.indexOf(b) != -1;
255 } 254 }
256 255
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 'Webkit Mac10.5 (dbg)(3)': 'webkit-dbg-mac5-3' 332 'Webkit Mac10.5 (dbg)(3)': 'webkit-dbg-mac5-3'
334 }; 333 };
335 var builderBase = 'http://build.chromium.org/buildbot/'; 334 var builderBase = 'http://build.chromium.org/buildbot/';
336 } 335 }
337 336
338 var defaultStateValues = { 337 var defaultStateValues = {
339 sortOrder: BACKWARD, 338 sortOrder: BACKWARD,
340 sortColumn: 'flakiness', 339 sortColumn: 'flakiness',
341 showWontFix: false, 340 showWontFix: false,
342 showCorrectExpectations: false, 341 showCorrectExpectations: false,
342 showLegend: true,
343 showFlaky: true, 343 showFlaky: true,
344 showSkipped: false, 344 showSkipped: false,
345 maxResults: 200, 345 maxResults: 200,
346 testType: 'layout_test_results' 346 testType: 'layout_test_results'
347 }; 347 };
348 348
349 function fillDefaultStateValues() { 349 function fillDefaultStateValues() {
350 for (var state in defaultStateValues) { 350 for (var state in defaultStateValues) {
351 if (!(state in currentState)) 351 if (!(state in currentState))
352 currentState[state] = defaultStateValues[state]; 352 currentState[state] = defaultStateValues[state];
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 function() { 411 function() {
412 return value.match(/^\d+$/) 412 return value.match(/^\d+$/)
413 }); 413 });
414 414
415 return true; 415 return true;
416 416
417 case 'debug': 417 case 'debug':
418 case 'showWontFix': 418 case 'showWontFix':
419 case 'showCorrectExpectations': 419 case 'showCorrectExpectations':
420 case 'showFlaky': 420 case 'showFlaky':
421 case 'showLegend':
421 currentState[key] = value == 'true'; 422 currentState[key] = value == 'true';
422 423
423 return true; 424 return true;
424 425
425 default: 426 default:
426 return false; 427 return false;
427 } 428 }
428 } 429 }
429 430
430 // Keep the location around for detecting changes to hash arguments 431 // Keep the location around for detecting changes to hash arguments
431 // manually typed into the URL bar. 432 // manually typed into the URL bar.
432 var oldLocation; 433 var oldLocation;
433 434
434 function parseAllParameters() { 435 function parseAllParameters() {
435 oldLocation = window.location.href; 436 oldLocation = window.location.href;
436 parseParameters(window.location.hash.substring(1), 437 parseParameters(window.location.hash.substring(1),
437 handleValidHashParameter); 438 handleValidHashParameter);
438 fillDefaultStateValues(); 439 fillDefaultStateValues();
439 } 440 }
440 441
441 parseAllParameters(); 442 parseAllParameters();
442 443
443 // Append JSON script elements. 444 // Append JSON script elements.
444 var resultsByBuilder = {}; 445 var resultsByBuilder = {};
445 // Maps test path to an array of {builder, testResults} objects.
446 var testToResultsMap = {};
447 var expectationsByTest = {}; 446 var expectationsByTest = {};
448 function ADD_RESULTS(builds) { 447 function ADD_RESULTS(builds) {
449 for (var builderName in builds) { 448 for (var builderName in builds) {
450 if (builderName != 'version') 449 if (builderName != 'version')
451 resultsByBuilder[builderName] = builds[builderName]; 450 resultsByBuilder[builderName] = builds[builderName];
452 } 451 }
453 452
454 generatePage(); 453 generatePage();
455 } 454 }
456 455
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
786 } 785 }
787 786
788 var rawTest = resultsByBuilder[builderName].tests[test]; 787 var rawTest = resultsByBuilder[builderName].tests[test];
789 resultsForTest.rawTimes = rawTest.times; 788 resultsForTest.rawTimes = rawTest.times;
790 var rawResults = rawTest.results; 789 var rawResults = rawTest.results;
791 resultsForTest.rawResults = rawResults; 790 resultsForTest.rawResults = rawResults;
792 resultsForTest.flips = rawResults.length - 1; 791 resultsForTest.flips = rawResults.length - 1;
793 792
794 var unexpectedExpectations = []; 793 var unexpectedExpectations = [];
795 var resultsMap = {} 794 var resultsMap = {}
796 for (var i = 0; i < rawResults.length; i++) { 795 var numResultsSeen = 0;
796 for (var i = 0;
797 i < rawResults.length && numResultsSeen < currentState.maxResults;
798 i++) {
799 numResultsSeen += rawResults[i][0];
797 var expectation = getExpectationsFileStringForResult(rawResults[i][1]); 800 var expectation = getExpectationsFileStringForResult(rawResults[i][1]);
798 resultsMap[expectation] = true; 801 resultsMap[expectation] = true;
799 } 802 }
800 803
801 var expectationsArray = resultsForTest.expectations ? 804 var expectationsArray = resultsForTest.expectations ?
802 resultsForTest.expectations.split(' ') : []; 805 resultsForTest.expectations.split(' ') : [];
803 var extraExpectations = expectationsArray.filter( 806 var extraExpectations = expectationsArray.filter(
804 function(element) { 807 function(element) {
805 return element && !resultsMap[element] && 808 return element && !resultsMap[element] &&
806 !stringContains(element, 'BUG'); 809 !stringContains(element, 'BUG');
807 }); 810 });
808 811
809 var missingExpectations = []; 812 var missingExpectations = [];
810 for (var result in resultsMap) { 813 for (var result in resultsMap) {
811 var hasExpectation = false; 814 var hasExpectation = false;
812 for (var i = 0; i < expectationsArray.length; i++) { 815 for (var i = 0; i < expectationsArray.length; i++) {
813 if (result == expectationsArray[i]) 816 if (result == expectationsArray[i])
814 hasExpectation = true; 817 hasExpectation = true;
815 } 818 }
816 if (!hasExpectation) 819 if (!hasExpectation)
817 missingExpectations.push(result); 820 missingExpectations.push(result);
818 } 821 }
819 822
820 var times = resultsByBuilder[builderName].tests[test].times; 823 var times = resultsByBuilder[builderName].tests[test].times;
821 for (var i = 0; i < times.length; i++) { 824 var numResultsSeen = 0;
825 for (var i = 0;
826 i < times.length && numResultsSeen < currentState.maxResults;
827 i++) {
828 numResultsSeen += times[i][0];
822 resultsForTest.slowestTime = Math.max(resultsForTest.slowestTime, 829 resultsForTest.slowestTime = Math.max(resultsForTest.slowestTime,
823 times[i][1]); 830 times[i][1]);
824 } 831 }
825 832
826 if (resultsForTest.slowestTime && !resultsMap['TIMEOUT'] && 833 if (resultsForTest.slowestTime && !resultsMap['TIMEOUT'] &&
827 (!resultsForTest.expectations || 834 (!resultsForTest.expectations ||
828 !stringContains(resultsForTest.expectations, 'TIMEOUT')) && 835 !stringContains(resultsForTest.expectations, 'TIMEOUT')) &&
829 (!resultsForTest.modifiers || 836 (!resultsForTest.modifiers ||
830 !stringContains(resultsForTest.modifiers, 'SLOW'))) { 837 !stringContains(resultsForTest.modifiers, 'SLOW'))) {
831 missingExpectations.push('SLOW'); 838 missingExpectations.push('SLOW');
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 */ 877 */
871 function getHtmlForBugs(bugs) { 878 function getHtmlForBugs(bugs) {
872 bugs = bugs.replace(/BUG(\d{4})(\ |$)/g, externalBugReplaceValue); 879 bugs = bugs.replace(/BUG(\d{4})(\ |$)/g, externalBugReplaceValue);
873 bugs = bugs.replace(/BUG(\d{5})(\ |$)/g, externalBugReplaceValue); 880 bugs = bugs.replace(/BUG(\d{5})(\ |$)/g, externalBugReplaceValue);
874 bugs = bugs.replace(/BUG(\d{6})(\ |$)/g, internalBugReplaceValue); 881 bugs = bugs.replace(/BUG(\d{6})(\ |$)/g, internalBugReplaceValue);
875 bugs = bugs.replace(/BUG(\d{7})(\ |$)/g, internalBugReplaceValue); 882 bugs = bugs.replace(/BUG(\d{7})(\ |$)/g, internalBugReplaceValue);
876 return bugs; 883 return bugs;
877 } 884 }
878 885
879 function getLinkHTMLToOpenWindow(url, text) { 886 function getLinkHTMLToOpenWindow(url, text) {
880 return '<li class=link onclick="window.open(\'' + url + '\')">' + text + 887 return '<div class=link onclick="window.open(\'' + url + '\')">' + text +
881 '</li>'; 888 '</div>';
889 }
890
891 function createBlameListHTML(revisions, index, urlBase, separator, repo) {
892 var thisRevision = revisions[index];
893 if (!thisRevision)
894 return '';
895
896 var previousRevision = revisions[index + 1];
897 if (previousRevision && previousRevision != thisRevision) {
898 previousRevision++;
899 return getLinkHTMLToOpenWindow(
900 urlBase + thisRevision + separator + previousRevision,
901 repo + ' blamelist r' + previousRevision + ':r' + thisRevision);
902 } else {
903 return 'At ' + repo + ' revision: ' + thisRevision;
904 }
882 } 905 }
883 906
884 function showPopupForBuild(e, builder, index) { 907 function showPopupForBuild(e, builder, index) {
885 var html = ''; 908 var html = '';
886 909
887 var time = resultsByBuilder[builder].secondsSinceEpoch[index]; 910 var time = resultsByBuilder[builder].secondsSinceEpoch[index];
888 if (time) { 911 if (time) {
889 var date = new Date(time * 1000); 912 var date = new Date(time * 1000);
890 html += date.toLocaleDateString() + ' ' + date.toLocaleTimeString(); 913 html += date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
891 } 914 }
892 915
893 html += '<ul>'; 916 html += '<ul><li>' +
917 createBlameListHTML(resultsByBuilder[builder].webkitRevision, index,
918 'http://trac.webkit.org/log/?rev=', '&stop_rev=', 'WebKit') +
919 '</li><li>' +
920 createBlameListHTML(resultsByBuilder[builder].chromeRevision, index,
921 'http://build.chromium.org/buildbot/perf/dashboard/ui/' +
922 'changelog.html?url=/trunk/src&mode=html&range=', ':', 'Chrome') +
923 '</li>';
894 924
895 var webkitRevision = resultsByBuilder[builder].webkitRevision; 925 var chromeRevision = resultsByBuilder[builder].chromeRevision[index];
896 var thisWebkitRevision = webkitRevision[index]; 926 if (chromeRevision) {
897 if (thisWebkitRevision) { 927 html += '<li><a href="' + TEST_RESULTS_BASE_PATH + builders[builder] +
898 var previousWebkitRevision = webkitRevision[index + 1] || 928 '/' + chromeRevision + '/layout-test-results.zip' +
899 thisWebkitRevision; 929 '">layout-test-results.zip</a></li>';
900 html += getLinkHTMLToOpenWindow('http://trac.webkit.org/log/?rev=' +
901 thisWebkitRevision + '&stop_rev=' + previousWebkitRevision,
902 'WebKit blamelist r' + previousWebkitRevision + ':r' +
903 thisWebkitRevision);
904 }
905
906 var chromeRevision = resultsByBuilder[builder].chromeRevision;
907 var thisChromeRevision = chromeRevision[index];
908 if (thisChromeRevision) {
909 var previousChromeRevision = chromeRevision[index + 1] ||
910 thisChromeRevision;
911 html += getLinkHTMLToOpenWindow(
912 'http://build.chromium.org/buildbot/perf/dashboard/ui/' +
913 'changelog.html?url=/trunk/src&mode=html&range=' +
914 previousChromeRevision + ':' + thisChromeRevision,
915 'Chrome blamelist r' + previousChromeRevision + ':r' +
916 thisChromeRevision) +
917 getLinkHTMLToOpenWindow(TEST_RESULTS_BASE_PATH + builders[builder] +
918 '/' + thisChromeRevision + '/layout-test-results.zip',
919 'layout-test-results.zip');
920 } 930 }
921 931
922 var buildNumbers = resultsByBuilder[builder].buildNumbers; 932 var buildNumbers = resultsByBuilder[builder].buildNumbers;
923 html += getLinkHTMLToOpenWindow(BUILDERS_BASE_PATH + builder + '/builds/' + 933 html += '<li>' +
924 buildNumbers[index], 'Build log and blamelist') + '</ul>'; 934 getLinkHTMLToOpenWindow(BUILDERS_BASE_PATH + builder + '/builds/' +
935 buildNumbers[index], 'Build log and blamelist') + '</li></ul>';
925 936
926 showPopup(e, html); 937 showPopup(e, html);
927 } 938 }
928 939
940 function showPopupForTest(e, test) {
941 showPopup(e, getHTMLForIndividulTestOnAllBuilders(test));
942 }
943
929 function getHtmlForTestResults(test, builder) { 944 function getHtmlForTestResults(test, builder) {
930 var html = ''; 945 var html = '';
931 var results = test.rawResults.concat(); 946 var results = test.rawResults.concat();
932 var times = test.rawTimes.concat(); 947 var times = test.rawTimes.concat();
933 var buildNumbers = resultsByBuilder[builder].buildNumbers; 948 var buildNumbers = resultsByBuilder[builder].buildNumbers;
934 949
935 var indexToReplaceCurrentResult = -1; 950 var indexToReplaceCurrentResult = -1;
936 var indexToReplaceCurrentTime = -1; 951 var indexToReplaceCurrentTime = -1;
937 var currentResultArray, currentTimeArray, currentResult, innerHTML; 952 var currentResultArray, currentTimeArray, currentResult, innerHTML;
938 var maxIndex = Math.min(buildNumbers.length, currentState.maxResults); 953 var maxIndex = Math.min(buildNumbers.length, currentState.maxResults);
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1017 * Returns whether this tests results match the heuristic for new tests that 1032 * Returns whether this tests results match the heuristic for new tests that
1018 * have been fixed. Specifically, a new test that fails a couple 1033 * have been fixed. Specifically, a new test that fails a couple
1019 * times and then passes from then on would have results like PPPPFFFFNNNNN. 1034 * times and then passes from then on would have results like PPPPFFFFNNNNN.
1020 * Where that middle part can be a series of F's, S's or I's for the 1035 * Where that middle part can be a series of F's, S's or I's for the
1021 * different types of failures. 1036 * different types of failures.
1022 */ 1037 */
1023 function isFixedTest(testResult) { 1038 function isFixedTest(testResult) {
1024 if (testResult.isFixedTest === undefined) { 1039 if (testResult.isFixedTest === undefined) {
1025 var results = testResult.rawResults; 1040 var results = testResult.rawResults;
1026 var isFixedTest = results[0][1] == 'P'; 1041 var isFixedTest = results[0][1] == 'P';
1027 if (isFixedTest && results.length > 1) { 1042 var numResults = results[0][0];
1028 var secondResult = results[1][1]; 1043 if (numResults < currentState.maxResults &&
1029 isFixedTest = secondResult == 'S' || secondResult == 'F' || 1044 isFixedTest && results.length > 1) {
1030 secondResult == 'I'; 1045 // We don't care what the value of the second set of results is, just
1046 // how many results there are.
1047 numResults += results[1][0];
1031 } 1048 }
1032 if (isFixedTest && results.length > 2) { 1049 if (numResults < currentState.maxResults &&
1050 isFixedTest && results.length > 2) {
1033 isFixedTest = results.length == 3 && results[2][1] == 'N'; 1051 isFixedTest = results.length == 3 && results[2][1] == 'N';
1034 } 1052 }
1035 testResult.isFixedTest = isFixedTest; 1053 testResult.isFixedTest = isFixedTest;
1036 } 1054 }
1037 return testResult.isFixedTest; 1055 return testResult.isFixedTest;
1038 } 1056 }
1039 1057
1040 /** 1058 /**
1041 * Returns whether we should exclude test results from the test table. 1059 * Returns whether we should exclude test results from the test table.
1042 * Note that we never want to exclude tests when we're in the individual 1060 * Note that we never want to exclude tests when we're in the individual
(...skipping 21 matching lines...) Expand all
1064 if (shouldHideTest(test)) { 1082 if (shouldHideTest(test)) {
1065 // The innerHTML call is considerably faster if we exclude the rows for 1083 // The innerHTML call is considerably faster if we exclude the rows for
1066 // items we're not showing than if we hide them using display:none. 1084 // items we're not showing than if we hide them using display:none.
1067 return ''; 1085 return '';
1068 } 1086 }
1069 1087
1070 // If opt_isCrossBuilderView is true, we're just viewing a single test 1088 // If opt_isCrossBuilderView is true, we're just viewing a single test
1071 // with results for many builders, so the first column is builder names 1089 // with results for many builders, so the first column is builder names
1072 // instead of test paths. 1090 // instead of test paths.
1073 var testCellHTML = opt_isCrossBuilderView ? builder : 1091 var testCellHTML = opt_isCrossBuilderView ? builder :
1074 '<span class="link" onclick="setState(\'tests\', \'' + test.test + 1092 '<span class="link" onclick="showPopupForTest(event, \'' + test.test +
1075 '\');return false;">' + test.test + '</span>'; 1093 '\');return false;">' + test.test + '</span>';
1076 1094
1077 return '<tr class="' + 1095 return '<tr class="' +
1078 (test.meetsExpectations ? '' : 'wrong-expectations') + 1096 (test.meetsExpectations ? '' : 'wrong-expectations') +
1079 // TODO(ojan): If a test is a chrome/ or a pending/ test, point to 1097 // TODO(ojan): If a test is a chrome/ or a pending/ test, point to
1080 // src.chromium.org instead of trac.webkit.org. 1098 // src.chromium.org instead of trac.webkit.org.
1081 '"><td class=test-link>' + testCellHTML + 1099 '"><td class=test-link>' + testCellHTML +
1082 '</td><td class=options-container>' + test.bugsHTML + 1100 '</td><td class=options-container>' + test.bugsHTML +
1083 '</td><td class=options-container>' + test.modifiersHTML + 1101 '</td><td class=options-container>' + test.modifiersHTML +
1084 '</td><td class=options-container>' + test.expectationsHTML + 1102 '</td><td class=options-container>' + test.expectationsHTML +
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
1200 } 1218 }
1201 1219
1202 tableHeaders.shift(); 1220 tableHeaders.shift();
1203 if (currentState.tests) { 1221 if (currentState.tests) {
1204 tableHeaders.unshift('builder'); 1222 tableHeaders.unshift('builder');
1205 generatePageForIndividualTests(currentState.tests.split(',')); 1223 generatePageForIndividualTests(currentState.tests.split(','));
1206 } else { 1224 } else {
1207 tableHeaders.unshift('test'); 1225 tableHeaders.unshift('test');
1208 generatePageForBuilder(currentState.builder); 1226 generatePageForBuilder(currentState.builder);
1209 } 1227 }
1228
1229 $('max-results-input').value = currentState.maxResults;
1230 updateLegendDisplay();
1231 }
1232
1233 function getHTMLForIndividulTestOnAllBuilders(test) {
1234 for (var builder in builders)
1235 processTestRunsForBuilder(builder);
1236
1237 var testResults = testToResultsMap[test];
1238 if (testResults && testResults.length) {
1239 var tracURL = TEST_URL_BASE_PATH + test
1240 var html = getLinkHTMLToOpenWindow(tracURL, tracURL) +
1241 '<div><b>If a builder is not listed, that means the builder does ' +
1242 'run that tst or all runs of the test passed.</b></div>';
arv (Not doing code reviews) 2009/09/18 02:35:24 s/tst/test/
1243
1244 for (var j = 0; j < testResults.length; j++) {
1245 html += getHTMLForSingleTestRow(testResults[j].results,
1246 testResults[j].builder, true);
1247 }
1248 return getHTMLForTestTable(html);
1249 } else {
1250 return '<div class="not-found">Test not found. Either it does not ' +
1251 'exist or it passes on all platforms.</div>';
1252 }
1210 } 1253 }
1211 1254
1212 function generatePageForIndividualTests(tests) { 1255 function generatePageForIndividualTests(tests) {
1213 // TODO: Add link to trac from individual test page 1256 var html = getHTMLForNavBar();
1214 // TODO: Make links on builder pages to tests be to the individual test page
1215 for (var builder in builders)
1216 processTestRunsForBuilder(builder);
1217
1218 var html = getHTMLForNavBar() +
1219 '<b>IF A BUILDER IS NOT LISTED THAT MEANS THE ' +
1220 'BUILDER DOES NOT RUN THAT TEST OR ALL RUNS OF THE TEST PASSED.</b>';
1221
1222 for (var i = 0; i < tests.length; i++) { 1257 for (var i = 0; i < tests.length; i++) {
1223 html += '<h2>' + tests[i] + '</h2>'; 1258 html += '<h2>' + tests[i] + '</h2>' +
1224 1259 getHTMLForIndividulTestOnAllBuilders(tests[i]);
1225 var testResults = testToResultsMap[tests[i]];
1226 if (testResults && testResults.length) {
1227 var tableRowsHTML = '';
1228 for (var j = 0; j < testResults.length; j++) {
1229 tableRowsHTML += getHTMLForSingleTestRow(testResults[j].results,
1230 testResults[j].builder, true);
1231 }
1232 html += getHTMLForTestTable(tableRowsHTML);
1233 } else {
1234 html +='<div class="not-found">Test not found. Either it does not ' +
1235 'exist or it passes on all platforms.</div>';
1236 }
1237 } 1260 }
1238 setFullPageHTML(html); 1261 setFullPageHTML(html);
1239 1262
1240 $('tests-input').value = currentState.tests; 1263 $('tests-input').value = currentState.tests;
1241 } 1264 }
1242 1265
1243 function getHTMLForNavBar(opt_builderName) { 1266 function getHTMLForNavBar(opt_builderName) {
1244 var html = '<div id=builders>'; 1267 var html = '<div id=builders>';
1245 for (var builder in builders) { 1268 for (var builder in builders) {
1246 var className = builder == opt_builderName ? 'current-builder' : 'link'; 1269 var className = builder == opt_builderName ? 'current-builder' : 'link';
1247 html += '<span class=' + className + 1270 html += '<span class=' + className +
1248 ' onclick=\'setState("builder", "' + builder + '")\'>' + 1271 ' onclick=\'setState("builder", "' + builder + '")\'>' +
1249 builder + '</span>'; 1272 builder + '</span>';
1250 } 1273 }
1251 html += '</div>' + 1274 html += '</div>' +
1252 '<form id=tests-form ' + 1275 '<form id=tests-form ' +
1253 'onsubmit="setState(\'tests\', tests.value);return false;">' + 1276 'onsubmit="setState(\'tests\', tests.value);return false;">' +
1254 '<div>Show tests on all platforms (slow): </div><input name=tests ' + 1277 '<div>Show tests on all platforms (slow): </div><input name=tests ' +
1255 'placeholder="LayoutTests/foo/bar.html,LayoutTests/foo/baz.html" ' + 1278 'placeholder="LayoutTests/foo/bar.html,LayoutTests/foo/baz.html" ' +
1256 'id=tests-input></form><div id="loading-ui">LOADING...</div>' + 1279 'id=tests-input></form>' +
1257 '<div id=legend>'; 1280 '<form id=max-results-form ' +
1281 'onsubmit="setState(\'maxResults\', maxResults.value);return false;"' +
1282 '><span>Number of results to show (max=500): </span>' +
1283 '<input name=maxResults id=max-results-input></form>' +
1284 '<div id="loading-ui">LOADING...</div><div id=legend>' +
1285 '<div id=legend-toggle>' + getLinkHTMLToToggleLegendDisplay() +
1286 '</div><div id=legend-contents>';
1258 1287
1259 for (var expectation in EXPECTATIONS_MAP) { 1288 for (var expectation in EXPECTATIONS_MAP) {
1260 html += '<div class=' + expectation + '>' + 1289 html += '<div class=' + expectation + '>' +
1261 EXPECTATIONS_MAP[expectation] + '</div>'; 1290 EXPECTATIONS_MAP[expectation] + '</div>';
1262 } 1291 }
1263 return html + '<div class=wrong-expectations>WRONG EXPECTATIONS</div>' + 1292 return html + '<div class=wrong-expectations>WRONG EXPECTATIONS</div>' +
1264 '<div class=merge>WEBKIT MERGE</div></div>'; 1293 '<div class=merge>WEBKIT MERGE</div></div></div>';
1265 } 1294 }
1266 1295
1267 function getLinkHTMLToToggleState(key, linkText) { 1296 function getLinkHTMLToToggleState(key, linkText) {
1268 var isTrue = currentState[key]; 1297 var isTrue = currentState[key];
1269 return '<span class=link onclick="setState(\'' + key + '\', ' + !isTrue + 1298 return '<span class=link onclick="setState(\'' + key + '\', ' + !isTrue +
1270 ')">' + (isTrue ? 'Hide' : 'Show') + ' ' + linkText + '</span>'; 1299 ')">' + (isTrue ? 'Hide' : 'Show') + ' ' + linkText + '</span>';
1271 } 1300 }
1272 1301
1273 function generatePageForBuilder(builderName) { 1302 function generatePageForBuilder(builderName) {
1274 processTestRunsForBuilder(builderName); 1303 processTestRunsForBuilder(builderName);
1275 1304
1276 var tableRowsHTML = ''; 1305 var tableRowsHTML = '';
1277 var results = perBuilderFailures[builderName]; 1306 var results = perBuilderFailures[builderName];
1278 sortTests(results, currentState.sortColumn, currentState.sortOrder); 1307 sortTests(results, currentState.sortColumn, currentState.sortOrder);
1279 for (var i = 0; i < results.length; i++) { 1308 for (var i = 0; i < results.length; i++) {
1280 tableRowsHTML += getHTMLForSingleTestRow(results[i], builderName); 1309 tableRowsHTML += getHTMLForSingleTestRow(results[i], builderName);
1281 } 1310 }
1282 1311
1283 var testsHTML = tableRowsHTML ? getHTMLForTestTable(tableRowsHTML) : 1312 var testsHTML = tableRowsHTML ? getHTMLForTestTable(tableRowsHTML) :
1284 '<div>No tests. Try showing tests with correct expectations.</div>'; 1313 '<div>No tests. Try showing tests with correct expectations.</div>';
1285 1314
1286 var html = getHTMLForNavBar(builderName) + 1315 var html = getHTMLForNavBar(builderName) +
1287 getHTMLForTestsWithExpectationsButNoFailures(builderName) + 1316 getHTMLForTestsWithExpectationsButNoFailures(builderName) +
1288 '<h2>Failing tests</h2><div>' + 1317 '<h2>Failing tests</h2><div>' +
1289 getLinkHTMLToToggleState('showWontFix', 'WONTFIX tests') + ' | ' + 1318 getLinkHTMLToToggleState('showWontFix', 'WONTFIX tests') + ' | ' +
1290 getLinkHTMLToToggleState('showCorrectExpectations', 1319 getLinkHTMLToToggleState('showCorrectExpectations',
1291 'tests with correct expectations') + ' | ' + 1320 'tests with correct expectations') + ' | ' +
1292 getLinkHTMLToToggleState('showFlaky', 'flaky tests') + ' | ' + 1321 getLinkHTMLToToggleState('showFlaky', 'flaky tests') + ' | ' +
1293 '<form id=max-results-form ' + 1322 '<b>All columns are sortable. | ' +
1294 'onsubmit="setState(\'maxResults\', maxResults.value);return false;"' +
1295 '><span>Number of results to show: </span>' +
1296 '<input name=maxResults id=max-results-input></form> | ' +
1297 '<b>All columns are sortable. | Skipped tests are not listed. | ' +
1298 'Flakiness reader order is newer --> older runs.</b></div>' + 1323 'Flakiness reader order is newer --> older runs.</b></div>' +
1299 testsHTML; 1324 testsHTML;
1300 1325
1301 setFullPageHTML(html); 1326 setFullPageHTML(html);
1302 1327
1303 var ths = document.getElementsByTagName('th'); 1328 var ths = document.getElementsByTagName('th');
1304 for (var i = 0; i < ths.length; i++) { 1329 for (var i = 0; i < ths.length; i++) {
1305 ths[i].addEventListener('click', changeSort, false); 1330 ths[i].addEventListener('click', changeSort, false);
1306 ths[i].className = "sortable"; 1331 ths[i].className = "sortable";
1307 } 1332 }
1333 }
1308 1334
1309 $('max-results-input').value = currentState.maxResults; 1335 function getLinkHTMLToToggleLegendDisplay() {
1336 return getLinkHTMLToToggleState('showLegend', 'Legend');
1337 }
1338
1339 function updateLegendDisplay() {
1340 $('legend-contents').style.display = currentState.showLegend ? '' : 'none';
1341 }
1342
1343 /**
1344 * Clears the processed test state for perBuilderFailures.
1345 * TODO(ojan): This really should probably clear all the state we've
1346 * generated, but that's kind of a pain given the many global objects state is
1347 * stored in. There should probably be one global generatedState
1348 * object that all the generated state lives off of.
1349 */
1350 function clearProcessedTestState() {
1351 for (var builder in builders) {
1352 delete perBuilderFailures[builder];
1353 delete perBuilderPlatformAndBuildType[builder];
1354 delete perBuilderWithExpectationsButNoFailures[builder];
1355 delete perBuilderSkippedPaths[builder];
1356 }
1357
1358 for (var key in testToResultsMap) {
1359 delete testToResultsMap[key]
1360 }
1310 } 1361 }
1311 1362
1312 /** 1363 /**
1313 * Sets the page state and regenerates the page. Takes varargs of key, value 1364 * Sets the page state and regenerates the page. Takes varargs of key, value
1314 * pairs. 1365 * pairs.
1315 */ 1366 */
1316 function setState(key, value) { 1367 function setState(key, value) {
1317 for (var i = 0; i < arguments.length; i = i + 2) { 1368 for (var i = 0; i < arguments.length; i = i + 2) {
1318 var key = arguments[i]; 1369 var key = arguments[i];
1319 if (key != 'tests') { 1370 if (key != 'tests' && key != 'maxResults') {
1320 delete currentState.tests; 1371 delete currentState.tests;
1321 } 1372 }
1322 1373
1374 if (key == 'maxResults') {
1375 // Processing the test results JSON makes assumptions about the number
1376 // of results to show. This makes changing the number of maxResults slow
1377 // but is considerably easier than refactoring all the other code.
1378 clearProcessedTestState();
1379 }
1380
1323 currentState[key] = arguments[i + 1]; 1381 currentState[key] = arguments[i + 1];
1324 } 1382 }
1325 window.location.replace(getPermaLinkURL()); 1383 window.location.replace(getPermaLinkURL());
1326 handleLocationChange(); 1384 if (key == 'showLegend') {
1385 saveStoredWindowLocation();
1386 updateLegendDisplay();
1387 $('legend-toggle').innerHTML = getLinkHTMLToToggleLegendDisplay();
1388 } else {
1389 handleLocationChange();
1390 }
1391 }
1392
1393 function saveStoredWindowLocation() {
1394 oldLocation = window.location.href;
1327 } 1395 }
1328 1396
1329 function handleLocationChange() { 1397 function handleLocationChange() {
1330 $('loading-ui').style.display = 'block'; 1398 $('loading-ui').style.display = 'block';
1331 setTimeout(function() { 1399 setTimeout(function() {
1332 oldLocation = window.location.href; 1400 saveStoredWindowLocation();
1333 generatePage(); 1401 generatePage();
1334 }, 0); 1402 }, 0);
1335 } 1403 }
1336 1404
1337 function getPermaLinkURL() { 1405 function getPermaLinkURL() {
1338 return window.location.pathname + '#' + joinParameters(currentState); 1406 return window.location.pathname + '#' + joinParameters(currentState);
1339 } 1407 }
1340 1408
1341 function joinParameters(stateObject) { 1409 function joinParameters(stateObject) {
1342 var state = []; 1410 var state = [];
(...skipping 20 matching lines...) Expand all
1363 document.body.appendChild(popup); 1431 document.body.appendChild(popup);
1364 } 1432 }
1365 1433
1366 // Set html first so that we can get accurate size metrics on the popup. 1434 // Set html first so that we can get accurate size metrics on the popup.
1367 popup.innerHTML = html; 1435 popup.innerHTML = html;
1368 1436
1369 var targetRect = e.target.getBoundingClientRect(); 1437 var targetRect = e.target.getBoundingClientRect();
1370 1438
1371 var x = Math.min(targetRect.left - 10, 1439 var x = Math.min(targetRect.left - 10,
1372 document.documentElement.clientWidth - popup.offsetWidth); 1440 document.documentElement.clientWidth - popup.offsetWidth);
1441 x = Math.max(0, x);
1373 popup.style.left = x + document.body.scrollLeft + 'px'; 1442 popup.style.left = x + document.body.scrollLeft + 'px';
1374 1443
1375 var y = targetRect.top + targetRect.height; 1444 var y = targetRect.top + targetRect.height;
1376 if (y + popup.offsetHeight > document.documentElement.clientHeight) { 1445 if (y + popup.offsetHeight > document.documentElement.clientHeight) {
1377 y = targetRect.top - popup.offsetHeight; 1446 y = targetRect.top - popup.offsetHeight;
1378 } 1447 }
1448 y = Math.max(0, y);
1379 popup.style.top = y + document.body.scrollTop + 'px'; 1449 popup.style.top = y + document.body.scrollTop + 'px';
1380 } 1450 }
1381 1451
1382 document.onmousedown = function(e) { 1452 document.onmousedown = function(e) {
1383 // Clear the open popup, unless the click was inside the popup. 1453 // Clear the open popup, unless the click was inside the popup.
1384 var popup = $('popup'); 1454 var popup = $('popup');
1385 if (popup && e.target != popup && 1455 if (popup && e.target != popup &&
1386 !(popup.compareDocumentPosition(e.target) & 16)) { 1456 !(popup.compareDocumentPosition(e.target) & 16)) {
1387 hidePopup(); 1457 hidePopup();
1388 } 1458 }
1389 }; 1459 };
1390 1460
1391 window.onload = function() { 1461 window.onload = function() {
1392 // This doesn't seem totally accurate as there is a race between 1462 // This doesn't seem totally accurate as there is a race between
1393 // onload firing and the last script tag being executed. 1463 // onload firing and the last script tag being executed.
1394 logTime('Time to load JS', pageLoadStartTime); 1464 logTime('Time to load JS', pageLoadStartTime);
1395 setInterval(function() { 1465 setInterval(function() {
1396 if (oldLocation != window.location.href) { 1466 if (oldLocation != window.location.href) {
1397 parseAllParameters(); 1467 parseAllParameters();
1398 handleLocationChange(); 1468 handleLocationChange();
1399 } 1469 }
1400 }, 100); 1470 }, 100);
1401 } 1471 }
1402 </script> 1472 </script>
1403 </head> 1473 </head>
1404 1474
1405 <body></body> 1475 <body></body>
1406 </html> 1476 </html>
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698