OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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> |
OLD | NEW |