9b168f285cc1a01acef80e6ce091854e849606f5
[WebKit-https.git] / Tools / TestResultServer / static-dashboards / flakiness_dashboard_unittests.js
1 // Copyright (C) 2011 Google Inc. All rights reserved.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 //     * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //     * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 //     * Neither the name of Google Inc. nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 function resetGlobals()
30 {
31     allExpectations = null;
32     allTests = null;
33     g_expectationsByPlatform = {};
34     g_resultsByBuilder = {};
35     g_allExpectations = null;
36     g_allTestsTrie = null;
37     g_currentState = {};
38     g_crossDashboardState = {};
39     g_testToResultsMap = {};
40
41     for (var key in g_defaultCrossDashboardStateValues)
42         g_crossDashboardState[key] = g_defaultCrossDashboardStateValues[key];
43
44     LOAD_BUILDBOT_DATA([{
45         name: 'ChromiumWebkit',
46         url: 'dummyurl', 
47         tests: {'layout-tests': {'builders': ['WebKit Linux', 'WebKit Linux (dbg)', 'WebKit Mac10.7', 'WebKit Win', 'WebKit Win (dbg)']}}
48     },
49     {
50         name: 'webkit.org',
51         url: 'dummyurl',
52         tests: {'layout-tests': {'builders': ['Apple SnowLeopard Tests', 'Qt Linux Tests', 'Chromium Mac10.7 Tests', 'GTK Win']}}
53     }]);
54  
55     for (var group in LAYOUT_TESTS_BUILDER_GROUPS)
56         LAYOUT_TESTS_BUILDER_GROUPS[group] = null;
57 }
58
59 function stubResultsByBuilder(data)
60 {
61     for (var builder in currentBuilders())
62     {
63         g_resultsByBuilder[builder] = data[builder] || {'tests': []};
64     };
65 }
66
67 function runExpectationsTest(builder, test, expectations, modifiers)
68 {
69     // Put in some dummy results. processExpectations expects the test to be
70     // there.
71     var tests = {};
72     tests[test] = {'results': [[100, 'F']], 'times': [[100, 0]]};
73     var results = {};
74     results[builder] = {'tests': tests};
75     stubResultsByBuilder(results);
76
77     processExpectations();
78     var resultsForTest = createResultsObjectForTest(test, builder);
79     populateExpectationsData(resultsForTest);
80
81     var message = 'Builder: ' + resultsForTest.builder + ' test: ' + resultsForTest.test;
82     equal(resultsForTest.expectations, expectations, message);
83     equal(resultsForTest.modifiers, modifiers, message);
84 }
85
86 test('flattenTrie', 1, function() {
87     resetGlobals();
88     var tests = {
89         'bar.html': {'results': [[100, 'F']], 'times': [[100, 0]]},
90         'foo': {
91             'bar': {
92                 'baz.html': {'results': [[100, 'F']], 'times': [[100, 0]]},
93             }
94         }
95     };
96     var expectedFlattenedTests = {
97         'bar.html': {'results': [[100, 'F']], 'times': [[100, 0]]},
98         'foo/bar/baz.html': {'results': [[100, 'F']], 'times': [[100, 0]]},
99     };
100     equal(JSON.stringify(flattenTrie(tests)), JSON.stringify(expectedFlattenedTests))
101 });
102
103 test('releaseFail', 2, function() {
104     resetGlobals();
105     loadBuildersList('@ToT - chromium.org', 'layout-tests');
106
107     var builder = 'WebKit Win';
108     var test = 'foo/1.html';
109     var expectationsArray = [
110         {'modifiers': 'RELEASE', 'expectations': 'FAIL'}
111     ];
112     g_expectationsByPlatform['CHROMIUM'] = getParsedExpectations('[ Release ] ' + test + ' [ Failure ]');
113     runExpectationsTest(builder, test, 'FAIL', 'RELEASE');
114 });
115
116 test('releaseFailDebugCrashReleaseBuilder', 2, function() {
117     resetGlobals();
118     loadBuildersList('@ToT - chromium.org', 'layout-tests');
119     var builder = 'WebKit Win';
120     var test = 'foo/1.html';
121     var expectationsArray = [
122         {'modifiers': 'RELEASE', 'expectations': 'FAIL'},
123         {'modifiers': 'DEBUG', 'expectations': 'CRASH'}
124     ];
125     g_expectationsByPlatform['CHROMIUM'] = getParsedExpectations('[ Release ] ' + test + ' [ Failure ]\n' +
126         '[ Debug ] ' + test + ' [ Crash ]');
127     runExpectationsTest(builder, test, 'FAIL', 'RELEASE');
128 });
129
130 test('releaseFailDebugCrashDebugBuilder', 2, function() {
131     resetGlobals();
132     loadBuildersList('@ToT - chromium.org', 'layout-tests');
133     var builder = 'WebKit Win (dbg)';
134     var test = 'foo/1.html';
135     var expectationsArray = [
136         {'modifiers': 'RELEASE', 'expectations': 'FAIL'},
137         {'modifiers': 'DEBUG', 'expectations': 'CRASH'}
138     ];
139     g_expectationsByPlatform['CHROMIUM'] = getParsedExpectations('[ Release ] ' + test + ' [ Failure ]\n' +
140         '[ Debug ] ' + test + ' [ Crash ]');
141     runExpectationsTest(builder, test, 'CRASH', 'DEBUG');
142 });
143
144 test('overrideJustBuildType', 12, function() {
145     resetGlobals();
146     loadBuildersList('@ToT - chromium.org', 'layout-tests');
147     var test = 'bar/1.html';
148     g_expectationsByPlatform['CHROMIUM'] = getParsedExpectations('bar [ WontFix Failure Pass Timeout ]\n' +
149         '[ Mac ] ' + test + ' [ WontFix Failure ]\n' +
150         '[ Linux Debug ] ' + test + ' [ Crash ]');
151     
152     runExpectationsTest('WebKit Win', test, 'FAIL PASS TIMEOUT', 'WONTFIX');
153     runExpectationsTest('WebKit Win (dbg)(3)', test, 'FAIL PASS TIMEOUT', 'WONTFIX');
154     runExpectationsTest('WebKit Linux', test, 'FAIL PASS TIMEOUT', 'WONTFIX');
155     runExpectationsTest('WebKit Linux (dbg)(3)', test, 'CRASH', 'LINUX DEBUG');
156     runExpectationsTest('WebKit Mac10.7', test, 'FAIL', 'MAC WONTFIX');
157     runExpectationsTest('WebKit Mac10.7 (dbg)(3)', test, 'FAIL', 'MAC WONTFIX');
158 });
159
160 test('platformAndBuildType', 78, function() {
161     var runPlatformAndBuildTypeTest = function(builder, expectedPlatform, expectedBuildType) {
162         g_perBuilderPlatformAndBuildType = {};
163         buildInfo = platformAndBuildType(builder);
164         var message = 'Builder: ' + builder;
165         equal(buildInfo.platform, expectedPlatform, message);
166         equal(buildInfo.buildType, expectedBuildType, message);
167     }
168     runPlatformAndBuildTypeTest('WebKit Win (deps)', 'CHROMIUM_XP', 'RELEASE');
169     runPlatformAndBuildTypeTest('WebKit Win (deps)(dbg)(1)', 'CHROMIUM_XP', 'DEBUG');
170     runPlatformAndBuildTypeTest('WebKit Win (deps)(dbg)(2)', 'CHROMIUM_XP', 'DEBUG');
171     runPlatformAndBuildTypeTest('WebKit Linux (deps)', 'CHROMIUM_LUCID', 'RELEASE');
172     runPlatformAndBuildTypeTest('WebKit Linux (deps)(dbg)(1)', 'CHROMIUM_LUCID', 'DEBUG');
173     runPlatformAndBuildTypeTest('WebKit Linux (deps)(dbg)(2)', 'CHROMIUM_LUCID', 'DEBUG');
174     runPlatformAndBuildTypeTest('WebKit Mac10.6 (deps)', 'CHROMIUM_SNOWLEOPARD', 'RELEASE');
175     runPlatformAndBuildTypeTest('WebKit Mac10.6 (deps)(dbg)(1)', 'CHROMIUM_SNOWLEOPARD', 'DEBUG');
176     runPlatformAndBuildTypeTest('WebKit Mac10.6 (deps)(dbg)(2)', 'CHROMIUM_SNOWLEOPARD', 'DEBUG');
177     runPlatformAndBuildTypeTest('WebKit Win', 'CHROMIUM_XP', 'RELEASE');
178     runPlatformAndBuildTypeTest('WebKit Win7', 'CHROMIUM_WIN7', 'RELEASE');
179     runPlatformAndBuildTypeTest('WebKit Win (dbg)(1)', 'CHROMIUM_XP', 'DEBUG');
180     runPlatformAndBuildTypeTest('WebKit Win (dbg)(2)', 'CHROMIUM_XP', 'DEBUG');
181     runPlatformAndBuildTypeTest('WebKit Linux', 'CHROMIUM_LUCID', 'RELEASE');
182     runPlatformAndBuildTypeTest('WebKit Linux 32', 'CHROMIUM_LUCID', 'RELEASE');
183     runPlatformAndBuildTypeTest('WebKit Linux (dbg)(1)', 'CHROMIUM_LUCID', 'DEBUG');
184     runPlatformAndBuildTypeTest('WebKit Linux (dbg)(2)', 'CHROMIUM_LUCID', 'DEBUG');
185     runPlatformAndBuildTypeTest('WebKit Mac10.6', 'CHROMIUM_SNOWLEOPARD', 'RELEASE');
186     runPlatformAndBuildTypeTest('WebKit Mac10.6 (dbg)', 'CHROMIUM_SNOWLEOPARD', 'DEBUG');
187     runPlatformAndBuildTypeTest('XP Tests', 'CHROMIUM_XP', 'RELEASE');
188     runPlatformAndBuildTypeTest('Interactive Tests (dbg)', 'CHROMIUM_XP', 'DEBUG');
189     
190     g_crossDashboardState.group = '@ToT - webkit.org';
191     g_crossDashboardState.testType = 'layout-tests';
192     runPlatformAndBuildTypeTest('Chromium Win Release (Tests)', 'CHROMIUM_XP', 'RELEASE');
193     runPlatformAndBuildTypeTest('Chromium Linux Release (Tests)', 'CHROMIUM_LUCID', 'RELEASE');
194     runPlatformAndBuildTypeTest('Chromium Mac Release (Tests)', 'CHROMIUM_SNOWLEOPARD', 'RELEASE');
195     
196     // FIXME: These platforms should match whatever we use in the TestExpectations format.
197     runPlatformAndBuildTypeTest('Lion Release (Tests)', 'APPLE_MAC_LION_WK1', 'RELEASE');
198     runPlatformAndBuildTypeTest('Lion Debug (Tests)', 'APPLE_MAC_LION_WK1', 'DEBUG');
199     runPlatformAndBuildTypeTest('SnowLeopard Intel Release (Tests)', 'APPLE_MAC_SNOWLEOPARD_WK1', 'RELEASE');
200     runPlatformAndBuildTypeTest('SnowLeopard Intel Leaks', 'APPLE_MAC_SNOWLEOPARD_WK1', 'RELEASE');
201     runPlatformAndBuildTypeTest('SnowLeopard Intel Debug (Tests)', 'APPLE_MAC_SNOWLEOPARD_WK1', 'DEBUG');
202     runPlatformAndBuildTypeTest('GTK Linux 32-bit Release', 'GTK_LINUX_WK1', 'RELEASE');
203     runPlatformAndBuildTypeTest('GTK Linux 32-bit Debug', 'GTK_LINUX_WK1', 'DEBUG');
204     runPlatformAndBuildTypeTest('GTK Linux 64-bit Debug', 'GTK_LINUX_WK1', 'DEBUG');
205     runPlatformAndBuildTypeTest('GTK Linux 64-bit Debug WK2', 'GTK_LINUX_WK2', 'DEBUG');
206     runPlatformAndBuildTypeTest('Qt Linux Release', 'QT_LINUX', 'RELEASE');
207     runPlatformAndBuildTypeTest('Windows 7 Release (Tests)', 'APPLE_WIN_WIN7', 'RELEASE');
208     runPlatformAndBuildTypeTest('Windows XP Debug (Tests)', 'APPLE_WIN_XP', 'DEBUG');
209     
210     // FIXME: Should WebKit2 be it's own platform?
211     runPlatformAndBuildTypeTest('SnowLeopard Intel Release (WebKit2 Tests)', 'APPLE_MAC_SNOWLEOPARD_WK2', 'RELEASE');
212     runPlatformAndBuildTypeTest('SnowLeopard Intel Debug (WebKit2 Tests)', 'APPLE_MAC_SNOWLEOPARD_WK2', 'DEBUG');
213     runPlatformAndBuildTypeTest('Windows 7 Release (WebKit2 Tests)', 'APPLE_WIN_WIN7', 'RELEASE');    
214 });
215
216 test('realModifiers', 3, function() {
217     equal(realModifiers('BUG(Foo) LINUX LION WIN DEBUG SLOW'), 'SLOW');
218     equal(realModifiers('BUG(Foo) LUCID MAC XP RELEASE SKIP'), 'SKIP');
219     equal(realModifiers('BUG(Foo)'), '');
220 });
221
222 test('allTestsWithSamePlatformAndBuildType', 1, function() {
223     // FIXME: test that allTestsWithSamePlatformAndBuildType actually returns the right set of tests.
224     var expectedPlatformsList = ['CHROMIUM_LION', 'CHROMIUM_SNOWLEOPARD', 'CHROMIUM_XP', 'CHROMIUM_VISTA', 'CHROMIUM_WIN7', 'CHROMIUM_LUCID',
225                                  'CHROMIUM_ANDROID', 'APPLE_MAC_LION_WK1', 'APPLE_MAC_LION_WK2', 'APPLE_MAC_SNOWLEOPARD_WK1', 'APPLE_MAC_SNOWLEOPARD_WK2',
226                                  'APPLE_WIN_XP', 'APPLE_WIN_WIN7',  'GTK_LINUX_WK1', 'GTK_LINUX_WK2', 'QT_LINUX', 'EFL_LINUX_WK1', 'EFL_LINUX_WK2'];
227     var actualPlatformsList = Object.keys(g_allTestsByPlatformAndBuildType);
228     deepEqual(expectedPlatformsList, actualPlatformsList);
229 });
230
231 test('filterBugs',4, function() {
232     var filtered = filterBugs('Skip crbug.com/123 webkit.org/b/123 Slow Bug(Tony) Debug')
233     equal(filtered.modifiers, 'Skip Slow Debug');
234     equal(filtered.bugs, 'crbug.com/123 webkit.org/b/123 Bug(Tony)');
235
236     filtered = filterBugs('Skip Slow Debug')
237     equal(filtered.modifiers, 'Skip Slow Debug');
238     equal(filtered.bugs, '');
239 });
240
241 test('getExpectations', 16, function() {
242     resetGlobals();
243     loadBuildersList('@ToT - chromium.org', 'layout-tests');
244  
245     stubResultsByBuilder({
246         'WebKit Win' : {
247             'tests': {
248                 'foo/test1.html': {'results': [[100, 'F']], 'times': [[100, 0]]},
249                 'foo/test2.html': {'results': [[100, 'F']], 'times': [[100, 0]]},
250                 'foo/test3.html': {'results': [[100, 'F']], 'times': [[100, 0]]},
251                 'test1.html': {'results': [[100, 'F']], 'times': [[100, 0]]}
252             }
253         }
254     });
255
256     g_expectationsByPlatform['CHROMIUM'] = getParsedExpectations('Bug(123) foo [ Failure Pass Crash ]\n' +
257         'Bug(Foo) [ Release ] foo/test1.html [ Failure ]\n' +
258         '[ Debug ] foo/test1.html [ Crash ]\n' +
259         'Bug(456) foo/test2.html [ Failure ]\n' +
260         '[ Linux Debug ] foo/test2.html [ Crash ]\n' +
261         '[ Release ] test1.html [ Failure ]\n' +
262         '[ Debug ] test1.html [ Crash ]\n');
263     g_expectationsByPlatform['CHROMIUM_ANDROID'] = getParsedExpectations('Bug(654) foo/test2.html [ Crash ]\n');
264
265     g_expectationsByPlatform['GTK'] = getParsedExpectations('Bug(42) foo/test2.html [ ImageOnlyFailure ]\n' +
266         '[ Debug ] test1.html [ Crash ]\n');
267     g_expectationsByPlatform['GTK_LINUX_WK1'] = getParsedExpectations('[ Release ] foo/test1.html [ ImageOnlyFailure ]\n' +
268         'Bug(789) foo/test2.html [ Crash ]\n');
269     g_expectationsByPlatform['GTK_LINUX_WK2'] = getParsedExpectations('Bug(987) foo/test2.html [ Failure ]\n');
270
271     processExpectations();
272     
273     var expectations = getExpectations('foo/test1.html', 'CHROMIUM_XP', 'DEBUG');
274     equal(JSON.stringify(expectations), '{"modifiers":"DEBUG","expectations":"CRASH"}');
275
276     var expectations = getExpectations('foo/test1.html', 'CHROMIUM_LUCID', 'RELEASE');
277     equal(JSON.stringify(expectations), '{"modifiers":"Bug(Foo) RELEASE","expectations":"FAIL"}');
278
279     var expectations = getExpectations('foo/test2.html', 'CHROMIUM_LUCID', 'RELEASE');
280     equal(JSON.stringify(expectations), '{"modifiers":"Bug(456)","expectations":"FAIL"}');
281
282     var expectations = getExpectations('foo/test2.html', 'CHROMIUM_LION', 'DEBUG');
283     equal(JSON.stringify(expectations), '{"modifiers":"Bug(456)","expectations":"FAIL"}');
284
285     var expectations = getExpectations('foo/test2.html', 'CHROMIUM_LUCID', 'DEBUG');
286     equal(JSON.stringify(expectations), '{"modifiers":"LINUX DEBUG","expectations":"CRASH"}');
287
288     var expectations = getExpectations('foo/test2.html', 'CHROMIUM_ANDROID', 'RELEASE');
289     equal(JSON.stringify(expectations), '{"modifiers":"Bug(654)","expectations":"CRASH"}');
290
291     var expectations = getExpectations('test1.html', 'CHROMIUM_ANDROID', 'RELEASE');
292     equal(JSON.stringify(expectations), '{"modifiers":"RELEASE","expectations":"FAIL"}');
293
294     var expectations = getExpectations('foo/test3.html', 'CHROMIUM_LUCID', 'DEBUG');
295     equal(JSON.stringify(expectations), '{"modifiers":"Bug(123)","expectations":"FAIL PASS CRASH"}');
296
297     var expectations = getExpectations('test1.html', 'CHROMIUM_XP', 'DEBUG');
298     equal(JSON.stringify(expectations), '{"modifiers":"DEBUG","expectations":"CRASH"}');
299
300     var expectations = getExpectations('test1.html', 'CHROMIUM_LUCID', 'RELEASE');
301     equal(JSON.stringify(expectations), '{"modifiers":"RELEASE","expectations":"FAIL"}');
302
303     var expectations = getExpectations('foo/test1.html', 'GTK_LINUX_WK1', 'RELEASE');
304     equal(JSON.stringify(expectations), '{"modifiers":"RELEASE","expectations":"IMAGE"}');
305
306     var expectations = getExpectations('foo/test2.html', 'GTK_LINUX_WK1', 'DEBUG');
307     equal(JSON.stringify(expectations), '{"modifiers":"Bug(789)","expectations":"CRASH"}');
308
309     var expectations = getExpectations('test1.html', 'GTK_LINUX_WK1', 'DEBUG');
310     equal(JSON.stringify(expectations), '{"modifiers":"DEBUG","expectations":"CRASH"}');
311
312     var expectations = getExpectations('foo/test2.html', 'GTK_LINUX_WK2', 'DEBUG');
313     equal(JSON.stringify(expectations), '{"modifiers":"Bug(987)","expectations":"FAIL"}');
314
315     var expectations = getExpectations('foo/test2.html', 'GTK_LINUX_WK2', 'RELEASE');
316     equal(JSON.stringify(expectations), '{"modifiers":"Bug(987)","expectations":"FAIL"}');
317
318     var expectations = getExpectations('test1.html', 'GTK_LINUX_WK2', 'DEBUG');
319     equal(JSON.stringify(expectations), '{"modifiers":"DEBUG","expectations":"CRASH"}');
320 });
321
322 test('substringList', 2, function() {
323     g_crossDashboardState.testType = 'gtest';
324     g_currentState.tests = 'test.FLAKY_foo test.FAILS_foo1 test.DISABLED_foo2 test.MAYBE_foo3 test.foo4';
325     equal(substringList().toString(), 'test.foo,test.foo1,test.foo2,test.foo3,test.foo4');
326
327     g_crossDashboardState.testType = 'layout-tests';
328     g_currentState.tests = 'foo/bar.FLAKY_foo.html';
329     equal(substringList().toString(), 'foo/bar.FLAKY_foo.html');
330 });
331
332 test('htmlForTestsWithExpectationsButNoFailures', 4, function() {
333     loadBuildersList('@ToT - chromium.org', 'layout-tests');
334     var builder = 'WebKit Win';
335     g_perBuilderWithExpectationsButNoFailures[builder] = ['passing-test1.html', 'passing-test2.html'];
336     g_perBuilderSkippedPaths[builder] = ['skipped-test1.html'];
337     g_resultsByBuilder[builder] = { buildNumbers: [5, 4, 3, 1] };
338
339     g_currentState.showUnexpectedPasses = true;
340     g_currentState.showSkipped = true;
341
342     g_crossDashboardState.group = '@ToT - chromium.org';
343     g_crossDashboardState.testType = 'layout-tests';
344     
345     var container = document.createElement('div');
346     container.innerHTML = htmlForTestsWithExpectationsButNoFailures(builder);
347     equal(container.querySelectorAll('#passing-tests > div').length, 2);
348     equal(container.querySelectorAll('#skipped-tests > div').length, 1);
349     
350     g_currentState.showUnexpectedPasses = false;
351     g_currentState.showSkipped = false;
352     
353     var container = document.createElement('div');
354     container.innerHTML = htmlForTestsWithExpectationsButNoFailures(builder);
355     equal(container.querySelectorAll('#passing-tests > div').length, 0);
356     equal(container.querySelectorAll('#skipped-tests > div').length, 0);
357 });
358
359 test('headerForTestTableHtml', 1, function() {
360     var container = document.createElement('div');
361     container.innerHTML = headerForTestTableHtml();
362     equal(container.querySelectorAll('input').length, 5);
363 });
364
365 test('htmlForTestTypeSwitcherGroup', 6, function() {
366     var container = document.createElement('div');
367     g_crossDashboardState.testType = 'ui_tests';
368     container.innerHTML = htmlForTestTypeSwitcher(true);
369     var selects = container.querySelectorAll('select');
370     equal(selects.length, 2);
371     var group = selects[1];
372     equal(group.parentNode.textContent.indexOf('Group:'), 0);
373     equal(group.children.length, 3);
374
375     g_crossDashboardState.testType = 'layout-tests';
376     container.innerHTML = htmlForTestTypeSwitcher(true);
377     var selects = container.querySelectorAll('select');
378     equal(selects.length, 2);
379     var group = selects[1];
380     equal(group.parentNode.textContent.indexOf('Group:'), 0);
381     equal(group.children.length, 4);
382 });
383
384 test('htmlForIndividualTestOnAllBuilders', 1, function() {
385     resetGlobals();
386     loadBuildersList('@ToT - chromium.org', 'layout-tests');
387     equal(htmlForIndividualTestOnAllBuilders('foo/nonexistant.html'), '<div class="not-found">Test not found. Either it does not exist, is skipped or passes on all platforms.</div>');
388 });
389
390 test('htmlForIndividualTestOnAllBuildersWithResultsLinksNonexistant', 1, function() {
391     resetGlobals();
392     loadBuildersList('@ToT - chromium.org', 'layout-tests');
393     equal(htmlForIndividualTestOnAllBuildersWithResultsLinks('foo/nonexistant.html'),
394         '<div class="not-found">Test not found. Either it does not exist, is skipped or passes on all platforms.</div>' +
395         '<div class=expectations test=foo/nonexistant.html>' +
396             '<div>' +
397                 '<span class=link onclick="setQueryParameter(\'showExpectations\', true)">Show results</span> | ' +
398                 '<span class=link onclick="setQueryParameter(\'showLargeExpectations\', true)">Show large thumbnails</span> | ' +
399                 '<b>Only shows actual results/diffs from the most recent *failure* on each bot.</b>' +
400             '</div>' +
401         '</div>');
402 });
403
404 test('htmlForIndividualTestOnAllBuildersWithResultsLinks', 1, function() {
405     resetGlobals();
406     loadBuildersList('@ToT - chromium.org', 'layout-tests');
407
408     var builderName = 'WebKit Linux';
409     var test = 'dummytest.html';
410     g_testToResultsMap[test] = [createResultsObjectForTest(test, builderName)];
411
412     equal(htmlForIndividualTestOnAllBuildersWithResultsLinks(test),
413         '<table class=test-table><thead><tr>' +
414                 '<th sortValue=test><div class=table-header-content><span></span><span class=header-text>test</span></div></th>' +
415                 '<th sortValue=bugs><div class=table-header-content><span></span><span class=header-text>bugs</span></div></th>' +
416                 '<th sortValue=modifiers><div class=table-header-content><span></span><span class=header-text>modifiers</span></div></th>' +
417                 '<th sortValue=expectations><div class=table-header-content><span></span><span class=header-text>expectations</span></div></th>' +
418                 '<th sortValue=slowest><div class=table-header-content><span></span><span class=header-text>slowest run</span></div></th>' +
419                 '<th sortValue=flakiness colspan=10000><div class=table-header-content><span></span><span class=header-text>flakiness (numbers are runtimes in seconds)</span></div></th>' +
420             '</tr></thead>' +
421             '<tbody></tbody>' +
422         '</table>' +
423         '<div>The following builders either don\'t run this test (e.g. it\'s skipped) or all runs passed:</div>' +
424         '<div class=skipped-builder-list>' +
425             '<div class=skipped-builder>WebKit Linux (dbg)</div><div class=skipped-builder>WebKit Mac10.7</div><div class=skipped-builder>WebKit Win</div><div class=skipped-builder>WebKit Win (dbg)</div>' +
426         '</div>' +
427         '<div class=expectations test=dummytest.html>' +
428             '<div><span class=link onclick="setQueryParameter(\'showExpectations\', true)">Show results</span> | ' +
429             '<span class=link onclick="setQueryParameter(\'showLargeExpectations\', true)">Show large thumbnails</span> | ' +
430             '<b>Only shows actual results/diffs from the most recent *failure* on each bot.</b></div>' +
431         '</div>');
432 });
433
434 test('htmlForIndividualTestOnAllBuildersWithResultsLinksWebkitMaster', 1, function() {
435     resetGlobals();
436     g_crossDashboardState.group = '@ToT - webkit.org';
437     loadBuildersList('@ToT - webkit.org', 'layout-tests');
438
439     var builderName = 'Apple SnowLeopard Tests';
440     var test = 'dummytest.html';
441     g_testToResultsMap[test] = [createResultsObjectForTest(test, builderName)];
442
443     equal(htmlForIndividualTestOnAllBuildersWithResultsLinks(test),
444         '<table class=test-table><thead><tr>' +
445                 '<th sortValue=test><div class=table-header-content><span></span><span class=header-text>test</span></div></th>' +
446                 '<th sortValue=bugs><div class=table-header-content><span></span><span class=header-text>bugs</span></div></th>' +
447                 '<th sortValue=modifiers><div class=table-header-content><span></span><span class=header-text>modifiers</span></div></th>' +
448                 '<th sortValue=expectations><div class=table-header-content><span></span><span class=header-text>expectations</span></div></th>' +
449                 '<th sortValue=slowest><div class=table-header-content><span></span><span class=header-text>slowest run</span></div></th>' +
450                 '<th sortValue=flakiness colspan=10000><div class=table-header-content><span></span><span class=header-text>flakiness (numbers are runtimes in seconds)</span></div></th>' +
451             '</tr></thead>' +
452             '<tbody></tbody>' +
453         '</table>' +
454         '<div>The following builders either don\'t run this test (e.g. it\'s skipped) or all runs passed:</div>' +
455         '<div class=skipped-builder-list>' +
456             '<div class=skipped-builder>Qt Linux Tests</div><div class=skipped-builder>Chromium Mac10.7 Tests</div><div class=skipped-builder>GTK Win</div>' +
457         '</div>' +
458         '<div class=expectations test=dummytest.html>' +
459             '<div><span class=link onclick="setQueryParameter(\'showExpectations\', true)">Show results</span> | ' +
460             '<span class=link onclick="setQueryParameter(\'showLargeExpectations\', true)">Show large thumbnails</span>' +
461             '<form onsubmit="setQueryParameter(\'revision\', revision.value);return false;">' +
462                 'Show results for WebKit revision: <input name=revision placeholder="e.g. 65540" value="" id=revision-input>' +
463             '</form></div>' +
464         '</div>');
465 });
466
467 test('htmlForIndividualTests', 4, function() {
468     resetGlobals();
469     loadBuildersList('@ToT - chromium.org', 'layout-tests');
470     var test1 = 'foo/nonexistant.html';
471     var test2 = 'bar/nonexistant.html';
472
473     g_currentState.showChrome = false;
474
475     var tests = [test1, test2];
476     equal(htmlForIndividualTests(tests),
477         '<h2><a href="http://trac.webkit.org/browser/trunk/LayoutTests/foo/nonexistant.html" target="_blank">foo/nonexistant.html</a></h2>' +
478         htmlForIndividualTestOnAllBuilders(test1) + 
479         '<div class=expectations test=foo/nonexistant.html>' +
480             '<div><span class=link onclick=\"setQueryParameter(\'showExpectations\', true)\">Show results</span> | ' +
481             '<span class=link onclick=\"setQueryParameter(\'showLargeExpectations\', true)\">Show large thumbnails</span> | ' +
482             '<b>Only shows actual results/diffs from the most recent *failure* on each bot.</b></div>' +
483         '</div>' +
484         '<hr>' +
485         '<h2><a href="http://trac.webkit.org/browser/trunk/LayoutTests/bar/nonexistant.html" target="_blank">bar/nonexistant.html</a></h2>' +
486         htmlForIndividualTestOnAllBuilders(test2) +
487         '<div class=expectations test=bar/nonexistant.html>' +
488             '<div><span class=link onclick=\"setQueryParameter(\'showExpectations\', true)\">Show results</span> | ' +
489             '<span class=link onclick=\"setQueryParameter(\'showLargeExpectations\', true)\">Show large thumbnails</span> | ' +
490             '<b>Only shows actual results/diffs from the most recent *failure* on each bot.</b></div>' +
491         '</div>');
492
493     tests = [test1];
494     equal(htmlForIndividualTests(tests), htmlForIndividualTestOnAllBuilders(test1) +
495         '<div class=expectations test=foo/nonexistant.html>' +
496             '<div><span class=link onclick=\"setQueryParameter(\'showExpectations\', true)\">Show results</span> | ' +
497             '<span class=link onclick=\"setQueryParameter(\'showLargeExpectations\', true)\">Show large thumbnails</span> | ' +
498             '<b>Only shows actual results/diffs from the most recent *failure* on each bot.</b></div>' +
499         '</div>');
500
501     g_currentState.showChrome = true;
502
503     equal(htmlForIndividualTests(tests),
504         '<h2><a href="http://trac.webkit.org/browser/trunk/LayoutTests/foo/nonexistant.html" target="_blank">foo/nonexistant.html</a></h2>' +
505         htmlForIndividualTestOnAllBuildersWithResultsLinks(test1));
506
507     tests = [test1, test2];
508     equal(htmlForIndividualTests(tests),
509         '<h2><a href="http://trac.webkit.org/browser/trunk/LayoutTests/foo/nonexistant.html" target="_blank">foo/nonexistant.html</a></h2>' +
510         htmlForIndividualTestOnAllBuildersWithResultsLinks(test1) + '<hr>' +
511         '<h2><a href="http://trac.webkit.org/browser/trunk/LayoutTests/bar/nonexistant.html" target="_blank">bar/nonexistant.html</a></h2>' +
512         htmlForIndividualTestOnAllBuildersWithResultsLinks(test2));
513 });
514
515 test('htmlForSingleTestRow', 1, function() {
516     resetGlobals();
517     var builder = 'dummyBuilder';
518     BUILDER_TO_MASTER[builder] = CHROMIUM_WEBKIT_BUILDER_MASTER;
519     var test = createResultsObjectForTest('foo/exists.html', builder);
520     g_currentState.showCorrectExpectations = true;
521     g_resultsByBuilder[builder] = {buildNumbers: [2, 1], webkitRevision: [1234, 1233]};
522     test.rawResults = [[1, 'F'], [2, 'I']];
523     test.rawTimes = [[1, 0], [2, 5]];
524     var expected = '<tr>' +
525         '<td class="test-link"><span class="link" onclick="setQueryParameter(\'tests\',\'foo/exists.html\');">foo/exists.html</span>' +
526         '<td class=options-container><a href="https://bugs.webkit.org/enter_bug.cgi?assigned_to=webkit-unassigned%40lists.webkit.org&product=WebKit&form_name=enter_bug&component=Tools%20%2F%20Tests&short_desc=Layout%20Test%20foo%2Fexists.html%20is%20failing&comment=The%20following%20layout%20test%20is%20failing%20on%20%5Binsert%20platform%5D%0A%0Afoo%2Fexists.html%0A%0AProbable%20cause%3A%0A%0A%5Binsert%20probable%20cause%5D" class="file-bug">FILE BUG</a>' +
527         '<td class=options-container>' +
528             '<td class=options-container>' +
529                 '<td><td title="TEXT. Click for more info." class="results F merge" onclick=\'showPopupForBuild(event, "dummyBuilder",0,"foo/exists.html")\'>&nbsp;' +
530                 '<td title="IMAGE. Click for more info." class="results I" onclick=\'showPopupForBuild(event, "dummyBuilder",1,"foo/exists.html")\'>5';
531
532     equal(htmlForSingleTestRow(test), expected);
533 });
534
535 test('lookupVirtualTestSuite', 2, function() {
536     equal(lookupVirtualTestSuite('fast/canvas/foo.html'), '');
537     equal(lookupVirtualTestSuite('platform/chromium/virtual/gpu/fast/canvas/foo.html'), 'platform/chromium/virtual/gpu/fast/canvas');
538 });
539
540 test('baseTest', 2, function() {
541     equal(baseTest('fast/canvas/foo.html', ''), 'fast/canvas/foo.html');
542     equal(baseTest('platform/chromium/virtual/gpu/fast/canvas/foo.html', 'platform/chromium/virtual/gpu/fast/canvas'), 'fast/canvas/foo.html');
543 });
544
545 // FIXME: Create builders_tests.js and move this there.
546
547 test('isChromiumWebkitTipOfTreeTestRunner', 1, function() {
548     var builderList = ["WebKit Linux", "WebKit Linux (dbg)", "WebKit Linux 32", "WebKit Mac10.6", "WebKit Mac10.6 (dbg)",
549         "WebKit Mac10.6 (deps)", "WebKit Mac10.7", "WebKit Win", "WebKit Win (dbg)(1)", "WebKit Win (dbg)(2)", "WebKit Win (deps)",
550         "WebKit Win7", "Linux (Content Shell)"];
551     var expectedBuilders = ["WebKit Linux", "WebKit Linux (dbg)", "WebKit Linux 32", "WebKit Mac10.6",
552         "WebKit Mac10.6 (dbg)", "WebKit Mac10.7", "WebKit Win", "WebKit Win (dbg)(1)", "WebKit Win (dbg)(2)", "WebKit Win7"];
553     deepEqual(builderList.filter(isChromiumWebkitTipOfTreeTestRunner), expectedBuilders);
554 });
555
556 test('isChromiumWebkitDepsTestRunner', 1, function() {
557     var builderList = ["Chrome Frame Tests", "GPU Linux (NVIDIA)", "GPU Linux (dbg) (NVIDIA)", "GPU Mac", "GPU Mac (dbg)", "GPU Win7 (NVIDIA)", "GPU Win7 (dbg) (NVIDIA)", "Linux Perf", "Linux Tests",
558         "Linux Valgrind", "Mac Builder (dbg)", "Mac10.6 Perf", "Mac10.6 Tests", "Vista Perf", "Vista Tests", "WebKit Linux", "WebKit Linux ASAN",  "WebKit Linux (dbg)", "WebKit Linux (deps)", "WebKit Linux 32",
559         "WebKit Mac10.6", "WebKit Mac10.6 (dbg)", "WebKit Mac10.6 (deps)", "WebKit Mac10.7", "WebKit Win", "WebKit Win (dbg)(1)", "WebKit Win (dbg)(2)", "WebKit Win (deps)",
560         "WebKit Win7", "Win (dbg)", "Win Builder"];
561     var expectedBuilders = ["WebKit Linux (deps)", "WebKit Mac10.6 (deps)", "WebKit Win (deps)"];
562     deepEqual(builderList.filter(isChromiumWebkitDepsTestRunner), expectedBuilders);
563 });
564
565 test('queryHashAsMap', 2, function() {
566     equal(window.location.hash, '#useTestData=true');
567     deepEqual(queryHashAsMap(), {useTestData: 'true'});
568 });
569
570 test('parseCrossDashboardParameters', 2, function() {
571     equal(window.location.hash, '#useTestData=true');
572     parseCrossDashboardParameters();
573
574     var expectedParameters = {};
575     for (var key in g_defaultCrossDashboardStateValues)
576         expectedParameters[key] = g_defaultCrossDashboardStateValues[key];
577     expectedParameters.useTestData = true;
578
579     deepEqual(g_crossDashboardState, expectedParameters);
580 });
581
582 test('diffStates', 5, function() {
583     var newState = {a: 1, b: 2};
584     deepEqual(diffStates(null, newState), newState);
585
586     var oldState = {a: 1};
587     deepEqual(diffStates(oldState, newState), {b: 2});
588
589     // FIXME: This is kind of weird. I think the existing users of this code work correctly, but it's a confusing result.
590     var oldState = {c: 1};
591     deepEqual(diffStates(oldState, newState), {a:1, b: 2});
592
593     var oldState = {a: 1, b: 2};
594     deepEqual(diffStates(oldState, newState), {});
595
596     var oldState = {a: 2, b: 3};
597     deepEqual(diffStates(oldState, newState), {a: 1, b: 2});
598 });
599
600 test('addBuilderLoadErrors', 1, function() {
601     clearErrors();
602     g_buildersThatFailedToLoad = ['builder1', 'builder2'];
603     g_staleBuilders = ['staleBuilder1'];
604     addBuilderLoadErrors();
605     equal(g_errorMessages, 'ERROR: Failed to get data from builder1,builder2.<br>ERROR: Data from staleBuilder1 is more than 1 day stale.<br>');
606 });
607
608 test('builderGroupIsToTWebKitAttribute', 2, function() {
609     var dummyMaster = new builders.BuilderMaster('Chromium', 'dummyurl', {'layout-tests': {'builders': ['WebKit Linux', 'WebKit Linux (dbg)', 'WebKit Mac10.7', 'WebKit Win']}});
610     var testBuilderGroups = {
611         '@ToT - dummy.org': new BuilderGroup(BuilderGroup.TOT_WEBKIT),
612         '@DEPS - dummy.org': new BuilderGroup(BuilderGroup.DEPS_WEBKIT),
613     }
614
615     var testJSONData = "{ \"Dummy Builder 1\": null, \"Dummy Builder 2\": null }";
616     requestBuilderList(testBuilderGroups, 'ChromiumWebkit', '@ToT - dummy.org', testBuilderGroups['@ToT - dummy.org'], 'layout-tests');
617     equal(testBuilderGroups['@ToT - dummy.org'].isToTWebKit, true);
618     requestBuilderList(testBuilderGroups, 'ChromiumWebkit', '@DEPS - dummy.org', testBuilderGroups['@DEPS - dummy.org'], 'layout-tests');
619     equal(testBuilderGroups['@DEPS - dummy.org'].isToTWebKit, false);
620 });
621
622 test('requestBuilderListAddsBuilderGroupEntry', 1, function() {
623     var testBuilderGroups = { '@ToT - dummy.org': null };
624     var builderGroup = new BuilderGroup(BuilderGroup.TOT_WEBKIT);
625     var groupName = '@ToT - dummy.org';
626     requestBuilderList(testBuilderGroups, 'ChromiumWebkit', groupName, builderGroup, 'layout-tests');
627
628     equal(testBuilderGroups['@ToT - dummy.org'], builderGroup);
629 })
630
631 test('sortTests', 4, function() {
632     var test1 = createResultsObjectForTest('foo/test1.html', 'dummyBuilder');
633     var test2 = createResultsObjectForTest('foo/test2.html', 'dummyBuilder');
634     var test3 = createResultsObjectForTest('foo/test3.html', 'dummyBuilder');
635     test1.modifiers = 'b';
636     test2.modifiers = 'a';
637     test3.modifiers = '';
638
639     var tests = [test1, test2, test3];
640     sortTests(tests, 'modifiers', FORWARD);
641     deepEqual(tests, [test2, test1, test3]);
642     sortTests(tests, 'modifiers', BACKWARD);
643     deepEqual(tests, [test3, test1, test2]);
644
645     test1.bugs = 'b';
646     test2.bugs = 'a';
647     test3.bugs = '';
648
649     var tests = [test1, test2, test3];
650     sortTests(tests, 'bugs', FORWARD);
651     deepEqual(tests, [test2, test1, test3]);
652     sortTests(tests, 'bugs', BACKWARD);
653     deepEqual(tests, [test3, test1, test2]);
654 });
655
656 test('popup', 2, function() {
657     showPopup(document.body, 'dummy content');
658     ok(document.querySelector('#popup'));
659     hidePopup();
660     ok(!document.querySelector('#popup'));
661 });
662
663 test('gpuResultsPath', 3, function() {
664   equal(gpuResultsPath('777777', 'Win7 Release (ATI)'), '777777_Win7_Release_ATI_');
665   equal(gpuResultsPath('123', 'GPU Linux (dbg)(NVIDIA)'), '123_GPU_Linux_dbg_NVIDIA_');
666   equal(gpuResultsPath('12345', 'GPU Mac'), '12345_GPU_Mac');
667 });
668
669 test('TestTrie', 3, function() {
670     var builders = {
671         "Dummy Chromium Windows Builder": true,
672         "Dummy GTK Linux Builder": true,
673         "Dummy Apple Mac Lion Builder": true
674     };
675
676     var resultsByBuilder = {
677         "Dummy Chromium Windows Builder": {
678             tests: {
679                 "foo": true,
680                 "foo/bar/1.html": true,
681                 "foo/bar/baz": true
682             }
683         },
684         "Dummy GTK Linux Builder": {
685             tests: {
686                 "bar": true,
687                 "foo/1.html": true,
688                 "foo/bar/2.html": true,
689                 "foo/bar/baz/1.html": true,
690             }
691         },
692         "Dummy Apple Mac Lion Builder": {
693             tests: {
694                 "foo/bar/3.html": true,
695                 "foo/bar/baz/foo": true,
696             }
697         }
698     };
699     var expectedTrie = {
700         "foo": {
701             "bar": {
702                 "1.html": true,
703                 "2.html": true,
704                 "3.html": true,
705                 "baz": {
706                     "1.html": true,
707                     "foo": true
708                 }
709             },
710             "1.html": true
711         },
712         "bar": true
713     }
714
715     var trie = new TestTrie(builders, resultsByBuilder);
716     deepEqual(trie._trie, expectedTrie);
717
718     var leafsOfCompleteTrieTraversal = [];
719     var expectedLeafs = ["foo/bar/1.html", "foo/bar/baz/1.html", "foo/bar/baz/foo", "foo/bar/2.html", "foo/bar/3.html", "foo/1.html", "bar"];
720     trie.forEach(function(triePath) {
721         leafsOfCompleteTrieTraversal.push(triePath);
722     });
723     deepEqual(leafsOfCompleteTrieTraversal, expectedLeafs);
724
725     var leafsOfPartialTrieTraversal = [];
726     expectedLeafs = ["foo/bar/1.html", "foo/bar/baz/1.html", "foo/bar/baz/foo", "foo/bar/2.html", "foo/bar/3.html"];
727     trie.forEach(function(triePath) {
728         leafsOfPartialTrieTraversal.push(triePath);
729     }, "foo/bar");
730     deepEqual(leafsOfPartialTrieTraversal, expectedLeafs);
731 });