11359086fb181fa01cfb586c662896731c388e0c
[WebKit-https.git] / Tools / BuildSlaveSupport / build.webkit.org-config / mastercfg_unittest.py
1 #! /usr/bin/python
2
3 import sys
4 import os
5 import StringIO
6 import unittest
7 import make_passwords_json
8 import json
9
10 # Show DepricationWarnings come from buildbot - it isn't default with Python 2.7 or newer.
11 # See https://bugs.webkit.org/show_bug.cgi?id=90161 for details.
12 import warnings
13 warnings.simplefilter('default')
14
15 class BuildBotConfigLoader(object):
16     def _add_webkitpy_to_sys_path(self):
17         # When files are passed to the python interpreter on the command line (e.g. python test.py) __file__ is a relative path.
18         absolute_file_path = os.path.abspath(__file__)
19         webkit_org_config_dir = os.path.dirname(absolute_file_path)
20         build_slave_support_dir = os.path.dirname(webkit_org_config_dir)
21         webkit_tools_dir = os.path.dirname(build_slave_support_dir)
22         scripts_dir = os.path.join(webkit_tools_dir, 'Scripts')
23         sys.path.append(scripts_dir)
24
25     def _mock_open(self, filename):
26         if filename == 'passwords.json':
27             return StringIO.StringIO(json.dumps(make_passwords_json.create_mock_slave_passwords_dict()))
28         return __builtins__.open(filename)
29
30     def _add_dependant_modules_to_sys_modules(self):
31         from webkitpy.thirdparty.autoinstalled import buildbot
32         sys.modules['buildbot'] = buildbot
33
34     def load_config(self, master_cfg_path):
35         # Before we can use webkitpy.thirdparty, we need to fix our path to include webkitpy.
36         # FIXME: If we're ever run by test-webkitpy we won't need this step.
37         self._add_webkitpy_to_sys_path()
38         # master.cfg expects the buildbot module to be in sys.path.
39         self._add_dependant_modules_to_sys_modules()
40
41         # master.cfg expects a passwords.json file which is not checked in.  Fake it by mocking open().
42         globals()['open'] = self._mock_open
43         # Because the master_cfg_path may have '.' in its name, we can't just use import, we have to use execfile.
44         # We pass globals() as both the globals and locals to mimic exectuting in the global scope, so
45         # that globals defined in master.cfg will be global to this file too.
46         execfile(master_cfg_path, globals(), globals())
47         globals()['open'] = __builtins__.open  # Stop mocking open().
48
49
50 class MasterCfgTest(unittest.TestCase):
51     def test_nrwt_leaks_parsing(self):
52         run_webkit_tests = RunWebKitTests()  # pylint is confused by the way we import the module ... pylint: disable-msg=E0602
53         log_text = """
54 12:44:24.295 77706 13981 total leaks found for a total of 197,936 bytes.
55 12:44:24.295 77706 1 unique leaks found.
56 """
57         expected_incorrect_lines = [
58             '13981 total leaks found for a total of 197,936 bytes.',
59             '1 unique leaks found.',
60         ]
61         run_webkit_tests._parseRunWebKitTestsOutput(log_text)
62         self.assertEqual(run_webkit_tests.incorrectLayoutLines, expected_incorrect_lines)
63
64     def test_nrwt_missing_results(self):
65         run_webkit_tests = RunWebKitTests()  # pylint is confused by the way we import the module ... pylint: disable-msg=E0602
66         log_text = """
67 Expected to fail, but passed: (2)
68   animations/additive-transform-animations.html
69   animations/cross-fade-webkit-mask-box-image.html
70
71 Unexpected flakiness: text-only failures (2)
72   fast/events/touch/touch-inside-iframe.html [ Failure Pass ]
73   http/tests/inspector-enabled/console-clear-arguments-on-frame-navigation.html [ Failure Pass ]
74
75 Unexpected flakiness: timeouts (1)
76   svg/text/foreignObject-repaint.xml [ Timeout Pass ]
77
78 Regressions: Unexpected missing results (1)
79   svg/custom/zero-path-square-cap-rendering2.svg [ Missing ]
80
81 Regressions: Unexpected text-only failures (1)
82   svg/custom/zero-path-square-cap-rendering2.svg [ Failure ]
83 """
84         run_webkit_tests._parseRunWebKitTestsOutput(log_text)
85         self.assertEqual(set(run_webkit_tests.incorrectLayoutLines),
86             set(['2 new passes', '3 flakes', '1 missing results', '1 failures']))
87
88 class StubStdio(object):
89     def __init__(self, stdio):
90         self._stdio = stdio
91
92     def getText(self):
93         return self._stdio
94
95
96 class StubRemoteCommand(object):
97     def __init__(self, rc, stdio):
98         self.rc = rc
99         self.logs = {'stdio': StubStdio(stdio)}
100
101
102 class RunJavaScriptCoreTestsTest(unittest.TestCase):
103     def assertResults(self, expected_result, expected_text, rc, stdio):
104         cmd = StubRemoteCommand(rc, stdio)
105         step = RunJavaScriptCoreTests()
106         step.commandComplete(cmd)
107         actual_results = step.evaluateCommand(cmd)
108         actual_text = step.getText2(cmd, actual_results)
109
110         self.assertEqual(expected_result, actual_results)
111         self.assertEqual(actual_text, expected_text)
112
113     def test_no_regressions_old_output(self):
114         self.assertResults(SUCCESS, ["jscore-test"], 0, """Results for Mozilla tests:
115     0 regressions found.
116     0 tests fixed.
117     OK.""")
118
119     def test_no_failure_new_output(self):
120         self.assertResults(SUCCESS, ["jscore-test"], 0, """Results for JSC stress tests:
121     0 failures found.
122     OK.""")
123
124     def test_mozilla_failure_old_output(self):
125         self.assertResults(FAILURE, ["1 JSC test failed"], 1, """Results for Mozilla tests:
126     1 regression found.
127     0 tests fixed.""")
128
129     def test_mozilla_failures_old_output(self):
130         self.assertResults(FAILURE, ["2 JSC tests failed"], 1, """Results for Mozilla tests:
131     2 regressions found.
132     0 tests fixed.""")
133
134     def test_jsc_stress_failure_new_output(self):
135         self.assertResults(FAILURE, ["1 JSC test failed"], 1,  """Results for JSC stress tests:
136     1 failure found.""")
137
138     def test_jsc_stress_failures_new_output(self):
139         self.assertResults(FAILURE, ["5 JSC tests failed"], 1,  """Results for JSC stress tests:
140     5 failures found.""")
141
142
143 class RunLLINTCLoopTestsTest(unittest.TestCase):
144     def assertResults(self, expected_result, expected_text, rc, stdio):
145         cmd = StubRemoteCommand(rc, stdio)
146         step = RunLLINTCLoopTests()
147         step.commandComplete(cmd)
148         actual_results = step.evaluateCommand(cmd)
149         actual_text = step.getText2(cmd, actual_results)
150
151         self.assertEqual(expected_result, actual_results)
152         self.assertEqual(actual_text, expected_text)
153
154     def test_failures(self):
155         self.assertResults(FAILURE, ['5 regressions found.'], 1,  '    5 regressions found.')
156
157     def test_failure(self):
158         self.assertResults(FAILURE, ['1 regression found.'], 1,  '    1 regression found.')
159
160     def test_no_failure(self):
161         self.assertResults(SUCCESS, ['webkit-jsc-cloop-test'], 0,  '    0 regressions found.')
162
163
164 class Run32bitJSCTestsTest(unittest.TestCase):
165     def assertResults(self, expected_result, expected_text, rc, stdio):
166         cmd = StubRemoteCommand(rc, stdio)
167         step = Run32bitJSCTests()
168         step.commandComplete(cmd)
169         actual_results = step.evaluateCommand(cmd)
170         actual_text = step.getText2(cmd, actual_results)
171
172         self.assertEqual(expected_result, actual_results)
173         self.assertEqual(actual_text, expected_text)
174
175     def test_failures(self):
176         self.assertResults(FAILURE, ['5 regressions found.'], 1,  '    5 failures found.')
177
178     def test_failure(self):
179         self.assertResults(FAILURE, ['1 regression found.'], 1,  '    1 failure found.')
180
181     def test_no_failure(self):
182         self.assertResults(SUCCESS, ['webkit-32bit-jsc-test'], 0,  '    0 failures found.')
183
184
185 class RunUnitTestsTest(unittest.TestCase):
186     def assertFailures(self, expected_failure_count, stdio):
187         if expected_failure_count:
188             rc = 1
189             expected_results = FAILURE
190             plural_suffix = "" if expected_failure_count == 1 else "s"
191             expected_text = '%d unit test%s failed or timed out' % (expected_failure_count, plural_suffix)
192         else:
193             rc = 0
194             expected_results = SUCCESS
195             expected_text = 'run-api-tests'
196
197         cmd = StubRemoteCommand(rc, stdio)
198         step = RunUnitTests()
199         step.commandComplete(cmd)
200         actual_results = step.evaluateCommand(cmd)
201         actual_failure_count = step.failedTestCount
202         actual_text = step.getText(cmd, actual_results)[0]
203
204         self.assertEqual(expected_results, actual_results)
205         self.assertEqual(expected_failure_count, actual_failure_count)
206         self.assertEqual(expected_text, actual_text)
207
208     def test_no_failures_or_timeouts(self):
209         self.assertFailures(0, """Note: Google Test filter = WebViewDestructionWithHostWindow.DestroyViewWindowWithoutClose
210 [==========] Running 1 test from 1 test case.
211 [----------] Global test environment set-up.
212 [----------] 1 test from WebViewDestructionWithHostWindow
213 [ RUN      ] WebViewDestructionWithHostWindow.DestroyViewWindowWithoutClose
214 [       OK ] WebViewDestructionWithHostWindow.DestroyViewWindowWithoutClose (127 ms)
215 [----------] 1 test from WebViewDestructionWithHostWindow (127 ms total)
216
217 [----------] Global test environment tear-down
218 [==========] 1 test from 1 test case ran. (127 ms total)
219 [  PASSED  ] 1 test.
220 """)
221
222     def test_one_failure(self):
223         self.assertFailures(1, """Note: Google Test filter = WebViewDestructionWithHostWindow.DestroyViewWindowWithoutClose
224 [==========] Running 1 test from 1 test case.
225 [----------] Global test environment set-up.
226 [----------] 1 test from WebViewDestructionWithHostWindow
227 [ RUN      ] WebViewDestructionWithHostWindow.DestroyViewWindowWithoutClose
228 [       OK ] WebViewDestructionWithHostWindow.DestroyViewWindowWithoutClose (127 ms)
229 [----------] 1 test from WebViewDestructionWithHostWindow (127 ms total)
230
231 [----------] Global test environment tear-down
232 [==========] 1 test from 1 test case ran. (127 ms total)
233 [  PASSED  ] 1 test.
234 Tests that failed:
235   WebKit2.WebKit2.CanHandleRequest
236 """)
237
238     def test_multiple_failures(self):
239         self.assertFailures(4, """Note: Google Test filter = WebViewDestructionWithHostWindow.DestroyViewWindowWithoutClose
240 [==========] Running 1 test from 1 test case.
241 [----------] Global test environment set-up.
242 [----------] 1 test from WebViewDestructionWithHostWindow
243 [ RUN      ] WebViewDestructionWithHostWindow.DestroyViewWindowWithoutClose
244 [       OK ] WebViewDestructionWithHostWindow.DestroyViewWindowWithoutClose (127 ms)
245 [----------] 1 test from WebViewDestructionWithHostWindow (127 ms total)
246
247 [----------] Global test environment tear-down
248 [==========] 1 test from 1 test case ran. (127 ms total)
249 [  PASSED  ] 1 test.
250 Tests that failed:
251   WebKit2.WebKit2.CanHandleRequest
252   WebKit2.WebKit2.DocumentStartUserScriptAlertCrashTest
253   WebKit2.WebKit2.HitTestResultNodeHandle
254   WebKit2.WebKit2.InjectedBundleBasic
255 """)
256
257     def test_one_timeout(self):
258         self.assertFailures(1, """Note: Google Test filter = WebViewDestructionWithHostWindow.DestroyViewWindowWithoutClose
259 [==========] Running 1 test from 1 test case.
260 [----------] Global test environment set-up.
261 [----------] 1 test from WebViewDestructionWithHostWindow
262 [ RUN      ] WebViewDestructionWithHostWindow.DestroyViewWindowWithoutClose
263 [       OK ] WebViewDestructionWithHostWindow.DestroyViewWindowWithoutClose (127 ms)
264 [----------] 1 test from WebViewDestructionWithHostWindow (127 ms total)
265
266 [----------] Global test environment tear-down
267 [==========] 1 test from 1 test case ran. (127 ms total)
268 [  PASSED  ] 1 test.
269 Tests that timed out:
270   WebKit2.WebKit2.CanHandleRequest
271 """)
272
273     def test_multiple_timeouts(self):
274         self.assertFailures(4, """Note: Google Test filter = WebViewDestructionWithHostWindow.DestroyViewWindowWithoutClose
275 [==========] Running 1 test from 1 test case.
276 [----------] Global test environment set-up.
277 [----------] 1 test from WebViewDestructionWithHostWindow
278 [ RUN      ] WebViewDestructionWithHostWindow.DestroyViewWindowWithoutClose
279 [       OK ] WebViewDestructionWithHostWindow.DestroyViewWindowWithoutClose (127 ms)
280 [----------] 1 test from WebViewDestructionWithHostWindow (127 ms total)
281
282 [----------] Global test environment tear-down
283 [==========] 1 test from 1 test case ran. (127 ms total)
284 [  PASSED  ] 1 test.
285 Tests that timed out:
286   WebKit2.WebKit2.CanHandleRequest
287   WebKit2.WebKit2.DocumentStartUserScriptAlertCrashTest
288   WebKit2.WebKit2.HitTestResultNodeHandle
289   WebKit2.WebKit2.InjectedBundleBasic
290 """)
291
292     def test_multiple_failures_and_timeouts(self):
293         self.assertFailures(8, """Note: Google Test filter = WebViewDestructionWithHostWindow.DestroyViewWindowWithoutClose
294 [==========] Running 1 test from 1 test case.
295 [----------] Global test environment set-up.
296 [----------] 1 test from WebViewDestructionWithHostWindow
297 [ RUN      ] WebViewDestructionWithHostWindow.DestroyViewWindowWithoutClose
298 [       OK ] WebViewDestructionWithHostWindow.DestroyViewWindowWithoutClose (127 ms)
299 [----------] 1 test from WebViewDestructionWithHostWindow (127 ms total)
300
301 [----------] Global test environment tear-down
302 [==========] 1 test from 1 test case ran. (127 ms total)
303 [  PASSED  ] 1 test.
304 Tests that failed:
305   WebKit2.WebKit2.CanHandleRequest
306   WebKit2.WebKit2.DocumentStartUserScriptAlertCrashTest
307   WebKit2.WebKit2.HitTestResultNodeHandle
308 Tests that timed out:
309   WebKit2.WebKit2.InjectedBundleBasic
310   WebKit2.WebKit2.LoadCanceledNoServerRedirectCallback
311   WebKit2.WebKit2.MouseMoveAfterCrash
312   WebKit2.WebKit2.ResponsivenessTimerDoesntFireEarly
313   WebKit2.WebKit2.WebArchive
314 """)
315
316
317 class SVNMirrorTest(unittest.TestCase):
318     def setUp(self):
319         self.config = json.load(open('config.json'))
320
321     def get_SVNMirrorFromConfig(self, builderName):
322         SVNMirror = None
323         for builder in self.config['builders']:
324             if builder['name'] == builderName:
325                 SVNMirror = builder.pop('SVNMirror', 'https://svn.webkit.org/repository/webkit/')
326         return SVNMirror
327
328     def test_CheckOutSource(self):
329         # SVN mirror feature isn't unittestable now with source.oldsource.SVN(==source.SVN) , only with source.svn.SVN(==SVN)
330         # https://bugs.webkit.org/show_bug.cgi?id=85887
331         if issubclass(CheckOutSource, source.SVN):
332             return
333
334         # Compare CheckOutSource.baseURL with SVNMirror (or with the default URL) in config.json for all builders
335         for builder in c['builders']:
336             for buildStepFactory, kwargs in builder['factory'].steps:
337                 if str(buildStepFactory).split('.')[-1] == 'CheckOutSource':
338                         CheckOutSourceInstance = buildStepFactory(**kwargs)
339                         self.assertEqual(CheckOutSourceInstance.baseURL, self.get_SVNMirrorFromConfig(builder['name']))
340
341
342 class BuildStepsConstructorTest(unittest.TestCase):
343     # "Passing a BuildStep subclass to factory.addStep is deprecated. Please pass a BuildStep instance instead.  Support will be dropped in v0.8.7."
344     # It checks if all builder's all buildsteps can be insantiated after migration.
345     # https://bugs.webkit.org/show_bug.cgi?id=89001
346     # http://buildbot.net/buildbot/docs/0.8.6p1/manual/customization.html#writing-buildstep-constructors
347
348     @staticmethod
349     def generateTests():
350         for builderNumber, builder in enumerate(c['builders']):
351             for stepNumber, step in enumerate(builder['factory'].steps):
352                 builderName = builder['name'].encode('ascii', 'ignore')
353                 setattr(BuildStepsConstructorTest, 'test_builder%02d_step%02d' % (builderNumber, stepNumber), BuildStepsConstructorTest.createTest(builderName, step))
354
355     @staticmethod
356     def createTest(builderName, step):
357         def doTest(self):
358             try:
359                 buildStepFactory, kwargs = step
360                 buildStepFactory(**kwargs)
361             except TypeError as e:
362                 buildStepName = str(buildStepFactory).split('.')[-1]
363                 self.fail("Error during instantiation %s buildstep for %s builder: %s\n" % (buildStepName, builderName, e))
364         return doTest
365
366
367 expected_build_steps = {
368     'Apple Win 7 Debug (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile', 'download-built-product', 'extract-built-product', 'jscore-test', 'layout-test', 'run-api-tests', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'archive-test-results', 'upload', 'MasterShellCommand'],
369     'Apple Win 7 Release (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile', 'download-built-product', 'extract-built-product', 'jscore-test', 'layout-test', 'run-api-tests', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'archive-test-results', 'upload', 'MasterShellCommand'],
370     'Apple Win Debug (Build)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile', 'compile-webkit', 'archive-built-product', 'upload', 'trigger'],
371     'Apple Win Release (Build)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile', 'compile-webkit', 'archive-built-product', 'upload', 'trigger'],
372
373     'Apple El Capitan 32-bit JSC (BuildAndTest)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit', 'webkit-32bit-jsc-test'],
374     'Apple El Capitan CMake Debug (Build)' :['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit'],
375     'Apple El Capitan Debug (Build)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit', 'archive-built-product', 'upload', 'trigger'],
376     'Apple El Capitan Debug JSC (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'download-built-product', 'extract-built-product', 'jscore-test'],
377     'Apple El Capitan Debug WK1 (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'download-built-product', 'extract-built-product', 'layout-test', 'run-api-tests', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'archive-test-results', 'upload', 'MasterShellCommand'],
378     'Apple El Capitan Debug WK2 (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'download-built-product', 'extract-built-product', 'layout-test', 'run-api-tests', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'archive-test-results', 'upload', 'MasterShellCommand'],
379     'Apple El Capitan LLINT CLoop (BuildAndTest)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit', 'webkit-jsc-cloop-test'],
380     'Apple El Capitan Release (32-bit Build)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit'],
381     'Apple El Capitan Release (Build)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit', 'archive-built-product', 'upload', 'trigger'],
382     'Apple El Capitan Release WK2 (Perf)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'download-built-product', 'extract-built-product', 'perf-test'],
383     'Apple El Capitan Release JSC (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'download-built-product', 'extract-built-product', 'jscore-test'],
384     'Apple El Capitan Release WK1 (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'download-built-product', 'extract-built-product', 'layout-test', 'run-api-tests', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'archive-test-results', 'upload', 'MasterShellCommand'],
385     'Apple El Capitan Release WK2 (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'download-built-product', 'extract-built-product', 'layout-test', 'run-api-tests', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'archive-test-results', 'upload', 'MasterShellCommand'],
386
387     'Apple Sierra 32-bit JSC (BuildAndTest)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit', 'webkit-32bit-jsc-test'],
388     'Apple Sierra (Leaks)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'download-built-product', 'extract-built-product', 'layout-test', 'archive-test-results', 'upload', 'MasterShellCommand'],
389     'Apple Sierra Debug (Build)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit', 'archive-built-product', 'upload', 'trigger'],
390     'Apple Sierra Debug JSC (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'download-built-product', 'extract-built-product', 'jscore-test'],
391     'Apple Sierra Debug WK1 (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'download-built-product', 'extract-built-product', 'layout-test', 'run-api-tests', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'archive-test-results', 'upload', 'MasterShellCommand'],
392     'Apple Sierra Debug WK2 (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'download-built-product', 'extract-built-product', 'layout-test', 'run-api-tests', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'archive-test-results', 'upload', 'MasterShellCommand'],
393     'Apple Sierra LLINT CLoop (BuildAndTest)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit', 'webkit-jsc-cloop-test'],
394     'Apple Sierra Release (32-bit Build)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit'],
395     'Apple Sierra Release (Build)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit', 'archive-built-product', 'upload', 'trigger'],
396     'Apple Sierra Release JSC (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'download-built-product', 'extract-built-product', 'jscore-test'],
397     'Apple Sierra Release WK1 (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'download-built-product', 'extract-built-product', 'layout-test', 'run-api-tests', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'archive-test-results', 'upload', 'MasterShellCommand'],
398     'Apple Sierra Release WK2 (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'download-built-product', 'extract-built-product', 'layout-test', 'run-api-tests', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'archive-test-results', 'upload', 'MasterShellCommand'],
399
400     'Apple iOS 10 Release (Build)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit'],
401     'Apple iOS 10 Simulator Release (Build)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit', 'archive-built-product', 'upload', 'trigger'],
402     'Apple iOS 10 Simulator Release WK1 (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'download-built-product', 'extract-built-product', 'layout-test', 'run-api-tests', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'archive-test-results', 'upload', 'MasterShellCommand'],
403     'Apple iOS 10 Simulator Release WK2 (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'download-built-product', 'extract-built-product', 'layout-test', 'run-api-tests', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'archive-test-results', 'upload', 'MasterShellCommand'],
404
405     'Apple iOS 10 Simulator Debug (Build)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit', 'archive-built-product', 'upload', 'trigger'],
406     'Apple iOS 10 Simulator Debug WK1 (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'download-built-product', 'extract-built-product', 'layout-test', 'run-api-tests', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'archive-test-results', 'upload', 'MasterShellCommand'],
407     'Apple iOS 10 Simulator Debug WK2 (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'download-built-product', 'extract-built-product', 'layout-test', 'run-api-tests', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'archive-test-results', 'upload', 'MasterShellCommand'],
408
409     'JSCOnly Linux ARMv7 Thumb2 Release' : ['configure build', 'wait-for-svn-server', 'svn', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit', 'jscore-test'],
410     'JSCOnly Linux ARMv7 Traditional Release' : ['configure build', 'wait-for-svn-server', 'svn', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit', 'jscore-test'],
411     'JSCOnly Linux AArch64 Release' : ['configure build', 'wait-for-svn-server', 'svn', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit', 'jscore-test'],
412
413     'GTK Linux 32-bit Release' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'jhbuild', 'compile-webkit', 'jscore-test', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'API tests'],
414     'GTK Linux 64-bit Debug (Build)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'jhbuild', 'compile-webkit', 'archive-built-product', 'upload', 'trigger'],
415     'GTK Linux 64-bit Debug (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'jhbuild', 'download-built-product', 'extract-built-product', 'jscore-test', 'layout-test', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'archive-test-results', 'upload', 'MasterShellCommand', 'API tests'],
416     'GTK Linux 64-bit Release (Build)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'jhbuild', 'compile-webkit', 'archive-built-product', 'upload', 'trigger'],
417     'GTK Linux 64-bit Release (Perf)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'jhbuild', 'download-built-product', 'extract-built-product', 'perf-test', 'benchmark-test'],
418     'GTK Linux 64-bit Release (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'jhbuild', 'download-built-product', 'extract-built-product', 'jscore-test', 'layout-test', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'archive-test-results', 'upload', 'MasterShellCommand', 'API tests'],
419     'GTK Linux 64-bit Release Wayland (Tests)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'jhbuild', 'download-built-product', 'extract-built-product', 'jscore-test', 'layout-test', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'archive-test-results', 'upload', 'MasterShellCommand', 'API tests'],
420     'GTK Linux 64-bit Release Ubuntu LTS (Build)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit'],
421     'GTK Linux 64-bit Release Debian Stable (Build)' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit'],
422     'GTK Linux ARM Release' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'jhbuild', 'compile-webkit', 'jscore-test', 'webkitpy-test', 'webkitperl-test', 'bindings-generation-tests', 'builtins-generator-tests', 'dashboard-tests', 'API tests'],
423
424     'WinCairo 64-Bit Release' : ['configure build', 'svn', 'kill old processes', 'delete WebKitBuild directory', 'delete stale build files', 'compile-webkit'],
425 }
426
427
428 class BuildStepsTest(unittest.TestCase):
429     @staticmethod
430     def generateTests():
431         for builder in c['builders']:
432             builderName = builder['name'].encode('ascii', 'ignore')
433             setattr(BuildStepsTest, 'test_builder %s' % builderName, BuildStepsTest.createTest(builder))
434
435     @staticmethod
436     def createTest(builder):
437         def doTest(self):
438             buildSteps = []
439             for step in builder['factory'].steps:
440                 buildSteps.append(step[0].name)
441             self.assertTrue(builder['name'] in expected_build_steps, "Missing expected result for builder: %s\n Actual result is %s" % (builder['name'], buildSteps))
442             self.assertListEqual(expected_build_steps[builder['name']], buildSteps)
443
444         return doTest
445
446     def test_unnecessary_expected_results(self):
447         builders = set()
448         for builder in c['builders']:
449             builders.add(builder['name'].encode('ascii', 'ignore'))
450
451         for builder in expected_build_steps:
452             self.assertTrue(builder in builders, "Builder %s doesn't exist, but has unnecessary expected results" % builder)
453
454
455 class RunAndUploadPerfTestsTest(unittest.TestCase):
456     def assertResults(self, rc, expected_text):
457         cmd = StubRemoteCommand(rc, expected_text)
458         step = RunAndUploadPerfTests()
459         step.commandComplete(cmd)
460         actual_results = step.evaluateCommand(cmd)
461         actual_text = str(step.getText2(cmd, actual_results)[0])
462         self.assertEqual(expected_text, actual_text)
463
464     def test_success(self):
465         self.assertResults(0, "perf-test")
466
467     def test_tests_failed(self):
468         self.assertResults(5, "5 perf tests failed")
469
470     def test_build_bad_build(self):
471         self.assertResults(255, "build not up to date")
472
473     def test_build_bad_source_json(self):
474         self.assertResults(254, "slave config JSON error")
475
476     def test_build_bad_marge(self):
477         self.assertResults(253, "output JSON merge error")
478
479     def test_build_bad_failed_uploading(self):
480         self.assertResults(252, "upload error")
481
482     def test_build_bad_preparation(self):
483         self.assertResults(251, "system dependency error")
484
485     def test_buildbot_timeout(self):
486         self.assertResults(-1, "timeout")
487
488
489 class RunBenchmarkTest(unittest.TestCase):
490     def assertResults(self, rc, expected_text):
491         cmd = StubRemoteCommand(rc, expected_text)
492         step = RunBenchmarkTests()
493         step.commandComplete(cmd)
494         actual_results = step.evaluateCommand(cmd)
495         actual_text = str(step.getText2(cmd, actual_results)[0])
496         self.assertEqual(expected_text, actual_text)
497
498     def test_success(self):
499         self.assertResults(0, "benchmark-test")
500
501     def test_tests_failed(self):
502         self.assertResults(7, "7 benchmark tests failed")
503
504
505 # FIXME: We should run this file as part of test-webkitpy.
506 # Unfortunately test-webkitpy currently requires that unittests
507 # be located in a directory with a valid module name.
508 # 'build.webkit.org-config' is not a valid module name (due to '.' and '-')
509 # so for now this is a stand-alone test harness.
510 if __name__ == '__main__':
511     BuildBotConfigLoader().load_config('master.cfg')
512     BuildStepsConstructorTest.generateTests()
513     BuildStepsTest.generateTests()
514     unittest.main()