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

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

Issue 195081: Flakiness dashboard changes:... (Closed) Base URL: svn://chrome-svn/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 {
11 font-family: arial; 11 font-family: arial;
12 font-size: 13px; 12 font-size: 13px;
13 } 13 }
14 h2 { 14 h2 {
15 font-size: 16px; 15 font-size: 16px;
16 margin-bottom: .25em; 16 margin-bottom: .25em;
17 } 17 }
18 h3 {
19 font-size: 13px;
20 margin: 0;
21 }
18 #max-results-form { 22 #max-results-form {
19 display: inline; 23 display: inline;
20 } 24 }
21 #max-results-input { 25 #max-results-input {
22 width: 30px; 26 width: 30px;
23 } 27 }
24 #tests-form { 28 #tests-form {
25 display: -webkit-box; 29 display: -webkit-box;
26 } 30 }
27 #tests-form > * { 31 #tests-form > * {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 } 121 }
118 .S { 122 .S {
119 background-color: #c6c; 123 background-color: #c6c;
120 } 124 }
121 .F { 125 .F {
122 background-color: #e98080; 126 background-color: #e98080;
123 } 127 }
124 .O { 128 .O {
125 background-color: #69f; 129 background-color: #69f;
126 } 130 }
131 .merge {
132 background-color: green;
133 }
134 :not(#legend) > .merge {
135 width: 1px;
136 }
127 .separator { 137 .separator {
128 border: 1px solid lightgray; 138 border: 1px solid lightgray;
129 height: 0px; 139 height: 0px;
130 } 140 }
131 .different-platform { 141 .different-platform {
132 color: gray; 142 color: gray;
133 font-size: 10px; 143 font-size: 10px;
134 } 144 }
135 .current-builder { 145 .current-builder {
136 font-weight: bold; 146 font-weight: bold;
137 } 147 }
138 #passing-tests { 148 #passing-tests {
139 -webkit-column-count: 2; 149 -webkit-column-count: 3;
140 -webkit-column-gap: 25px; 150 -webkit-column-gap: 25px;
141 -webkit-column-rule: 1px dashed black; 151 -webkit-column-rule: 1px dashed black;
142 -moz-column-count: 2; 152 -moz-column-count: 3;
143 -moz-column-gap: 25px; 153 -moz-column-gap: 25px;
144 -moz-column-rule: 1px dashed black; 154 -moz-column-rule: 1px dashed black;
145 } 155 }
146 .not-found { 156 .not-found {
147 color: red; 157 color: red;
148 font-size: large; 158 font-size: large;
149 } 159 }
150 #loading-ui { 160 #loading-ui {
151 display: none; 161 display: none;
152 position: fixed; 162 position: fixed;
153 top: 0; 163 top: 0;
154 left: 0; 164 left: 0;
155 background-color: yellow; 165 background-color: yellow;
156 padding: 5px; 166 padding: 5px;
157 text-align: center; 167 text-align: center;
158 font-weight: bold; 168 font-weight: bold;
159 } 169 }
170 #popup {
171 background-color: white;
172 overflow: hidden;
173 width: 250px;
174 z-index: 1;
175 position: absolute;
176 border: 3px solid grey;
177 padding: 3px;
178 -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);
180 -webkit-border-radius: 5px;
181 -moz-border-radius: 5px;
182 }
183 #popup > * {
184 width: 100%;
185 }
186 #popup > ul {
187 margin: 0;
188 padding-left: 20px;
189 }
160 </style> 190 </style>
161 191
162 <script> 192 <script>
163 /** 193 /**
164 * @fileoverview Creates a dashboard for multiple runs of a given set of tests 194 * @fileoverview Creates a dashboard for multiple runs of a given set of tests
165 * on the buildbots. Pulls in JSONP-ish files with the results for running 195 * on the buildbots. Pulls in JSONP-ish files with the results for running
166 * tests on a given builder (i.e. ADD_RESULTS(json_here)) and the expectations 196 * tests on a given builder (i.e. ADD_RESULTS(json_here)) and the expectations
167 * for all tests on all builders (i.e. ADD_EXPECTATIONS(json_here)). 197 * for all tests on all builders (i.e. ADD_EXPECTATIONS(json_here)).
168 * 198 *
169 * This shows flakiness of the tests as well as runtimes for slow tests. 199 * This shows flakiness of the tests as well as runtimes for slow tests.
170 * 200 *
171 * Also, each column in the dashboard is sortable. 201 * Also, each column in the dashboard is sortable.
172 * 202 *
173 * Currently, only webkit tests are supported, but adding other test types 203 * Currently, only webkit tests are supported, but adding other test types
174 * should just require the following steps: 204 * should just require the following steps:
175 * -generate results.json and expectations.json for these tests 205 * -generate results.json and expectations.json for these tests
176 * -copy them to the appropriate location 206 * -copy them to the appropriate location
177 * -add the builder name to the list of builders below. 207 * -add the builder name to the list of builders below.
178 */ 208 */
179 209
180 // CONSTANTS 210 // CONSTANTS
181 var FORWARD = 'forward'; 211 var FORWARD = 'forward';
182 var BACKWARD = 'backward'; 212 var BACKWARD = 'backward';
183 var TEST_URL_BASE_PATH = 213 var TEST_URL_BASE_PATH =
184 'http://trac.webkit.org/projects/webkit/browser/trunk/'; 214 'http://trac.webkit.org/projects/webkit/browser/trunk/';
185 var BUILDERS_BASE_PATH = 215 var BUILDERS_BASE_PATH =
186 'http://build.chromium.org/buildbot/waterfall/builders/'; 216 'http://build.chromium.org/buildbot/waterfall/builders/';
187 var EXPECTATIONS_MAP = { 217 var TEST_RESULTS_BASE_PATH =
188 'T': 'TIMEOUT', 218 'http://build.chromium.org/buildbot/layout_test_results/';
189 'C': 'CRASH', 219 var EXPECTATIONS_MAP = {
190 'P': 'PASS', 220 'T': 'TIMEOUT',
191 'F': 'TEXT FAIL', 221 'C': 'CRASH',
192 'S': 'SIMPLIFIED', 222 'P': 'PASS',
193 'I': 'IMAGE', 223 'F': 'TEXT FAIL',
194 'O': 'OTHER', 224 'S': 'SIMPLIFIED',
195 'N': 'NO DATA' 225 'I': 'IMAGE',
196 }; 226 'O': 'OTHER',
197 var PLATFORMS = {'MAC': 'MAC', 'LINUX': 'LINUX', 'WIN': 'WIN'}; 227 'N': 'NO DATA'
198 var BUILD_TYPES = {'DEBUG': 'DBG', 'RELEASE': 'RELEASE'}; 228 };
229 var PLATFORMS = {'MAC': 'MAC', 'LINUX': 'LINUX', 'WIN': 'WIN'};
230 var BUILD_TYPES = {'DEBUG': 'DBG', 'RELEASE': 'RELEASE'};
199 231
200 // GLOBALS 232 // GLOBALS
201 // The DUMMYVALUE gets shifted off the array in the first call to 233 // The DUMMYVALUE gets shifted off the array in the first call to
202 // generatePage. 234 // generatePage.
203 var tableHeaders = ['DUMMYVALUE', 'bugs', 'modifiers', 'expectations', 235 var tableHeaders = ['DUMMYVALUE', 'bugs', 'modifiers', 'expectations',
204 'missing', 'extra', 'slowest run', 236 'missing', 'extra', 'slowest run',
205 'flakiness (numbers are runtimes in seconds)']; 237 'flakiness (numbers are runtimes in seconds)'];
206 var perBuilderPlatformAndBuildType = {}; 238 var perBuilderPlatformAndBuildType = {};
207 var perBuilderFailures = {}; 239 var perBuilderFailures = {};
208 // Map of builder to arrays of tests that are listed in the expectations file 240 // Map of builder to arrays of tests that are listed in the expectations file
209 // but have for that builder. 241 // but have for that builder.
210 var perBuilderWithExpectationsButNoFailures = {}; 242 var perBuilderWithExpectationsButNoFailures = {};
211 243 // 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
245 // don't actually have any data here for skipped tests.
246 var perBuilderSkippedPaths = {};
212 247
213 // Generic utility functions. 248 // Generic utility functions.
214 function $(id) { 249 function $(id) {
215 return document.getElementById(id); 250 return document.getElementById(id);
216 } 251 }
217 252
218 function stringContains(a, b) { 253 function stringContains(a, b) {
219 return a.indexOf(b) != -1; 254 return a.indexOf(b) != -1;
220 } 255 }
221 256
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 }; 334 };
300 var builderBase = 'http://build.chromium.org/buildbot/'; 335 var builderBase = 'http://build.chromium.org/buildbot/';
301 } 336 }
302 337
303 var defaultStateValues = { 338 var defaultStateValues = {
304 sortOrder: BACKWARD, 339 sortOrder: BACKWARD,
305 sortColumn: 'flakiness', 340 sortColumn: 'flakiness',
306 showWontFix: false, 341 showWontFix: false,
307 showCorrectExpectations: false, 342 showCorrectExpectations: false,
308 showFlaky: true, 343 showFlaky: true,
344 showSkipped: false,
309 maxResults: 200, 345 maxResults: 200,
310 testType: 'layout_test_results' 346 testType: 'layout_test_results'
311 }; 347 };
312 348
313 for (var builder in builders) {
314 defaultStateValues.builder = builder;
315 break;
316 }
317
318 function fillDefaultStateValues() { 349 function fillDefaultStateValues() {
319 // tests has no states with default values.
320 if (currentState.tests)
321 return;
322
323 for (var state in defaultStateValues) { 350 for (var state in defaultStateValues) {
324 if (!(state in currentState)) 351 if (!(state in currentState))
325 currentState[state] = defaultStateValues[state]; 352 currentState[state] = defaultStateValues[state];
326 } 353 }
354
355 if (!currentState.tests && !('builder' in currentState)) {
356 for (var builder in builders) {
357 currentState.builder = builder;
358 break;
359 }
360 }
327 } 361 }
328 362
329 function handleValidHashParameter(key, value) { 363 function handleValidHashParameter(key, value) {
330 switch(key) { 364 switch(key) {
331 case 'testType': 365 case 'testType':
332 validateParameter(currentState, key, value, 366 validateParameter(currentState, key, value,
333 function() { 367 function() {
334 return isValidName(value); 368 return isValidName(value);
335 }); 369 });
336 370
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
595 } 629 }
596 630
597 return allTestsByPlatformAndBuildType[platform][buildType]; 631 return allTestsByPlatformAndBuildType[platform][buildType];
598 } 632 }
599 633
600 /** 634 /**
601 * Adds the given test and path to the appropriate objects depending on 635 * Adds the given test and path to the appropriate objects depending on
602 * whether the modifiers match the builders platform and buildType. 636 * whether the modifiers match the builders platform and buildType.
603 */ 637 */
604 function addTestAndExpectations(test, prefixPath, builder, expectationsMap, 638 function addTestAndExpectations(test, prefixPath, builder, expectationsMap,
605 expectations, testPrefixes) { 639 expectations, testPrefixes, skippedPaths) {
606 var modifiersForBuilder = 640 var modifiersForBuilder =
607 getModifierThatHasPlatformAndBuildType(builder, expectations); 641 getModifierThatHasPlatformAndBuildType(builder, expectations);
608 if (modifiersForBuilder) { 642
609 if (getAllTestsWithSamePlatformAndBuildType(builder)[test]) { 643 if (!modifiersForBuilder)
610 expectationsMap[test] = expectations; 644 return false;
611 testPrefixes[test] = prefixPath; 645
612 } else if (!stringContains(modifiersForBuilder.modifiers, 'SKIP') && 646 if (getAllTestsWithSamePlatformAndBuildType(builder)[test]) {
613 !modifiersForBuilder.expectations.match(/^\s*PASS\s*$/)) { 647 expectationsMap[test] = expectations;
648 testPrefixes[test] = prefixPath;
649 } else if (!stringContains(modifiersForBuilder.modifiers, 'WONTFIX')) {
650
651 if (stringContains(modifiersForBuilder.modifiers, 'SKIP')) {
652 skippedPaths[prefixPath] = true;
653 } else if (!modifiersForBuilder.expectations.match(/^\s*PASS\s*$/)) {
614 // Don't include skip tests here as they'll look the same as a test 654 // Don't include skip tests here as they'll look the same as a test
615 // that passes on all builders. 655 // that passes on all builders.
616 // Also don't include tests that are only expected to pass, e.g. 656 // Also don't include tests that are only expected to pass, e.g.
617 // SLOW : foo/bar/baz.html = PASS 657 // SLOW : foo/bar/baz.html = PASS
618 // TODO(ojan): Should we also exclude WONTFIX tests here? 658 // TODO(ojan): Should we also exclude WONTFIX tests here?
619 perBuilderWithExpectationsButNoFailures[builder].push(test); 659 perBuilderWithExpectationsButNoFailures[builder].push(test);
620 } 660 }
621 return true;
622 } 661 }
623 return false; 662
663 return true;
624 } 664 }
625 665
626 /** 666 /**
627 * Naive check that path points to a directory. 667 * Naive check that path points to a directory.
628 */ 668 */
629 function isDirectory(path) { 669 function isDirectory(path) {
630 return !stringContains(path, '.') 670 return !stringContains(path, '.')
631 } 671 }
632 672
633 function addHTMLToIndividualOptionsArray(array, html, isCurrentPlatform) { 673 function addHTMLToIndividualOptionsArray(array, html, isCurrentPlatform) {
(...skipping 24 matching lines...) Expand all
658 var allTests = getAllTests(); 698 var allTests = getAllTests();
659 699
660 var expectationsMap = {}; 700 var expectationsMap = {};
661 for (var test in allTests) { 701 for (var test in allTests) {
662 if (expectationsByTest[test]) 702 if (expectationsByTest[test])
663 expectationsMap[test] = expectationsByTest[test]; 703 expectationsMap[test] = expectationsByTest[test];
664 } 704 }
665 705
666 var testPrefixes = {}; 706 var testPrefixes = {};
667 perBuilderWithExpectationsButNoFailures[builderName] = []; 707 perBuilderWithExpectationsButNoFailures[builderName] = [];
708 var skippedPaths = {};
668 for (var path in expectationsByTest) { 709 for (var path in expectationsByTest) {
669 var expectations = expectationsByTest[path]; 710 var expectations = expectationsByTest[path];
670 if (!isDirectory(path) && 711 if (!isDirectory(path) &&
671 addTestAndExpectations(path, path, builderName, expectationsMap, 712 addTestAndExpectations(path, path, builderName, expectationsMap,
672 expectations, testPrefixes)) { 713 expectations, testPrefixes, skippedPaths)) {
673 continue; 714 continue;
674 } 715 }
675 // Test path doesn't match a specific test, see if it prefix matches 716 // Test path doesn't match a specific test, see if it prefix matches
676 // any test. 717 // any test.
677 for (var test in allTests) { 718 for (var test in allTests) {
678 if (stringContains(test, path) && 719 if (stringContains(test, path) &&
679 (!testPrefixes[test] || 720 (!testPrefixes[test] ||
680 !stringContains(testPrefixes[test], path))) { 721 !stringContains(testPrefixes[test], path))) {
681 addTestAndExpectations(test, path, builderName, expectationsMap, 722 addTestAndExpectations(test, path, builderName, expectationsMap,
682 expectations, testPrefixes); 723 expectations, testPrefixes, skippedPaths);
683 } 724 }
684 } 725 }
685 } 726 }
727
728 perBuilderSkippedPaths[builderName] = [];
729 for (var path in skippedPaths) {
730 perBuilderSkippedPaths[builderName].push(path);
731 }
732 perBuilderSkippedPaths[builderName].sort();
686 perBuilderWithExpectationsButNoFailures[builderName].sort(); 733 perBuilderWithExpectationsButNoFailures[builderName].sort();
687 734
688 var allTestsForThisBuilder = resultsByBuilder[builderName].tests; 735 var allTestsForThisBuilder = resultsByBuilder[builderName].tests;
689 for (var test in allTestsForThisBuilder) { 736 for (var test in allTestsForThisBuilder) {
690 var resultsForTest = createResultsObjectForTest(test); 737 var resultsForTest = createResultsObjectForTest(test);
691 738
692 if (expectationsMap[test] && expectationsMap[test].length) { 739 if (expectationsMap[test] && expectationsMap[test].length) {
693 var expectationsArray = expectationsMap[test]; 740 var expectationsArray = expectationsMap[test];
694 var htmlArrays = {}; 741 var htmlArrays = {};
695 htmlArrays.expectations = []; 742 htmlArrays.expectations = [];
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
769 if (!hasExpectation) 816 if (!hasExpectation)
770 missingExpectations.push(result); 817 missingExpectations.push(result);
771 } 818 }
772 819
773 var times = resultsByBuilder[builderName].tests[test].times; 820 var times = resultsByBuilder[builderName].tests[test].times;
774 for (var i = 0; i < times.length; i++) { 821 for (var i = 0; i < times.length; i++) {
775 resultsForTest.slowestTime = Math.max(resultsForTest.slowestTime, 822 resultsForTest.slowestTime = Math.max(resultsForTest.slowestTime,
776 times[i][1]); 823 times[i][1]);
777 } 824 }
778 825
779 if (resultsForTest.slowestTime && 826 if (resultsForTest.slowestTime && !resultsMap['TIMEOUT'] &&
780 (!resultsForTest.expectations || 827 (!resultsForTest.expectations ||
781 !stringContains(resultsForTest.expectations, 'TIMEOUT')) && 828 !stringContains(resultsForTest.expectations, 'TIMEOUT')) &&
782 (!resultsForTest.modifiers || 829 (!resultsForTest.modifiers ||
783 !stringContains(resultsForTest.modifiers, 'SLOW'))) { 830 !stringContains(resultsForTest.modifiers, 'SLOW'))) {
784 missingExpectations.push('SLOW'); 831 missingExpectations.push('SLOW');
785 } 832 }
786 833
787 resultsForTest.meetsExpectations = 834 resultsForTest.meetsExpectations =
788 !missingExpectations.length && !extraExpectations.length; 835 !missingExpectations.length && !extraExpectations.length;
789 resultsForTest.missing = missingExpectations.sort().join(' '); 836 resultsForTest.missing = missingExpectations.sort().join(' ');
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
822 * are internal google bugs. 869 * are internal google bugs.
823 */ 870 */
824 function getHtmlForBugs(bugs) { 871 function getHtmlForBugs(bugs) {
825 bugs = bugs.replace(/BUG(\d{4})(\ |$)/g, externalBugReplaceValue); 872 bugs = bugs.replace(/BUG(\d{4})(\ |$)/g, externalBugReplaceValue);
826 bugs = bugs.replace(/BUG(\d{5})(\ |$)/g, externalBugReplaceValue); 873 bugs = bugs.replace(/BUG(\d{5})(\ |$)/g, externalBugReplaceValue);
827 bugs = bugs.replace(/BUG(\d{6})(\ |$)/g, internalBugReplaceValue); 874 bugs = bugs.replace(/BUG(\d{6})(\ |$)/g, internalBugReplaceValue);
828 bugs = bugs.replace(/BUG(\d{7})(\ |$)/g, internalBugReplaceValue); 875 bugs = bugs.replace(/BUG(\d{7})(\ |$)/g, internalBugReplaceValue);
829 return bugs; 876 return bugs;
830 } 877 }
831 878
832 function loadBuilderPageForBuildNumber(builderName, buildNumber) { 879 function getLinkHTMLToOpenWindow(url, text) {
833 window.open(BUILDERS_BASE_PATH + builderName + '/builds/' + buildNumber); 880 return '<li class=link onclick="window.open(\'' + url + '\')">' + text +
881 '</li>';
882 }
883
884 function showPopupForBuild(e, builder, index) {
885 var html = '';
886
887 var time = resultsByBuilder[builder].secondsSinceEpoch[index];
888 if (time) {
889 var date = new Date(time * 1000);
890 html += date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
891 }
892
893 html += '<ul>';
894
895 var webkitRevision = resultsByBuilder[builder].webkitRevision;
896 var thisWebkitRevision = webkitRevision[index];
897 if (thisWebkitRevision) {
898 var previousWebkitRevision = webkitRevision[index + 1] ||
899 thisWebkitRevision;
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 }
921
922 var buildNumbers = resultsByBuilder[builder].buildNumbers;
923 html += getLinkHTMLToOpenWindow(BUILDERS_BASE_PATH + builder + '/builds/' +
924 buildNumbers[index], 'Build log and blamelist') + '</ul>';
925
926 showPopup(e, html);
834 } 927 }
835 928
836 function getHtmlForTestResults(test, builder) { 929 function getHtmlForTestResults(test, builder) {
837 var html = ''; 930 var html = '';
838 var results = test.rawResults.concat(); 931 var results = test.rawResults.concat();
839 var times = test.rawTimes.concat(); 932 var times = test.rawTimes.concat();
840 var buildNumbers = resultsByBuilder[builder].buildNumbers; 933 var buildNumbers = resultsByBuilder[builder].buildNumbers;
841 934
842 var indexToReplaceCurrentResult = -1; 935 var indexToReplaceCurrentResult = -1;
843 var indexToReplaceCurrentTime = -1; 936 var indexToReplaceCurrentTime = -1;
844 var currentResultArray, currentTimeArray, currentResult, innerHTML; 937 var currentResultArray, currentTimeArray, currentResult, innerHTML;
845 for (var i = 0; 938 var maxIndex = Math.min(buildNumbers.length, currentState.maxResults);
846 i < buildNumbers.length && i < currentState.maxResults; 939 for (var i = 0; i < maxIndex; i++) {
847 i++) {
848 if (i > indexToReplaceCurrentResult) { 940 if (i > indexToReplaceCurrentResult) {
849 currentResultArray = results.shift(); 941 currentResultArray = results.shift();
850 if (currentResultArray) { 942 if (currentResultArray) {
851 currentResult = currentResultArray[1]; 943 currentResult = currentResultArray[1];
852 indexToReplaceCurrentResult += currentResultArray[0]; 944 indexToReplaceCurrentResult += currentResultArray[0];
853 } else { 945 } else {
854 currentResult = 'N'; 946 currentResult = 'N';
855 indexToReplaceCurrentResult += buildNumbers.length; 947 indexToReplaceCurrentResult += buildNumbers.length;
856 } 948 }
857 } 949 }
858 950
859 if (i > indexToReplaceCurrentTime) { 951 if (i > indexToReplaceCurrentTime) {
860 currentTimeArray = times.shift(); 952 currentTimeArray = times.shift();
861 var currentTime = 0; 953 var currentTime = 0;
862 if (currentResultArray) { 954 if (currentResultArray) {
863 currentTime = currentTimeArray[1]; 955 currentTime = currentTimeArray[1];
864 indexToReplaceCurrentTime += currentTimeArray[0]; 956 indexToReplaceCurrentTime += currentTimeArray[0];
865 } else { 957 } else {
866 indexToReplaceCurrentTime += buildNumbers.length; 958 indexToReplaceCurrentTime += buildNumbers.length;
867 } 959 }
868 innerHTML = currentTime || '&nbsp;'; 960 innerHTML = currentTime || '&nbsp;';
869 } 961 }
870 962
871 var buildNumber = buildNumbers[i]; 963 html += '<td title="Click results for handy links." class="results ' +
872 html += '<td title="Build:' + buildNumber + '" class="results ' + 964 currentResult + '" onclick=\'showPopupForBuild(event, "' + builder +
873 currentResult + '" onclick=\'loadBuilderPageForBuildNumber("' + 965 '",' + i + ')\'>' + innerHTML + '</td>';
874 builder + '","' + buildNumber + '")\'>' + innerHTML + '</td>'; 966
967 var webkitRevision = resultsByBuilder[builder].webkitRevision;
968 var isWebkitMerge = webkitRevision[i + 1] &&
969 webkitRevision[i] != webkitRevision[i + 1];
970 if (isWebkitMerge)
971 html += '<td class=merge></td>';
875 } 972 }
876 return html; 973 return html;
877 } 974 }
878 975
879 function getHTMLForTestsWithExpectationsButNoFailures(builder) { 976 function getHTMLForTestsWithExpectationsButNoFailures(builder) {
880 var tests = perBuilderWithExpectationsButNoFailures[builder]; 977 var tests = perBuilderWithExpectationsButNoFailures[builder];
881 if (!tests.length) 978 var skippedPaths = perBuilderSkippedPaths[builder];
882 return '';
883 979
884 var buildInfo = getPlatFormAndBuildType(builder); 980 var html = '';
885 return '<h2>Have expectations for ' + buildInfo.platform + '-' + 981 if (tests.length || skippedPaths.length) {
886 buildInfo.buildType + ' but have not failed in last ' + 982 var buildInfo = getPlatFormAndBuildType(builder);
983 html += '<h2>Expectations for ' + buildInfo.platform + '-' +
984 buildInfo.buildType + ':</h2>';
985 }
986
987 if (tests.length) {
988 html += '<h3>Have not failed in last ' +
887 resultsByBuilder[builderName].buildNumbers.length + 989 resultsByBuilder[builderName].buildNumbers.length +
888 ' runs.</h2><div id="passing-tests"><div>' + 990 ' runs.</h3><div id="passing-tests"><div>' +
889 tests.join('</div><div>') + '</div></div>'; 991 tests.join('</div><div>') + '</div></div>';
992 }
993
994 if (skippedPaths.length) {
995 html += '<h3>' +
996 getLinkHTMLToToggleState('showSkipped',
997 'Skipped tests in text_expectations.txt') +
998 '</h3>';
999
1000 if (currentState.showSkipped) {
1001 html += '<div id="passing-tests"><div>' +
1002 skippedPaths.join('</div><div>') + '</div></div>';
1003 }
1004 }
1005 return html;
890 } 1006 }
891 1007
892 /** 1008 /**
893 * Returns true if a test should be considered flaky. Uses heuristics to 1009 * Returns true if a test should be considered flaky. Uses heuristics to
894 * avoid common non-flaky cases. 1010 * avoid common non-flaky cases.
895 */ 1011 */
896 function isTestFlaky(testResult) { 1012 function isTestFlaky(testResult) {
897 return testResult.flips > 1 && !isFixedTest(testResult); 1013 return testResult.flips > 1 && !isFixedTest(testResult);
898 } 1014 }
899 1015
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
1138 '<div>Show tests on all platforms (slow): </div><input name=tests ' + 1254 '<div>Show tests on all platforms (slow): </div><input name=tests ' +
1139 'placeholder="LayoutTests/foo/bar.html,LayoutTests/foo/baz.html" ' + 1255 'placeholder="LayoutTests/foo/bar.html,LayoutTests/foo/baz.html" ' +
1140 'id=tests-input></form><div id="loading-ui">LOADING...</div>' + 1256 'id=tests-input></form><div id="loading-ui">LOADING...</div>' +
1141 '<div id=legend>'; 1257 '<div id=legend>';
1142 1258
1143 for (var expectation in EXPECTATIONS_MAP) { 1259 for (var expectation in EXPECTATIONS_MAP) {
1144 html += '<div class=' + expectation + '>' + 1260 html += '<div class=' + expectation + '>' +
1145 EXPECTATIONS_MAP[expectation] + '</div>'; 1261 EXPECTATIONS_MAP[expectation] + '</div>';
1146 } 1262 }
1147 return html + '<div class=wrong-expectations>WRONG EXPECTATIONS</div>' + 1263 return html + '<div class=wrong-expectations>WRONG EXPECTATIONS</div>' +
1148 '</div>'; 1264 '<div class=merge>WEBKIT MERGE</div></div>';
1149 } 1265 }
1150 1266
1151 function getLinkHTMLToToggleState(key, linkText) { 1267 function getLinkHTMLToToggleState(key, linkText) {
1152 var isTrue = currentState[key]; 1268 var isTrue = currentState[key];
1153 return '<span class=link onclick="setState(\'' + key + '\', ' + !isTrue + 1269 return '<span class=link onclick="setState(\'' + key + '\', ' + !isTrue +
1154 ')">' + (isTrue ? 'Hide' : 'Show') + ' ' + linkText + '</span> | '; 1270 ')">' + (isTrue ? 'Hide' : 'Show') + ' ' + linkText + '</span>';
1155 } 1271 }
1156 1272
1157 function generatePageForBuilder(builderName) { 1273 function generatePageForBuilder(builderName) {
1158 processTestRunsForBuilder(builderName); 1274 processTestRunsForBuilder(builderName);
1159 1275
1160 var tableRowsHTML = ''; 1276 var tableRowsHTML = '';
1161 var results = perBuilderFailures[builderName]; 1277 var results = perBuilderFailures[builderName];
1162 sortTests(results, currentState.sortColumn, currentState.sortOrder); 1278 sortTests(results, currentState.sortColumn, currentState.sortOrder);
1163 for (var i = 0; i < results.length; i++) { 1279 for (var i = 0; i < results.length; i++) {
1164 tableRowsHTML += getHTMLForSingleTestRow(results[i], builderName); 1280 tableRowsHTML += getHTMLForSingleTestRow(results[i], builderName);
1165 } 1281 }
1166 1282
1167 var testsHTML = tableRowsHTML ? getHTMLForTestTable(tableRowsHTML) : 1283 var testsHTML = tableRowsHTML ? getHTMLForTestTable(tableRowsHTML) :
1168 '<div>No tests. Try showing tests with correct expectations.</div>'; 1284 '<div>No tests. Try showing tests with correct expectations.</div>';
1169 1285
1170 var html = getHTMLForNavBar(builderName) + 1286 var html = getHTMLForNavBar(builderName) +
1171 getHTMLForTestsWithExpectationsButNoFailures(builderName) + 1287 getHTMLForTestsWithExpectationsButNoFailures(builderName) +
1172 '<h2>Failing tests</h2><div>' + 1288 '<h2>Failing tests</h2><div>' +
1173 getLinkHTMLToToggleState('showWontFix', 'WONTFIX tests') + 1289 getLinkHTMLToToggleState('showWontFix', 'WONTFIX tests') + ' | ' +
1174 getLinkHTMLToToggleState('showCorrectExpectations', 1290 getLinkHTMLToToggleState('showCorrectExpectations',
1175 'tests with correct expectations') + 1291 'tests with correct expectations') + ' | ' +
1176 getLinkHTMLToToggleState('showFlaky', 'flaky tests') + 1292 getLinkHTMLToToggleState('showFlaky', 'flaky tests') + ' | ' +
1177 '<form id=max-results-form ' + 1293 '<form id=max-results-form ' +
1178 'onsubmit="setState(\'maxResults\', maxResults.value);return false;"' + 1294 'onsubmit="setState(\'maxResults\', maxResults.value);return false;"' +
1179 '><span>Max results to show: </span>' + 1295 '><span>Number of results to show: </span>' +
1180 '<input name=maxResults id=max-results-input></form> | ' + 1296 '<input name=maxResults id=max-results-input></form> | ' +
1181 '<b>All columns are sortable. | Skipped tests are not listed. | ' + 1297 '<b>All columns are sortable. | Skipped tests are not listed. | ' +
1182 'Flakiness reader order is newer --> older runs.</b></div>' + 1298 'Flakiness reader order is newer --> older runs.</b></div>' +
1183 testsHTML; 1299 testsHTML;
1184 1300
1185 setFullPageHTML(html); 1301 setFullPageHTML(html);
1186 1302
1187 var ths = document.getElementsByTagName('th'); 1303 var ths = document.getElementsByTagName('th');
1188 for (var i = 0; i < ths.length; i++) { 1304 for (var i = 0; i < ths.length; i++) {
1189 ths[i].addEventListener('click', changeSort, false); 1305 ths[i].addEventListener('click', changeSort, false);
1190 ths[i].className = "sortable"; 1306 ths[i].className = "sortable";
1191 } 1307 }
1192 1308
1193 $('max-results-input').value = currentState.maxResults; 1309 $('max-results-input').value = currentState.maxResults;
1194 } 1310 }
1195 1311
1196 var singleBuilderViewParameters = ['sortOrder', 'sortColumn', 'showWontFix',
1197 'showCorrectExpectations', 'showFlaky: true', 'maxResults'];
1198
1199 /** 1312 /**
1200 * Sets the page state and regenerates the page. Takes varargs of key, value 1313 * Sets the page state and regenerates the page. Takes varargs of key, value
1201 * pairs. 1314 * pairs.
1202 */ 1315 */
1203 function setState(key, value) { 1316 function setState(key, value) {
1204 for (var i = 0; i < arguments.length; i = i + 2) { 1317 for (var i = 0; i < arguments.length; i = i + 2) {
1205 var key = arguments[i]; 1318 var key = arguments[i];
1206 if (key == 'tests') { 1319 if (key != 'tests') {
1207 for (var state in singleBuilderViewParameters) {
1208 delete currentState[state];
1209 }
1210 } else {
1211 delete currentState.tests; 1320 delete currentState.tests;
1212 } 1321 }
1213 1322
1214 currentState[key] = arguments[i + 1]; 1323 currentState[key] = arguments[i + 1];
1215 } 1324 }
1216 window.location.replace(getPermaLinkURL()); 1325 window.location.replace(getPermaLinkURL());
1217 handleLocationChange(); 1326 handleLocationChange();
1218 } 1327 }
1219 1328
1220 function handleLocationChange() { 1329 function handleLocationChange() {
(...skipping 13 matching lines...) Expand all
1234 for (var key in stateObject) { 1343 for (var key in stateObject) {
1235 state.push(key + '=' + encodeURIComponent(stateObject[key])); 1344 state.push(key + '=' + encodeURIComponent(stateObject[key]));
1236 } 1345 }
1237 return state.join('&'); 1346 return state.join('&');
1238 } 1347 }
1239 1348
1240 function logTime(msg, startTime) { 1349 function logTime(msg, startTime) {
1241 console.log(msg + ': ' + (Date.now() - startTime)); 1350 console.log(msg + ': ' + (Date.now() - startTime));
1242 } 1351 }
1243 1352
1353 function hidePopup() {
1354 var popup = $('popup');
1355 popup.parentNode.removeChild(popup);
1356 }
1357
1358 function showPopup(e, html) {
1359 var popup = $('popup');
1360 if (!popup) {
1361 popup = document.createElement('div');
1362 popup.id = 'popup';
1363 document.body.appendChild(popup);
1364 }
1365
1366 // Set html first so that we can get accurate size metrics on the popup.
1367 popup.innerHTML = html;
1368
1369 var targetRect = e.target.getBoundingClientRect();
1370
1371 var x = Math.min(targetRect.left - 10,
1372 document.documentElement.clientWidth - popup.offsetWidth);
1373 popup.style.left = x + document.body.scrollLeft + 'px';
1374
1375 var y = targetRect.top + targetRect.height;
1376 if (y + popup.offsetHeight > document.documentElement.clientHeight) {
1377 y = targetRect.top - popup.offsetHeight;
1378 }
1379 popup.style.top = y + document.body.scrollTop + 'px';
1380 }
1381
1382 document.onmousedown = function(e) {
1383 // Clear the open popup, unless the click was inside the popup.
1384 var popup = $('popup');
1385 if (popup && e.target != popup &&
1386 !(popup.compareDocumentPosition(e.target) & 16)) {
1387 hidePopup();
1388 }
1389 };
1390
1244 window.onload = function() { 1391 window.onload = function() {
1245 // This doesn't seem totally accurate as there is a race between 1392 // This doesn't seem totally accurate as there is a race between
1246 // onload firing and the last script tag being executed. 1393 // onload firing and the last script tag being executed.
1247 logTime('Time to load JS', pageLoadStartTime); 1394 logTime('Time to load JS', pageLoadStartTime);
1248 setInterval(function() { 1395 setInterval(function() {
1249 if (oldLocation != window.location.href) { 1396 if (oldLocation != window.location.href) {
1250 parseAllParameters(); 1397 parseAllParameters();
1251 handleLocationChange(); 1398 handleLocationChange();
1252 } 1399 }
1253 }, 100); 1400 }, 100);
1254 } 1401 }
1255 </script> 1402 </script>
1256 </head> 1403 </head>
1257 1404
1258 <body></body> 1405 <body></body>
1259 </html> 1406 </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