9370db57b129229f82f0f72e8fae529243c03605
[WebKit-https.git] / Tools / BuildSlaveSupport / ews-build / steps_unittest.py
1 # Copyright (C) 2018-2019 Apple 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
5 # are met:
6 # 1.  Redistributions of source code must retain the above copyright
7 #     notice, this list of conditions and the following disclaimer.
8 # 2.  Redistributions in binary form must reproduce the above copyright
9 #     notice, this list of conditions and the following disclaimer in the
10 #     documentation and/or other materials provided with the distribution.
11 #
12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
13 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15 # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
16 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
19 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
20 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
21 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22
23 import operator
24 import os
25 import shutil
26 import tempfile
27
28 from buildbot.process import remotetransfer
29 from buildbot.process.results import Results, SUCCESS, FAILURE, WARNINGS, SKIPPED, EXCEPTION, RETRY
30 from buildbot.test.fake.remotecommand import Expect, ExpectRemoteRef, ExpectShell
31 from buildbot.test.util.steps import BuildStepMixin
32 from mock import call
33 from twisted.internet import error, reactor
34 from twisted.python import failure, log
35 from twisted.trial import unittest
36
37 from steps import (AnalyzeAPITestsResults, AnalyzeCompileWebKitResults, ApplyPatch, ArchiveBuiltProduct, ArchiveTestResults,
38                    CheckOutSource, CheckOutSpecificRevision, CheckPatchRelevance, CheckStyle, CleanBuild, CleanWorkingDirectory,
39                    CompileJSCOnly, CompileJSCOnlyToT, CompileWebKit, CompileWebKitToT, ConfigureBuild,
40                    DownloadBuiltProduct, ExtractBuiltProduct, ExtractTestResults, KillOldProcesses,
41                    PrintConfiguration, ReRunAPITests, ReRunJavaScriptCoreTests, RunAPITests, RunAPITestsWithoutPatch,
42                    RunBindingsTests, RunJavaScriptCoreTests, RunJavaScriptCoreTestsToT, RunWebKit1Tests, RunWebKitPerlTests,
43                    RunWebKitPyTests, RunWebKitTests, TestWithFailureCount, Trigger, TransferToS3, UnApplyPatchIfRequired,
44                    UploadBuiltProduct, UploadTestResults, ValidatePatch)
45
46 # Workaround for https://github.com/buildbot/buildbot/issues/4669
47 from buildbot.test.fake.fakebuild import FakeBuild
48 FakeBuild.addStepsAfterCurrentStep = lambda FakeBuild, step_factories: None
49
50
51 def mock_step(step, logs='', results=SUCCESS, stopped=False, properties=None):
52     step.logs = logs
53     step.results = results
54     step.stopped = stopped
55     return step
56
57
58 class ExpectMasterShellCommand(object):
59     def __init__(self, command, workdir=None, env=None, usePTY=0):
60         self.args = command
61         self.usePTY = usePTY
62         self.rc = None
63         self.path = None
64         self.logs = []
65
66         if env is not None:
67             self.env = env
68         else:
69             self.env = os.environ
70         if workdir:
71             self.path = os.path.join(os.getcwd(), workdir)
72
73     @classmethod
74     def log(self, name, value):
75         return ('log', name, value)
76
77     def __add__(self, other):
78         if isinstance(other, int):
79             self.rc = other
80         elif isinstance(other, tuple) and other[0] == 'log':
81             self.logs.append((other[1], other[2]))
82         return self
83
84     def __repr__(self):
85         return 'ExpectMasterShellCommand({0})'.format(repr(self.args))
86
87
88 class BuildStepMixinAdditions(BuildStepMixin):
89     def setUpBuildStep(self):
90         self.patch(reactor, 'spawnProcess', lambda *args, **kwargs: self._checkSpawnProcess(*args, **kwargs))
91         self._expected_local_commands = []
92
93         self._temp_directory = tempfile.mkdtemp()
94         os.chdir(self._temp_directory)
95         self._expected_uploaded_files = []
96
97         super(BuildStepMixinAdditions, self).setUpBuildStep()
98
99     def tearDownBuildStep(self):
100         shutil.rmtree(self._temp_directory)
101         super(BuildStepMixinAdditions, self).tearDownBuildStep()
102
103     def fakeBuildFinished(self, text, results):
104         self.build.text = text
105         self.build.results = results
106
107     def setupStep(self, step, *args, **kwargs):
108         self.previous_steps = kwargs.get('previous_steps') or []
109         if self.previous_steps:
110             del kwargs['previous_steps']
111
112         super(BuildStepMixinAdditions, self).setupStep(step, *args, **kwargs)
113         self.build.terminate = False
114         self.build.stopped = False
115         self.build.executedSteps = self.executedSteps
116         self.build.buildFinished = self.fakeBuildFinished
117         self._expected_added_urls = []
118         self._expected_sources = None
119
120     @property
121     def executedSteps(self):
122         return filter(lambda step: not step.stopped, self.previous_steps)
123
124     def setProperty(self, name, value, source='Unknown'):
125         self.properties.setProperty(name, value, source)
126
127     def expectAddedURLs(self, added_urls):
128         self._expected_added_urls = added_urls
129
130     def expectUploadedFile(self, path):
131         self._expected_uploaded_files.append(path)
132
133     def expectLocalCommands(self, *expected_commands):
134         self._expected_local_commands.extend(expected_commands)
135
136     def expectRemoteCommands(self, *expected_commands):
137         self.expectCommands(*expected_commands)
138
139     def expectSources(self, expected_sources):
140         self._expected_sources = expected_sources
141
142     def _checkSpawnProcess(self, processProtocol, executable, args, env, path, usePTY, **kwargs):
143         got = (executable, args, env, path, usePTY)
144         if not self._expected_local_commands:
145             self.fail('got local command {0} when no further commands were expected'.format(got))
146         local_command = self._expected_local_commands.pop(0)
147         try:
148             self.assertEqual(got, (local_command.args[0], local_command.args, local_command.env, local_command.path, local_command.usePTY))
149         except AssertionError:
150             log.err()
151             raise
152         for name, value in local_command.logs:
153             if name == 'stdout':
154                 processProtocol.outReceived(value)
155             elif name == 'stderr':
156                 processProtocol.errReceived(value)
157         if local_command.rc != 0:
158             value = error.ProcessTerminated(exitCode=local_command.rc)
159         else:
160             value = error.ProcessDone(None)
161         processProtocol.processEnded(failure.Failure(value))
162
163     def _added_files(self):
164         results = []
165         for dirpath, dirnames, filenames in os.walk(self._temp_directory):
166             relative_root_path = os.path.relpath(dirpath, start=self._temp_directory)
167             if relative_root_path == '.':
168                 relative_root_path = ''
169             for name in filenames:
170                 results.append(os.path.join(relative_root_path, name))
171         return results
172
173     def runStep(self):
174         def check(result):
175             self.assertEqual(self._expected_local_commands, [], 'assert all expected local commands were run')
176             self.expectAddedURLs(self._expected_added_urls)
177             self.assertEqual(self._added_files(), self._expected_uploaded_files)
178             if self._expected_sources is not None:
179                 # Convert to dictionaries because assertEqual() only knows how to diff Python built-in types.
180                 actual_sources = sorted([source.asDict() for source in self.build.sources], key=operator.itemgetter('codebase'))
181                 expected_sources = sorted([source.asDict() for source in self._expected_sources], key=operator.itemgetter('codebase'))
182                 self.assertEqual(actual_sources, expected_sources)
183         deferred_result = super(BuildStepMixinAdditions, self).runStep()
184         deferred_result.addCallback(check)
185         return deferred_result
186
187
188 def uploadFileWithContentsOfString(string, timestamp=None):
189     def behavior(command):
190         writer = command.args['writer']
191         writer.remote_write(string + '\n')
192         writer.remote_close()
193         if timestamp:
194             writer.remote_utime(timestamp)
195     return behavior
196
197
198 class TestCheckStyle(BuildStepMixinAdditions, unittest.TestCase):
199     def setUp(self):
200         self.longMessage = True
201         return self.setUpBuildStep()
202
203     def tearDown(self):
204         return self.tearDownBuildStep()
205
206     def test_success_internal(self):
207         self.setupStep(CheckStyle())
208         self.setProperty('try-codebase', 'internal')
209         self.setProperty('platform', 'mac')
210         self.setProperty('configuration', 'debug')
211
212         self.expectRemoteCommands(
213             ExpectShell(workdir='wkdir',
214                         command=['Tools/Scripts/check-webkit-style'],
215                         )
216             + 0,
217         )
218         self.expectOutcome(result=SUCCESS, state_string='check-webkit-style')
219         return self.runStep()
220
221     def test_failure_unknown_try_codebase(self):
222         self.setupStep(CheckStyle())
223         self.setProperty('try-codebase', 'foo')
224         self.setProperty('platform', 'mac')
225         self.setProperty('configuration', 'debug')
226
227         self.expectRemoteCommands(
228             ExpectShell(workdir='wkdir',
229                         command=['Tools/Scripts/check-webkit-style'],
230                         )
231             + 2,
232         )
233         self.expectOutcome(result=FAILURE, state_string='check-webkit-style (failure)')
234         return self.runStep()
235
236     def test_failures_with_style_issues(self):
237         self.setupStep(CheckStyle())
238         self.setProperty('try-codebase', 'internal')
239         self.setProperty('platform', 'mac')
240         self.setProperty('configuration', 'debug')
241
242         self.expectRemoteCommands(
243             ExpectShell(workdir='wkdir',
244                         command=['Tools/Scripts/check-webkit-style'],
245                         )
246             + ExpectShell.log('stdio', stdout='''ERROR: Source/WebCore/layout/FloatingContext.cpp:36:  Code inside a namespace should not be indented.  [whitespace/indent] [4]
247 ERROR: Source/WebCore/layout/FormattingContext.h:94:  Weird number of spaces at line-start.  Are you using a 4-space indent?  [whitespace/indent] [3]
248 ERROR: Source/WebCore/layout/LayoutContext.cpp:52:  Place brace on its own line for function definitions.  [whitespace/braces] [4]
249 ERROR: Source/WebCore/layout/LayoutContext.cpp:55:  Extra space before last semicolon. If this should be an empty statement, use { } instead.  [whitespace/semicolon] [5]
250 ERROR: Source/WebCore/layout/LayoutContext.cpp:60:  Tab found; better to use spaces  [whitespace/tab] [1]
251 ERROR: Source/WebCore/layout/Verification.cpp:88:  Missing space before ( in while(  [whitespace/parens] [5]
252 Total errors found: 8 in 48 files''')
253             + 2,
254         )
255         self.expectOutcome(result=FAILURE, state_string='8 style errors (failure)')
256         return self.runStep()
257
258     def test_failures_no_style_issues(self):
259         self.setupStep(CheckStyle())
260         self.setProperty('try-codebase', 'internal')
261         self.setProperty('platform', 'mac')
262         self.setProperty('configuration', 'debug')
263
264         self.expectRemoteCommands(
265             ExpectShell(workdir='wkdir',
266                         command=['Tools/Scripts/check-webkit-style'],
267                         )
268             + ExpectShell.log('stdio', stdout='Total errors found: 0 in 6 files')
269             + 0,
270         )
271         self.expectOutcome(result=SUCCESS, state_string='check-webkit-style')
272         return self.runStep()
273
274     def test_failures_no_changes(self):
275         self.setupStep(CheckStyle())
276         self.setProperty('try-codebase', 'internal')
277         self.setProperty('platform', 'mac')
278         self.setProperty('configuration', 'debug')
279
280         self.expectRemoteCommands(
281             ExpectShell(workdir='wkdir',
282                         command=['Tools/Scripts/check-webkit-style'],
283                         )
284             + ExpectShell.log('stdio', stdout='Total errors found: 0 in 0 files')
285             + 2,
286         )
287         self.expectOutcome(result=FAILURE, state_string='check-webkit-style (failure)')
288         return self.runStep()
289
290
291 class TestRunBindingsTests(BuildStepMixinAdditions, unittest.TestCase):
292     def setUp(self):
293         self.longMessage = True
294         self.jsonFileName = 'bindings_test_results.json'
295         return self.setUpBuildStep()
296
297     def tearDown(self):
298         return self.tearDownBuildStep()
299
300     def test_success(self):
301         self.setupStep(RunBindingsTests())
302         self.expectRemoteCommands(
303             ExpectShell(workdir='wkdir',
304                         timeout=300,
305                         command=['Tools/Scripts/run-bindings-tests', '--json-output={0}'.format(self.jsonFileName)],
306                         logfiles={'json': self.jsonFileName},
307                         )
308             + 0,
309         )
310         self.expectOutcome(result=SUCCESS, state_string='Passed bindings tests')
311         return self.runStep()
312
313     def test_failure(self):
314         self.setupStep(RunBindingsTests())
315         self.expectRemoteCommands(
316             ExpectShell(workdir='wkdir',
317                         timeout=300,
318                         command=['Tools/Scripts/run-bindings-tests', '--json-output={0}'.format(self.jsonFileName)],
319                         logfiles={'json': self.jsonFileName},
320                         )
321             + ExpectShell.log('stdio', stdout='FAIL: (JS) JSTestInterface.cpp')
322             + 2,
323         )
324         self.expectOutcome(result=FAILURE, state_string='bindings-tests (failure)')
325         return self.runStep()
326
327
328 class TestRunWebKitPerlTests(BuildStepMixinAdditions, unittest.TestCase):
329     def setUp(self):
330         self.longMessage = True
331         return self.setUpBuildStep()
332
333     def tearDown(self):
334         return self.tearDownBuildStep()
335
336     def test_success(self):
337         self.setupStep(RunWebKitPerlTests())
338         self.expectRemoteCommands(
339             ExpectShell(workdir='wkdir',
340                         command=['Tools/Scripts/test-webkitperl'],
341                         timeout=120,
342                         )
343             + 0,
344         )
345         self.expectOutcome(result=SUCCESS, state_string='webkitperl-tests')
346         return self.runStep()
347
348     def test_failure(self):
349         self.setupStep(RunWebKitPerlTests())
350         self.expectRemoteCommands(
351             ExpectShell(workdir='wkdir',
352                         command=['Tools/Scripts/test-webkitperl'],
353                         timeout=120,
354                         )
355             + ExpectShell.log('stdio', stdout='''Failed tests:  1-3, 5-7, 9, 11-13
356 Files=40, Tests=630,  4 wallclock secs ( 0.16 usr  0.09 sys +  2.78 cusr  0.64 csys =  3.67 CPU)
357 Result: FAIL
358 Failed 1/40 test programs. 10/630 subtests failed.''')
359             + 2,
360         )
361         self.expectOutcome(result=FAILURE, state_string='webkitperl-tests (failure)')
362         return self.runStep()
363
364
365 class TestWebKitPyTests(BuildStepMixinAdditions, unittest.TestCase):
366     def setUp(self):
367         self.longMessage = True
368         self.jsonFileName = 'webkitpy_test_results.json'
369         return self.setUpBuildStep()
370
371     def tearDown(self):
372         return self.tearDownBuildStep()
373
374     def test_success(self):
375         self.setupStep(RunWebKitPyTests())
376         self.expectRemoteCommands(
377             ExpectShell(workdir='wkdir',
378                         command=['Tools/Scripts/test-webkitpy', '--json-output={0}'.format(self.jsonFileName)],
379                         logfiles={'json': self.jsonFileName},
380                         timeout=120,
381                         )
382             + 0,
383         )
384         self.expectOutcome(result=SUCCESS, state_string='Passed webkitpy tests')
385         return self.runStep()
386
387     def test_failure(self):
388         self.setupStep(RunWebKitPyTests())
389         self.expectRemoteCommands(
390             ExpectShell(workdir='wkdir',
391                         command=['Tools/Scripts/test-webkitpy', '--json-output={0}'.format(self.jsonFileName)],
392                         logfiles={'json': self.jsonFileName},
393                         timeout=120,
394                         )
395             + ExpectShell.log('stdio', stdout='''Ran 1744 tests in 5.913s
396 FAILED (failures=1, errors=0)''')
397             + 2,
398         )
399         self.expectOutcome(result=FAILURE, state_string='webkitpy-tests (failure)')
400         return self.runStep()
401
402
403 class TestKillOldProcesses(BuildStepMixinAdditions, unittest.TestCase):
404     def setUp(self):
405         self.longMessage = True
406         return self.setUpBuildStep()
407
408     def tearDown(self):
409         return self.tearDownBuildStep()
410
411     def test_success(self):
412         self.setupStep(KillOldProcesses())
413         self.expectRemoteCommands(
414             ExpectShell(workdir='wkdir',
415                         command=['python', 'Tools/BuildSlaveSupport/kill-old-processes', 'buildbot'],
416                         logEnviron=False,
417                         timeout=60,
418                         )
419             + 0,
420         )
421         self.expectOutcome(result=SUCCESS, state_string='Killed old processes')
422         return self.runStep()
423
424     def test_failure(self):
425         self.setupStep(KillOldProcesses())
426         self.expectRemoteCommands(
427             ExpectShell(workdir='wkdir',
428                         command=['python', 'Tools/BuildSlaveSupport/kill-old-processes', 'buildbot'],
429                         logEnviron=False,
430                         timeout=60,
431                         )
432             + ExpectShell.log('stdio', stdout='Unexpected error.')
433             + 2,
434         )
435         self.expectOutcome(result=FAILURE, state_string='Killed old processes (failure)')
436         return self.runStep()
437
438
439 class TestCleanBuild(BuildStepMixinAdditions, unittest.TestCase):
440     def setUp(self):
441         self.longMessage = True
442         return self.setUpBuildStep()
443
444     def tearDown(self):
445         return self.tearDownBuildStep()
446
447     def test_success(self):
448         self.setupStep(CleanBuild())
449         self.setProperty('fullPlatform', 'ios-11')
450         self.setProperty('configuration', 'release')
451         self.expectRemoteCommands(
452             ExpectShell(workdir='wkdir',
453                         command=['python', 'Tools/BuildSlaveSupport/clean-build', '--platform=ios-11', '--release'],
454                         )
455             + 0,
456         )
457         self.expectOutcome(result=SUCCESS, state_string='Deleted WebKitBuild directory')
458         return self.runStep()
459
460     def test_failure(self):
461         self.setupStep(CleanBuild())
462         self.setProperty('fullPlatform', 'ios-simulator-11')
463         self.setProperty('configuration', 'debug')
464         self.expectRemoteCommands(
465             ExpectShell(workdir='wkdir',
466                         command=['python', 'Tools/BuildSlaveSupport/clean-build', '--platform=ios-simulator-11', '--debug'],
467                         )
468             + ExpectShell.log('stdio', stdout='Unexpected error.')
469             + 2,
470         )
471         self.expectOutcome(result=FAILURE, state_string='Deleted WebKitBuild directory (failure)')
472         return self.runStep()
473
474
475 class TestCompileWebKit(BuildStepMixinAdditions, unittest.TestCase):
476     def setUp(self):
477         self.longMessage = True
478         return self.setUpBuildStep()
479
480     def tearDown(self):
481         return self.tearDownBuildStep()
482
483     def test_success(self):
484         self.setupStep(CompileWebKit())
485         self.setProperty('fullPlatform', 'ios-simulator-11')
486         self.setProperty('configuration', 'release')
487         self.expectRemoteCommands(
488             ExpectShell(workdir='wkdir',
489                         command=['perl', 'Tools/Scripts/build-webkit', '--release'],
490                         )
491             + 0,
492         )
493         self.expectOutcome(result=SUCCESS, state_string='Compiled WebKit')
494         return self.runStep()
495
496     def test_failure(self):
497         self.setupStep(CompileWebKit())
498         self.setProperty('fullPlatform', 'mac-sierra')
499         self.setProperty('configuration', 'debug')
500         self.expectRemoteCommands(
501             ExpectShell(workdir='wkdir',
502                         command=['perl', 'Tools/Scripts/build-webkit', '--debug'],
503                         )
504             + ExpectShell.log('stdio', stdout='1 error generated.')
505             + 2,
506         )
507         self.expectOutcome(result=FAILURE, state_string='Compiled WebKit (failure)')
508         return self.runStep()
509
510
511 class TestCompileWebKitToT(BuildStepMixinAdditions, unittest.TestCase):
512     def setUp(self):
513         self.longMessage = True
514         return self.setUpBuildStep()
515
516     def tearDown(self):
517         return self.tearDownBuildStep()
518
519     def test_success(self):
520         self.setupStep(CompileWebKitToT())
521         self.setProperty('fullPlatform', 'ios-simulator-11')
522         self.setProperty('configuration', 'release')
523         self.setProperty('patchFailedToBuild', True)
524         self.expectRemoteCommands(
525             ExpectShell(workdir='wkdir',
526                         command=['perl', 'Tools/Scripts/build-webkit', '--release'],
527                         )
528             + 0,
529         )
530         self.expectOutcome(result=SUCCESS, state_string='Compiled WebKit')
531         return self.runStep()
532
533     def test_failure(self):
534         self.setupStep(CompileWebKitToT())
535         self.setProperty('fullPlatform', 'mac-sierra')
536         self.setProperty('configuration', 'debug')
537         self.setProperty('patchFailedTests', True)
538         self.expectRemoteCommands(
539             ExpectShell(workdir='wkdir',
540                         command=['perl', 'Tools/Scripts/build-webkit', '--debug'],
541                         )
542             + ExpectShell.log('stdio', stdout='1 error generated.')
543             + 2,
544         )
545         self.expectOutcome(result=FAILURE, state_string='Compiled WebKit (failure)')
546         return self.runStep()
547
548     def test_skip(self):
549         self.setupStep(CompileWebKitToT())
550         self.setProperty('fullPlatform', 'ios-simulator-11')
551         self.setProperty('configuration', 'release')
552         self.expectHidden(True)
553         self.expectOutcome(result=SKIPPED, state_string='Compiled WebKit (skipped)')
554         return self.runStep()
555
556
557 class TestAnalyzeCompileWebKitResults(BuildStepMixinAdditions, unittest.TestCase):
558     def setUp(self):
559         self.longMessage = True
560         return self.setUpBuildStep()
561
562     def tearDown(self):
563         return self.tearDownBuildStep()
564
565     def test_patch_with_build_failure(self):
566         previous_steps = [
567             mock_step(CompileWebKit(), results=FAILURE),
568             mock_step(CompileWebKitToT(), results=SUCCESS),
569         ]
570         self.setupStep(AnalyzeCompileWebKitResults(), previous_steps=previous_steps)
571         self.expectOutcome(result=FAILURE, state_string='Patch does not build (failure)')
572         return self.runStep()
573
574     def test_patch_with_ToT_failure(self):
575         previous_steps = [
576             mock_step(CompileWebKit(), results=FAILURE),
577             mock_step(CompileWebKitToT(), results=FAILURE),
578         ]
579         self.setupStep(AnalyzeCompileWebKitResults(), previous_steps=previous_steps)
580         self.expectOutcome(result=FAILURE, state_string='Unable to build WebKit without patch, retrying build (failure)')
581         return self.runStep()
582
583
584 class TestCompileJSCOnly(BuildStepMixinAdditions, unittest.TestCase):
585     def setUp(self):
586         self.longMessage = True
587         return self.setUpBuildStep()
588
589     def tearDown(self):
590         return self.tearDownBuildStep()
591
592     def test_success(self):
593         self.setupStep(CompileJSCOnly())
594         self.setProperty('fullPlatform', 'jsc-only')
595         self.setProperty('configuration', 'release')
596         self.expectRemoteCommands(
597             ExpectShell(workdir='wkdir',
598                         command=['perl', 'Tools/Scripts/build-jsc', '--release'],
599                         )
600             + 0,
601         )
602         self.expectOutcome(result=SUCCESS, state_string='Compiled JSC')
603         return self.runStep()
604
605     def test_failure(self):
606         self.setupStep(CompileJSCOnly())
607         self.setProperty('fullPlatform', 'jsc-only')
608         self.setProperty('configuration', 'debug')
609         self.expectRemoteCommands(
610             ExpectShell(workdir='wkdir',
611                         command=['perl', 'Tools/Scripts/build-jsc', '--debug'],
612                         )
613             + ExpectShell.log('stdio', stdout='1 error generated.')
614             + 2,
615         )
616         self.expectOutcome(result=FAILURE, state_string='Compiled JSC (failure)')
617         return self.runStep()
618
619
620 class TestCompileJSCOnlyToT(BuildStepMixinAdditions, unittest.TestCase):
621     def setUp(self):
622         self.longMessage = True
623         return self.setUpBuildStep()
624
625     def tearDown(self):
626         return self.tearDownBuildStep()
627
628     def test_success(self):
629         self.setupStep(CompileJSCOnlyToT())
630         self.setProperty('fullPlatform', 'jsc-only')
631         self.setProperty('configuration', 'release')
632         self.setProperty('patchFailedToBuild', 'True')
633         self.expectRemoteCommands(
634             ExpectShell(workdir='wkdir',
635                         command=['perl', 'Tools/Scripts/build-jsc', '--release'],
636                         )
637             + 0,
638         )
639         self.expectOutcome(result=SUCCESS, state_string='Compiled JSC')
640         return self.runStep()
641
642     def test_failure(self):
643         self.setupStep(CompileJSCOnlyToT())
644         self.setProperty('fullPlatform', 'jsc-only')
645         self.setProperty('configuration', 'debug')
646         self.setProperty('patchFailedToBuild', 'True')
647         self.expectRemoteCommands(
648             ExpectShell(workdir='wkdir',
649                         command=['perl', 'Tools/Scripts/build-jsc', '--debug'],
650                         )
651             + ExpectShell.log('stdio', stdout='1 error generated.')
652             + 2,
653         )
654         self.expectOutcome(result=FAILURE, state_string='Compiled JSC (failure)')
655         return self.runStep()
656
657     def test_skip(self):
658         self.setupStep(CompileJSCOnlyToT())
659         self.setProperty('fullPlatform', 'jsc-only')
660         self.setProperty('configuration', 'debug')
661         self.expectHidden(True)
662         self.expectOutcome(result=SKIPPED, state_string='Compiled JSC (skipped)')
663         return self.runStep()
664
665
666 class TestRunJavaScriptCoreTests(BuildStepMixinAdditions, unittest.TestCase):
667     def setUp(self):
668         self.longMessage = True
669         self.jsonFileName = 'jsc_results.json'
670         return self.setUpBuildStep()
671
672     def tearDown(self):
673         return self.tearDownBuildStep()
674
675     def test_success(self):
676         self.setupStep(RunJavaScriptCoreTests())
677         self.setProperty('fullPlatform', 'jsc-only')
678         self.setProperty('configuration', 'release')
679         self.expectRemoteCommands(
680             ExpectShell(workdir='wkdir',
681                         command=['perl', 'Tools/Scripts/run-javascriptcore-tests', '--no-build', '--no-fail-fast', '--json-output={0}'.format(self.jsonFileName), '--release'],
682                         logfiles={'json': self.jsonFileName},
683                         )
684             + 0,
685         )
686         self.expectOutcome(result=SUCCESS, state_string='jscore-tests')
687         return self.runStep()
688
689     def test_failure(self):
690         self.setupStep(RunJavaScriptCoreTests())
691         self.setProperty('fullPlatform', 'jsc-only')
692         self.setProperty('configuration', 'debug')
693         self.expectRemoteCommands(
694             ExpectShell(workdir='wkdir',
695                         command=['perl', 'Tools/Scripts/run-javascriptcore-tests', '--no-build', '--no-fail-fast', '--json-output={0}'.format(self.jsonFileName), '--debug'],
696                         logfiles={'json': self.jsonFileName},
697                         )
698             + ExpectShell.log('stdio', stdout='9 failures found.')
699             + 2,
700         )
701         self.expectOutcome(result=FAILURE, state_string='jscore-tests (failure)')
702         return self.runStep()
703
704
705 class TestReRunJavaScriptCoreTests(BuildStepMixinAdditions, unittest.TestCase):
706     def setUp(self):
707         self.longMessage = True
708         self.jsonFileName = 'jsc_results.json'
709         return self.setUpBuildStep()
710
711     def tearDown(self):
712         return self.tearDownBuildStep()
713
714     def test_success(self):
715         self.setupStep(ReRunJavaScriptCoreTests())
716         self.setProperty('fullPlatform', 'jsc-only')
717         self.setProperty('configuration', 'release')
718         self.setProperty('patchFailedTests', 'True')
719         self.expectRemoteCommands(
720             ExpectShell(workdir='wkdir',
721                         command=['perl', 'Tools/Scripts/run-javascriptcore-tests', '--no-build', '--no-fail-fast', '--json-output={0}'.format(self.jsonFileName), '--release'],
722                         logfiles={'json': self.jsonFileName},
723                         )
724             + 0,
725         )
726         self.expectOutcome(result=SUCCESS, state_string='jscore-tests')
727         return self.runStep()
728
729     def test_failure(self):
730         self.setupStep(ReRunJavaScriptCoreTests())
731         self.setProperty('fullPlatform', 'jsc-only')
732         self.setProperty('configuration', 'debug')
733         self.setProperty('patchFailedTests', 'True')
734         self.expectRemoteCommands(
735             ExpectShell(workdir='wkdir',
736                         command=['perl', 'Tools/Scripts/run-javascriptcore-tests', '--no-build', '--no-fail-fast', '--json-output={0}'.format(self.jsonFileName), '--debug'],
737                         logfiles={'json': self.jsonFileName},
738                         )
739             + ExpectShell.log('stdio', stdout='9 failures found.')
740             + 2,
741         )
742         self.expectOutcome(result=FAILURE, state_string='jscore-tests (failure)')
743         return self.runStep()
744
745     def test_skip(self):
746         self.setupStep(ReRunJavaScriptCoreTests())
747         self.setProperty('fullPlatform', 'jsc-only')
748         self.setProperty('configuration', 'debug')
749         self.expectHidden(True)
750         self.expectOutcome(result=SKIPPED, state_string='jscore-tests (skipped)')
751         return self.runStep()
752
753
754 class TestRunJavaScriptCoreTestsToT(BuildStepMixinAdditions, unittest.TestCase):
755     def setUp(self):
756         self.longMessage = True
757         self.jsonFileName = 'jsc_results.json'
758         return self.setUpBuildStep()
759
760     def tearDown(self):
761         return self.tearDownBuildStep()
762
763     def test_success(self):
764         self.setupStep(RunJavaScriptCoreTestsToT())
765         self.setProperty('fullPlatform', 'jsc-only')
766         self.setProperty('configuration', 'release')
767         self.setProperty('patchFailedTests', 'True')
768         self.expectRemoteCommands(
769             ExpectShell(workdir='wkdir',
770                         command=['perl', 'Tools/Scripts/run-javascriptcore-tests', '--no-fail-fast', '--json-output={0}'.format(self.jsonFileName), '--release'],
771                         logfiles={'json': self.jsonFileName},
772                         )
773             + 0,
774         )
775         self.expectOutcome(result=SUCCESS, state_string='jscore-tests')
776         return self.runStep()
777
778     def test_failure(self):
779         self.setupStep(RunJavaScriptCoreTestsToT())
780         self.setProperty('fullPlatform', 'jsc-only')
781         self.setProperty('configuration', 'debug')
782         self.setProperty('patchFailedTests', 'True')
783         self.expectRemoteCommands(
784             ExpectShell(workdir='wkdir',
785                         command=['perl', 'Tools/Scripts/run-javascriptcore-tests', '--no-fail-fast', '--json-output={0}'.format(self.jsonFileName), '--debug'],
786                         logfiles={'json': self.jsonFileName},
787                         )
788             + ExpectShell.log('stdio', stdout='9 failures found.')
789             + 2,
790         )
791         self.expectOutcome(result=FAILURE, state_string='jscore-tests (failure)')
792         return self.runStep()
793
794     def test_skip(self):
795         self.setupStep(RunJavaScriptCoreTestsToT())
796         self.setProperty('fullPlatform', 'jsc-only')
797         self.setProperty('configuration', 'debug')
798         self.expectHidden(True)
799         self.expectOutcome(result=SKIPPED, state_string='jscore-tests (skipped)')
800         return self.runStep()
801
802
803 class TestRunWebKitTests(BuildStepMixinAdditions, unittest.TestCase):
804     def setUp(self):
805         self.longMessage = True
806         return self.setUpBuildStep()
807
808     def tearDown(self):
809         return self.tearDownBuildStep()
810
811     def test_success(self):
812         self.setupStep(RunWebKitTests())
813         self.setProperty('fullPlatform', 'ios-simulator')
814         self.setProperty('configuration', 'release')
815         self.expectRemoteCommands(
816             ExpectShell(workdir='wkdir',
817                         command=['python', 'Tools/Scripts/run-webkit-tests', '--no-build', '--no-new-test-results', '--no-show-results', '--exit-after-n-failures', '30', '--skip-failing-tests', '--release', '--results-directory', 'layout-test-results', '--debug-rwt-logging'],
818                         )
819             + 0,
820         )
821         self.expectOutcome(result=SUCCESS, state_string='Passed layout tests')
822         return self.runStep()
823
824     def test_failure(self):
825         self.setupStep(RunWebKitTests())
826         self.setProperty('fullPlatform', 'ios-simulator')
827         self.setProperty('configuration', 'release')
828         self.expectRemoteCommands(
829             ExpectShell(workdir='wkdir',
830                         command=['python', 'Tools/Scripts/run-webkit-tests', '--no-build', '--no-new-test-results', '--no-show-results', '--exit-after-n-failures', '30', '--skip-failing-tests', '--release', '--results-directory', 'layout-test-results', '--debug-rwt-logging'],
831                         )
832             + ExpectShell.log('stdio', stdout='9 failures found.')
833             + 2,
834         )
835         self.expectOutcome(result=FAILURE, state_string='layout-tests (failure)')
836         return self.runStep()
837
838
839 class TestRunWebKit1Tests(BuildStepMixinAdditions, unittest.TestCase):
840     def setUp(self):
841         self.longMessage = True
842         return self.setUpBuildStep()
843
844     def tearDown(self):
845         return self.tearDownBuildStep()
846
847     def test_success(self):
848         self.setupStep(RunWebKit1Tests())
849         self.setProperty('fullPlatform', 'ios-11')
850         self.setProperty('configuration', 'debug')
851         self.expectRemoteCommands(
852             ExpectShell(workdir='wkdir',
853                         command=['python', 'Tools/Scripts/run-webkit-tests', '--no-build', '--no-new-test-results', '--no-show-results', '--exit-after-n-failures', '30', '--skip-failing-tests', '--debug', '--dump-render-tree', '--results-directory', 'layout-test-results', '--debug-rwt-logging'],
854                         )
855             + 0,
856         )
857         self.expectOutcome(result=SUCCESS, state_string='Passed layout tests')
858         return self.runStep()
859
860     def test_failure(self):
861         self.setupStep(RunWebKit1Tests())
862         self.setProperty('fullPlatform', 'ios-11')
863         self.setProperty('configuration', 'release')
864         self.expectRemoteCommands(
865             ExpectShell(workdir='wkdir',
866                         command=['python', 'Tools/Scripts/run-webkit-tests', '--no-build', '--no-new-test-results', '--no-show-results', '--exit-after-n-failures', '30', '--skip-failing-tests', '--release', '--dump-render-tree', '--results-directory', 'layout-test-results', '--debug-rwt-logging'],
867                         )
868             + ExpectShell.log('stdio', stdout='9 failures found.')
869             + 2,
870         )
871         self.expectOutcome(result=FAILURE, state_string='layout-tests (failure)')
872         return self.runStep()
873
874
875 class TestCheckOutSpecificRevision(BuildStepMixinAdditions, unittest.TestCase):
876     def setUp(self):
877         self.longMessage = True
878         return self.setUpBuildStep()
879
880     def tearDown(self):
881         return self.tearDownBuildStep()
882
883     def test_success(self):
884         self.setupStep(CheckOutSpecificRevision())
885         self.setProperty('ews_revision', '1a3425cb92dbcbca12a10aa9514f1b77c76dc26')
886         self.expectHidden(False)
887         self.expectRemoteCommands(
888             ExpectShell(workdir='wkdir',
889                         timeout=1200,
890                         command=['git', 'checkout', '1a3425cb92dbcbca12a10aa9514f1b77c76dc26'],
891                         )
892             + 0,
893         )
894         self.expectOutcome(result=SUCCESS, state_string='Checked out required revision')
895         return self.runStep()
896
897     def test_failure(self):
898         self.setupStep(CheckOutSpecificRevision())
899         self.setProperty('ews_revision', '1a3425cb92dbcbca12a10aa9514f1b77c76dc26')
900         self.expectHidden(False)
901         self.expectRemoteCommands(
902             ExpectShell(workdir='wkdir',
903                         timeout=1200,
904                         command=['git', 'checkout', '1a3425cb92dbcbca12a10aa9514f1b77c76dc26'],
905                         )
906             + ExpectShell.log('stdio', stdout='Unexpected failure')
907             + 2,
908         )
909         self.expectOutcome(result=FAILURE, state_string='Checked out required revision (failure)')
910         return self.runStep()
911
912     def test_skip(self):
913         self.setupStep(CheckOutSpecificRevision())
914         self.expectHidden(True)
915         self.expectOutcome(result=SKIPPED, state_string='Checked out required revision (skipped)')
916         return self.runStep()
917
918
919 class TestCleanWorkingDirectory(BuildStepMixinAdditions, unittest.TestCase):
920     def setUp(self):
921         self.longMessage = True
922         return self.setUpBuildStep()
923
924     def tearDown(self):
925         return self.tearDownBuildStep()
926
927     def test_success(self):
928         self.setupStep(CleanWorkingDirectory())
929         self.expectRemoteCommands(
930             ExpectShell(workdir='wkdir',
931                         command=['Tools/Scripts/clean-webkit'],
932                         )
933             + 0,
934         )
935         self.expectOutcome(result=SUCCESS, state_string='Cleaned working directory')
936         return self.runStep()
937
938     def test_failure(self):
939         self.setupStep(CleanWorkingDirectory())
940         self.expectRemoteCommands(
941             ExpectShell(workdir='wkdir',
942                         command=['Tools/Scripts/clean-webkit'],
943                         )
944             + ExpectShell.log('stdio', stdout='Unexpected failure.')
945             + 2,
946         )
947         self.expectOutcome(result=FAILURE, state_string='Cleaned working directory (failure)')
948         return self.runStep()
949
950
951 class TestUnApplyPatchIfRequired(BuildStepMixinAdditions, unittest.TestCase):
952     def setUp(self):
953         self.longMessage = True
954         return self.setUpBuildStep()
955
956     def tearDown(self):
957         return self.tearDownBuildStep()
958
959     def test_success(self):
960         self.setupStep(UnApplyPatchIfRequired())
961         self.setProperty('patchFailedToBuild', True)
962         self.expectHidden(False)
963         self.expectRemoteCommands(
964             ExpectShell(workdir='wkdir',
965                         command=['Tools/Scripts/clean-webkit'],
966                         )
967             + 0,
968         )
969         self.expectOutcome(result=SUCCESS, state_string='Unapplied patch')
970         return self.runStep()
971
972     def test_failure(self):
973         self.setupStep(UnApplyPatchIfRequired())
974         self.setProperty('patchFailedTests', True)
975         self.expectHidden(False)
976         self.expectRemoteCommands(
977             ExpectShell(workdir='wkdir',
978                         command=['Tools/Scripts/clean-webkit'],
979                         )
980             + ExpectShell.log('stdio', stdout='Unexpected failure.')
981             + 2,
982         )
983         self.expectOutcome(result=FAILURE, state_string='Unapplied patch (failure)')
984         return self.runStep()
985
986     def test_skip(self):
987         self.setupStep(UnApplyPatchIfRequired())
988         self.expectHidden(True)
989         self.expectOutcome(result=SKIPPED, state_string='Unapplied patch (skipped)')
990         return self.runStep()
991
992
993 class TestArchiveBuiltProduct(BuildStepMixinAdditions, unittest.TestCase):
994     def setUp(self):
995         self.longMessage = True
996         return self.setUpBuildStep()
997
998     def tearDown(self):
999         return self.tearDownBuildStep()
1000
1001     def test_success(self):
1002         self.setupStep(ArchiveBuiltProduct())
1003         self.setProperty('fullPlatform', 'ios-simulator')
1004         self.setProperty('configuration', 'release')
1005         self.expectRemoteCommands(
1006             ExpectShell(workdir='wkdir',
1007                         logEnviron=False,
1008                         command=['python', 'Tools/BuildSlaveSupport/built-product-archive', '--platform=ios-simulator',  '--release', 'archive'],
1009                         )
1010             + 0,
1011         )
1012         self.expectOutcome(result=SUCCESS, state_string='Archived built product')
1013         return self.runStep()
1014
1015     def test_failure(self):
1016         self.setupStep(ArchiveBuiltProduct())
1017         self.setProperty('fullPlatform', 'mac-sierra')
1018         self.setProperty('configuration', 'debug')
1019         self.expectRemoteCommands(
1020             ExpectShell(workdir='wkdir',
1021                         logEnviron=False,
1022                         command=['python', 'Tools/BuildSlaveSupport/built-product-archive', '--platform=mac-sierra',  '--debug', 'archive'],
1023                         )
1024             + ExpectShell.log('stdio', stdout='Unexpected failure.')
1025             + 2,
1026         )
1027         self.expectOutcome(result=FAILURE, state_string='Archived built product (failure)')
1028         return self.runStep()
1029
1030
1031 class TestUploadBuiltProduct(BuildStepMixinAdditions, unittest.TestCase):
1032     def setUp(self):
1033         self.longMessage = True
1034         return self.setUpBuildStep()
1035
1036     def tearDown(self):
1037         return self.tearDownBuildStep()
1038
1039     def test_success(self):
1040         self.setupStep(UploadBuiltProduct())
1041         self.setProperty('fullPlatform', 'mac-sierra')
1042         self.setProperty('configuration', 'release')
1043         self.setProperty('architecture', 'x86_64')
1044         self.setProperty('patch_id', '1234')
1045         self.expectHidden(False)
1046         self.expectRemoteCommands(
1047             Expect('uploadFile', dict(
1048                                         workersrc='WebKitBuild/release.zip', workdir='wkdir',
1049                                         blocksize=1024 * 256, maxsize=None, keepstamp=False,
1050                                         writer=ExpectRemoteRef(remotetransfer.FileWriter),
1051                                      ))
1052             + Expect.behavior(uploadFileWithContentsOfString('Dummy zip file content.'))
1053             + 0,
1054         )
1055         self.expectUploadedFile('public_html/archives/mac-sierra-x86_64-release/1234.zip')
1056
1057         self.expectOutcome(result=SUCCESS, state_string='Uploaded built product')
1058         return self.runStep()
1059
1060     def test_failure(self):
1061         self.setupStep(UploadBuiltProduct())
1062         self.setProperty('fullPlatform', 'mac-sierra')
1063         self.setProperty('configuration', 'release')
1064         self.setProperty('architecture', 'x86_64')
1065         self.setProperty('patch_id', '1234')
1066         self.expectHidden(False)
1067         self.expectRemoteCommands(
1068             Expect('uploadFile', dict(
1069                                         workersrc='WebKitBuild/release.zip', workdir='wkdir',
1070                                         blocksize=1024 * 256, maxsize=None, keepstamp=False,
1071                                         writer=ExpectRemoteRef(remotetransfer.FileWriter),
1072                                      ))
1073             + Expect.behavior(uploadFileWithContentsOfString('Dummy zip file content.'))
1074             + 1,
1075         )
1076         self.expectUploadedFile('public_html/archives/mac-sierra-x86_64-release/1234.zip')
1077
1078         self.expectOutcome(result=FAILURE, state_string='Failed to upload built product')
1079         return self.runStep()
1080
1081
1082 class TestDownloadBuiltProduct(BuildStepMixinAdditions, unittest.TestCase):
1083     def setUp(self):
1084         self.longMessage = True
1085         return self.setUpBuildStep()
1086
1087     def tearDown(self):
1088         return self.tearDownBuildStep()
1089
1090     def test_success(self):
1091         self.setupStep(DownloadBuiltProduct())
1092         self.setProperty('fullPlatform', 'ios-simulator-12')
1093         self.setProperty('configuration', 'release')
1094         self.setProperty('architecture', 'x86_64')
1095         self.setProperty('patch_id', '1234')
1096         self.expectRemoteCommands(
1097             ExpectShell(workdir='wkdir',
1098                         logEnviron=False,
1099                         command=['python', 'Tools/BuildSlaveSupport/download-built-product', '--release', 'https://s3-us-west-2.amazonaws.com/ews-archives.webkit.org/ios-simulator-12-x86_64-release/1234.zip'],
1100                         )
1101             + 0,
1102         )
1103         self.expectOutcome(result=SUCCESS, state_string='Downloaded built product')
1104         return self.runStep()
1105
1106     def test_failure(self):
1107         self.setupStep(DownloadBuiltProduct())
1108         self.setProperty('fullPlatform', 'mac-sierra')
1109         self.setProperty('configuration', 'debug')
1110         self.setProperty('architecture', 'x86_64')
1111         self.setProperty('patch_id', '123456')
1112         self.expectRemoteCommands(
1113             ExpectShell(workdir='wkdir',
1114                         logEnviron=False,
1115                         command=['python', 'Tools/BuildSlaveSupport/download-built-product', '--debug', 'https://s3-us-west-2.amazonaws.com/ews-archives.webkit.org/mac-sierra-x86_64-debug/123456.zip'],
1116                         )
1117             + ExpectShell.log('stdio', stdout='Unexpected failure.')
1118             + 2,
1119         )
1120         self.expectOutcome(result=FAILURE, state_string='Failed to download built product from S3')
1121         return self.runStep()
1122
1123
1124 class TestExtractBuiltProduct(BuildStepMixinAdditions, unittest.TestCase):
1125     def setUp(self):
1126         self.longMessage = True
1127         return self.setUpBuildStep()
1128
1129     def tearDown(self):
1130         return self.tearDownBuildStep()
1131
1132     def test_success(self):
1133         self.setupStep(ExtractBuiltProduct())
1134         self.setProperty('fullPlatform', 'ios-simulator')
1135         self.setProperty('configuration', 'release')
1136         self.expectRemoteCommands(
1137             ExpectShell(workdir='wkdir',
1138                         logEnviron=False,
1139                         command=['python', 'Tools/BuildSlaveSupport/built-product-archive', '--platform=ios-simulator',  '--release', 'extract'],
1140                         )
1141             + 0,
1142         )
1143         self.expectOutcome(result=SUCCESS, state_string='Extracted built product')
1144         return self.runStep()
1145
1146     def test_failure(self):
1147         self.setupStep(ExtractBuiltProduct())
1148         self.setProperty('fullPlatform', 'mac-sierra')
1149         self.setProperty('configuration', 'debug')
1150         self.expectRemoteCommands(
1151             ExpectShell(workdir='wkdir',
1152                         logEnviron=False,
1153                         command=['python', 'Tools/BuildSlaveSupport/built-product-archive', '--platform=mac-sierra',  '--debug', 'extract'],
1154                         )
1155             + ExpectShell.log('stdio', stdout='Unexpected failure.')
1156             + 2,
1157         )
1158         self.expectOutcome(result=FAILURE, state_string='Extracted built product (failure)')
1159         return self.runStep()
1160
1161
1162 class TestTransferToS3(BuildStepMixinAdditions, unittest.TestCase):
1163     def setUp(self):
1164         self.longMessage = True
1165         return self.setUpBuildStep()
1166
1167     def tearDown(self):
1168         return self.tearDownBuildStep()
1169
1170     def test_success(self):
1171         self.setupStep(TransferToS3())
1172         self.setProperty('fullPlatform', 'mac-highsierra')
1173         self.setProperty('configuration', 'release')
1174         self.setProperty('architecture', 'x86_64')
1175         self.setProperty('patch_id', '1234')
1176         self.expectLocalCommands(
1177             ExpectMasterShellCommand(command=['python',
1178                                               '../Shared/transfer-archive-to-s3',
1179                                               '--patch_id', '1234',
1180                                               '--identifier', 'mac-highsierra-x86_64-release',
1181                                               '--archive', 'public_html/archives/mac-highsierra-x86_64-release/1234.zip',
1182                                              ])
1183             + 0,
1184         )
1185         self.expectOutcome(result=SUCCESS, state_string='Transferred archive to S3')
1186         return self.runStep()
1187
1188     def test_failure(self):
1189         self.setupStep(TransferToS3())
1190         self.setProperty('fullPlatform', 'ios-simulator-12')
1191         self.setProperty('configuration', 'debug')
1192         self.setProperty('architecture', 'x86_64')
1193         self.setProperty('patch_id', '1234')
1194         self.expectLocalCommands(
1195             ExpectMasterShellCommand(command=['python',
1196                                               '../Shared/transfer-archive-to-s3',
1197                                               '--patch_id', '1234',
1198                                               '--identifier', 'ios-simulator-12-x86_64-debug',
1199                                               '--archive', 'public_html/archives/ios-simulator-12-x86_64-debug/1234.zip',
1200                                              ])
1201             + 2,
1202         )
1203         self.expectOutcome(result=FAILURE, state_string='Failed to transfer archive to S3')
1204         return self.runStep()
1205
1206
1207 class TestRunAPITests(BuildStepMixinAdditions, unittest.TestCase):
1208     def setUp(self):
1209         self.longMessage = True
1210         self.jsonFileName = 'api_test_results.json'
1211         return self.setUpBuildStep()
1212
1213     def tearDown(self):
1214         return self.tearDownBuildStep()
1215
1216     def test_success_mac(self):
1217         self.setupStep(RunAPITests())
1218         self.setProperty('fullPlatform', 'mac-mojave')
1219         self.setProperty('platform', 'mac')
1220         self.setProperty('configuration', 'release')
1221
1222         self.expectRemoteCommands(
1223             ExpectShell(workdir='wkdir',
1224                         logEnviron=False,
1225                         command=['python', 'Tools/Scripts/run-api-tests', '--no-build', '--release', '--verbose', '--json-output={0}'.format(self.jsonFileName)],
1226                         logfiles={'json': self.jsonFileName},
1227                         )
1228             + ExpectShell.log('stdio', stdout='''...
1229 worker/0 TestWTF.WTF_Variant.OperatorAmpersand Passed
1230 worker/0 TestWTF.WTF_Variant.Ref Passed
1231 worker/0 TestWTF.WTF_Variant.RefPtr Passed
1232 worker/0 TestWTF.WTF_Variant.RetainPtr Passed
1233 worker/0 TestWTF.WTF_Variant.VisitorUsingMakeVisitor Passed
1234 worker/0 TestWTF.WTF_Variant.VisitorUsingSwitchOn Passed
1235 Ran 1888 tests of 1888 with 1888 successful
1236 ------------------------------
1237 All tests successfully passed!
1238 ''')
1239             + 0,
1240         )
1241         self.expectOutcome(result=SUCCESS, state_string='run-api-tests')
1242         return self.runStep()
1243
1244     def test_success_ios_simulator(self):
1245         self.setupStep(RunAPITests())
1246         self.setProperty('fullPlatform', 'ios-simulator-11')
1247         self.setProperty('platform', 'ios')
1248         self.setProperty('configuration', 'debug')
1249
1250         self.expectRemoteCommands(
1251             ExpectShell(workdir='wkdir',
1252                         logEnviron=False,
1253                         command=['python', 'Tools/Scripts/run-api-tests', '--no-build', '--debug', '--verbose', '--json-output={0}'.format(self.jsonFileName), '--ios-simulator'],
1254                         logfiles={'json': self.jsonFileName},
1255                         )
1256             + ExpectShell.log('stdio', stdout='''...
1257 worker/0 TestWTF.WTF_Variant.OperatorAmpersand Passed
1258 worker/0 TestWTF.WTF_Variant.Ref Passed
1259 worker/0 TestWTF.WTF_Variant.RefPtr Passed
1260 worker/0 TestWTF.WTF_Variant.RetainPtr Passed
1261 worker/0 TestWTF.WTF_Variant.VisitorUsingMakeVisitor Passed
1262 worker/0 TestWTF.WTF_Variant.VisitorUsingSwitchOn Passed
1263 Ran 1888 tests of 1888 with 1888 successful
1264 ------------------------------
1265 All tests successfully passed!
1266 ''')
1267             + 0,
1268         )
1269         self.expectOutcome(result=SUCCESS, state_string='run-api-tests')
1270         return self.runStep()
1271
1272     def test_one_failure(self):
1273         self.setupStep(RunAPITests())
1274         self.setProperty('fullPlatform', 'mac-mojave')
1275         self.setProperty('platform', 'mac')
1276         self.setProperty('configuration', 'debug')
1277
1278         self.expectRemoteCommands(
1279             ExpectShell(workdir='wkdir',
1280                         logEnviron=False,
1281                         command=['python', 'Tools/Scripts/run-api-tests', '--no-build', '--debug', '--verbose', '--json-output={0}'.format(self.jsonFileName)],
1282                         logfiles={'json': self.jsonFileName},
1283                         )
1284             + ExpectShell.log('stdio', stdout='''
1285 worker/0 TestWTF.WTF_Variant.OperatorAmpersand Passed
1286 worker/0 TestWTF.WTF_Variant.Ref Passed
1287 worker/0 TestWTF.WTF_Variant.RefPtr Passed
1288 worker/0 TestWTF.WTF_Variant.RetainPtr Passed
1289 worker/0 TestWTF.WTF_Variant.VisitorUsingMakeVisitor Passed
1290 worker/0 TestWTF.WTF_Variant.VisitorUsingSwitchOn Passed
1291 worker/0 exiting
1292 Ran 1888 tests of 1888 with 1887 successful
1293 ------------------------------
1294 Test suite failed
1295
1296 Crashed
1297
1298     TestWTF.WTF.StringConcatenate_Unsigned
1299         **FAIL** WTF.StringConcatenate_Unsigned
1300
1301         Tools\\TestWebKitAPI\\Tests\\WTF\\StringConcatenate.cpp:84
1302         Value of: makeString('hello ', static_cast<unsigned short>(42) , ' world')
1303           Actual: hello 42 world
1304         Expected: 'hello * world'
1305         Which is: 74B00C9C
1306
1307 Testing completed, Exit status: 3
1308 ''')
1309             + 1,
1310         )
1311         self.expectOutcome(result=FAILURE, state_string='1 api test failed or timed out (failure)')
1312         return self.runStep()
1313
1314     def test_multiple_failures_and_timeouts(self):
1315         self.setupStep(RunAPITests())
1316         self.setProperty('fullPlatform', 'mac-mojave')
1317         self.setProperty('platform', 'mac')
1318         self.setProperty('configuration', 'debug')
1319
1320         self.expectRemoteCommands(
1321             ExpectShell(workdir='wkdir',
1322                         logEnviron=False,
1323                         command=['python', 'Tools/Scripts/run-api-tests', '--no-build', '--debug', '--verbose', '--json-output={0}'.format(self.jsonFileName)],
1324                         logfiles={'json': self.jsonFileName},
1325                         )
1326             + ExpectShell.log('stdio', stdout='''...
1327 worker/0 TestWTF.WTF_Variant.OperatorAmpersand Passed
1328 worker/0 TestWTF.WTF_Variant.Ref Passed
1329 worker/0 TestWTF.WTF_Variant.RefPtr Passed
1330 worker/0 TestWTF.WTF_Variant.RetainPtr Passed
1331 worker/0 TestWTF.WTF_Variant.VisitorUsingMakeVisitor Passed
1332 worker/0 TestWTF.WTF_Variant.VisitorUsingSwitchOn Passed
1333 worker/0 exiting
1334 Ran 1888 tests of 1888 with 1884 successful
1335 ------------------------------
1336 Test suite failed
1337
1338 Failed
1339
1340     TestWTF.WTF.StringConcatenate_Unsigned
1341         **FAIL** WTF.StringConcatenate_Unsigned
1342
1343         Tools\\TestWebKitAPI\\Tests\\WTF\\StringConcatenate.cpp:84
1344         Value of: makeString('hello ', static_cast<unsigned short>(42) , ' world')
1345           Actual: hello 42 world
1346         Expected: 'hello * world'
1347         Which is: 74B00C9C
1348
1349     TestWTF.WTF_Expected.Unexpected
1350         **FAIL** WTF_Expected.Unexpected
1351
1352         Tools\TestWebKitAPI\Tests\WTF\Expected.cpp:96
1353         Value of: s1
1354           Actual: oops
1355         Expected: s0
1356         Which is: oops
1357
1358 Timeout
1359
1360     TestWTF.WTF_PoisonedUniquePtrForTriviallyDestructibleArrays.Assignment
1361     TestWTF.WTF_Lock.ContendedShortSection
1362
1363 Testing completed, Exit status: 3
1364 ''')
1365             + 4,
1366         )
1367         self.expectOutcome(result=FAILURE, state_string='4 api tests failed or timed out (failure)')
1368         return self.runStep()
1369
1370     def test_unexpected_failure(self):
1371         self.setupStep(RunAPITests())
1372         self.setProperty('fullPlatform', 'mac-mojave')
1373         self.setProperty('platform', 'mac')
1374         self.setProperty('configuration', 'debug')
1375
1376         self.expectRemoteCommands(
1377             ExpectShell(workdir='wkdir',
1378                         logEnviron=False,
1379                         command=['python', 'Tools/Scripts/run-api-tests', '--no-build', '--debug', '--verbose', '--json-output={0}'.format(self.jsonFileName)],
1380                         logfiles={'json': self.jsonFileName},
1381                         )
1382             + ExpectShell.log('stdio', stdout='Unexpected failure. Failed to run api tests.')
1383             + 2,
1384         )
1385         self.expectOutcome(result=FAILURE, state_string='run-api-tests (failure)')
1386         return self.runStep()
1387
1388     def test_no_failures_or_timeouts_with_disabled(self):
1389         self.setupStep(RunAPITests())
1390         self.setProperty('fullPlatform', 'mac-mojave')
1391         self.setProperty('platform', 'mac')
1392         self.setProperty('configuration', 'debug')
1393
1394         self.expectRemoteCommands(
1395             ExpectShell(workdir='wkdir',
1396                         logEnviron=False,
1397                         command=['python', 'Tools/Scripts/run-api-tests', '--no-build', '--debug', '--verbose', '--json-output={0}'.format(self.jsonFileName)],
1398                         logfiles={'json': self.jsonFileName},
1399                         )
1400             + ExpectShell.log('stdio', stdout='''...
1401 worker/0 TestWTF.WTF_Variant.OperatorAmpersand Passed
1402 worker/0 TestWTF.WTF_Variant.Ref Passed
1403 worker/0 TestWTF.WTF_Variant.RefPtr Passed
1404 worker/0 TestWTF.WTF_Variant.RetainPtr Passed
1405 worker/0 TestWTF.WTF_Variant.VisitorUsingMakeVisitor Passed
1406 worker/0 TestWTF.WTF_Variant.VisitorUsingSwitchOn Passed
1407 worker/0 exiting
1408 Ran 1881 tests of 1888 with 1881 successful
1409 ------------------------------
1410 All tests successfully passed!
1411 ''')
1412             + 0,
1413         )
1414         self.expectOutcome(result=SUCCESS, state_string='run-api-tests')
1415         return self.runStep()
1416
1417
1418 class TestArchiveTestResults(BuildStepMixinAdditions, unittest.TestCase):
1419     def setUp(self):
1420         self.longMessage = True
1421         return self.setUpBuildStep()
1422
1423     def tearDown(self):
1424         return self.tearDownBuildStep()
1425
1426     def test_success(self):
1427         self.setupStep(ArchiveTestResults())
1428         self.setProperty('fullPlatform', 'ios-simulator')
1429         self.setProperty('platform', 'ios-simulator')
1430         self.setProperty('configuration', 'release')
1431         self.expectRemoteCommands(
1432             ExpectShell(workdir='wkdir',
1433                         command=['python', 'Tools/BuildSlaveSupport/test-result-archive', '--platform=ios-simulator',  '--release', 'archive'],
1434                         )
1435             + 0,
1436         )
1437         self.expectOutcome(result=SUCCESS, state_string='Archived test results')
1438         return self.runStep()
1439
1440     def test_failure(self):
1441         self.setupStep(ArchiveTestResults())
1442         self.setProperty('fullPlatform', 'mac-mojave')
1443         self.setProperty('platform', 'mac')
1444         self.setProperty('configuration', 'debug')
1445         self.expectRemoteCommands(
1446             ExpectShell(workdir='wkdir',
1447                         command=['python', 'Tools/BuildSlaveSupport/test-result-archive', '--platform=mac',  '--debug', 'archive'],
1448                         )
1449             + ExpectShell.log('stdio', stdout='Unexpected failure.')
1450             + 2,
1451         )
1452         self.expectOutcome(result=FAILURE, state_string='Archived test results (failure)')
1453         return self.runStep()
1454
1455
1456 class TestUploadTestResults(BuildStepMixinAdditions, unittest.TestCase):
1457     def setUp(self):
1458         self.longMessage = True
1459         return self.setUpBuildStep()
1460
1461     def tearDown(self):
1462         return self.tearDownBuildStep()
1463
1464     def test_success(self):
1465         self.setupStep(UploadTestResults())
1466         self.setProperty('configuration', 'release')
1467         self.setProperty('architecture', 'x86_64')
1468         self.setProperty('patch_id', '1234')
1469         self.setProperty('buildername', 'macOS-Sierra-Release-WK2-Tests-EWS')
1470         self.setProperty('buildnumber', '12')
1471         self.expectHidden(False)
1472         self.expectRemoteCommands(
1473             Expect('uploadFile', dict(
1474                                         workersrc='layout-test-results.zip', workdir='wkdir',
1475                                         blocksize=1024 * 256, maxsize=None, keepstamp=False,
1476                                         writer=ExpectRemoteRef(remotetransfer.FileWriter),
1477                                      ))
1478             + Expect.behavior(uploadFileWithContentsOfString('Dummy zip file content.'))
1479             + 0,
1480         )
1481         self.expectUploadedFile('public_html/results/macOS-Sierra-Release-WK2-Tests-EWS/r1234-12.zip')
1482
1483         self.expectOutcome(result=SUCCESS, state_string='Uploaded test results')
1484         return self.runStep()
1485
1486     def test_success_with_identifier(self):
1487         self.setupStep(UploadTestResults(identifier='clean-tree'))
1488         self.setProperty('configuration', 'release')
1489         self.setProperty('architecture', 'x86_64')
1490         self.setProperty('patch_id', '271211')
1491         self.setProperty('buildername', 'iOS-12-Simulator-WK2-Tests-EWS')
1492         self.setProperty('buildnumber', '120')
1493         self.expectHidden(False)
1494         self.expectRemoteCommands(
1495             Expect('uploadFile', dict(
1496                                         workersrc='layout-test-results.zip', workdir='wkdir',
1497                                         blocksize=1024 * 256, maxsize=None, keepstamp=False,
1498                                         writer=ExpectRemoteRef(remotetransfer.FileWriter),
1499                                      ))
1500             + Expect.behavior(uploadFileWithContentsOfString('Dummy zip file content.'))
1501             + 0,
1502         )
1503         self.expectUploadedFile('public_html/results/iOS-12-Simulator-WK2-Tests-EWS/r271211-120-clean-tree.zip')
1504
1505         self.expectOutcome(result=SUCCESS, state_string='Uploaded test results')
1506         return self.runStep()
1507
1508
1509 class TestExtractTestResults(BuildStepMixinAdditions, unittest.TestCase):
1510     def setUp(self):
1511         self.longMessage = True
1512         return self.setUpBuildStep()
1513
1514     def tearDown(self):
1515         return self.tearDownBuildStep()
1516
1517     def test_success(self):
1518         self.setupStep(ExtractTestResults())
1519         self.setProperty('configuration', 'release')
1520         self.setProperty('patch_id', '1234')
1521         self.setProperty('buildername', 'macOS-Sierra-Release-WK2-Tests-EWS')
1522         self.setProperty('buildnumber', '12')
1523         self.expectLocalCommands(
1524             ExpectMasterShellCommand(command=['unzip',
1525                                               'public_html/results/macOS-Sierra-Release-WK2-Tests-EWS/r1234-12.zip',
1526                                               '-d',
1527                                               'public_html/results/macOS-Sierra-Release-WK2-Tests-EWS/r1234-12',
1528                                              ])
1529             + 0,
1530         )
1531         self.expectOutcome(result=SUCCESS, state_string='Extracted test results')
1532         self.expectAddedURLs([call('view layout test results', '/results/test/r2468_ab1a28b4feee0d42973c7c05335b35bca927e974 (1)/results.html')])
1533         return self.runStep()
1534
1535     def test_success_with_identifier(self):
1536         self.setupStep(ExtractTestResults(identifier='rerun'))
1537         self.setProperty('configuration', 'release')
1538         self.setProperty('patch_id', '1234')
1539         self.setProperty('buildername', 'iOS-12-Simulator-WK2-Tests-EWS')
1540         self.setProperty('buildnumber', '12')
1541         self.expectLocalCommands(
1542             ExpectMasterShellCommand(command=['unzip',
1543                                               'public_html/results/iOS-12-Simulator-WK2-Tests-EWS/r1234-12-rerun.zip',
1544                                               '-d',
1545                                               'public_html/results/iOS-12-Simulator-WK2-Tests-EWS/r1234-12-rerun',
1546                                              ])
1547             + 0,
1548         )
1549         self.expectOutcome(result=SUCCESS, state_string='Extracted test results')
1550         self.expectAddedURLs([call('view layout test results', '/results/test/r2468_ab1a28b4feee0d42973c7c05335b35bca927e974 (1)/results.html')])
1551         return self.runStep()
1552
1553     def test_failure(self):
1554         self.setupStep(ExtractTestResults())
1555         self.setProperty('configuration', 'debug')
1556         self.setProperty('patch_id', '1234')
1557         self.setProperty('buildername', 'macOS-Sierra-Release-WK2-Tests-EWS')
1558         self.setProperty('buildnumber', '12')
1559         self.expectLocalCommands(
1560             ExpectMasterShellCommand(command=['unzip',
1561                                               'public_html/results/macOS-Sierra-Release-WK2-Tests-EWS/r1234-12.zip',
1562                                               '-d',
1563                                               'public_html/results/macOS-Sierra-Release-WK2-Tests-EWS/r1234-12',
1564                                              ])
1565             + 2,
1566         )
1567         self.expectOutcome(result=FAILURE, state_string='failed (2) (failure)')
1568         self.expectAddedURLs([call('view layout test results', '/results/test/r2468_ab1a28b4feee0d42973c7c05335b35bca927e974 (1)/results.html')])
1569         return self.runStep()
1570
1571
1572 class TestPrintConfiguration(BuildStepMixinAdditions, unittest.TestCase):
1573     def setUp(self):
1574         self.longMessage = True
1575         return self.setUpBuildStep()
1576
1577     def tearDown(self):
1578         return self.tearDownBuildStep()
1579
1580     def test_success_mac(self):
1581         self.setupStep(PrintConfiguration())
1582         self.setProperty('buildername', 'macOS-High-Sierra-Release-WK2-Tests-EWS')
1583         self.setProperty('platform', 'mac-highsierra')
1584
1585         self.expectRemoteCommands(
1586             ExpectShell(command=['hostname'], workdir='wkdir', timeout=60, logEnviron=False) + 0
1587             + ExpectShell.log('stdio', stdout='ews150.apple.com'),
1588             ExpectShell(command=['df', '-hl'], workdir='wkdir', timeout=60, logEnviron=False) + 0
1589             + ExpectShell.log('stdio', stdout='''Filesystem     Size   Used  Avail Capacity iused  ifree %iused  Mounted on
1590 /dev/disk1s1  119Gi   95Gi   23Gi    81%  937959 9223372036853837848    0%   /
1591 /dev/disk1s4  119Gi   20Ki   23Gi     1%       0 9223372036854775807    0%   /private/var/vm
1592 /dev/disk0s3  119Gi   22Gi   97Gi    19%  337595          4294629684    0%   /Volumes/Data'''),
1593             ExpectShell(command=['date'], workdir='wkdir', timeout=60, logEnviron=False) + 0
1594             + ExpectShell.log('stdio', stdout='Tue Apr  9 15:30:52 PDT 2019'),
1595             ExpectShell(command=['sw_vers'], workdir='wkdir', timeout=60, logEnviron=False) + 0
1596             + ExpectShell.log('stdio', stdout='''ProductName:   Mac OS X
1597 ProductVersion: 10.13.4
1598 BuildVersion:   17E199'''),
1599             ExpectShell(command=['xcodebuild', '-sdk', '-version'], workdir='wkdir', timeout=60, logEnviron=False)
1600             + ExpectShell.log('stdio', stdout='''MacOSX10.13.sdk - macOS 10.13 (macosx10.13)
1601 SDKVersion: 10.13
1602 Path: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk
1603 PlatformVersion: 1.1
1604 PlatformPath: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform
1605 ProductBuildVersion: 17E189
1606 ProductCopyright: 1983-2018 Apple Inc.
1607 ProductName: Mac OS X
1608 ProductUserVisibleVersion: 10.13.4
1609 ProductVersion: 10.13.4
1610
1611 Xcode 9.4.1
1612 Build version 9F2000''')
1613             + 0,
1614         )
1615         self.expectOutcome(result=SUCCESS, state_string='OS: High Sierra (10.13.4), Xcode: 9.4.1')
1616         return self.runStep()
1617
1618     def test_success_ios_simulator(self):
1619         self.setupStep(PrintConfiguration())
1620         self.setProperty('buildername', 'macOS-Sierra-Release-WK2-Tests-EWS')
1621         self.setProperty('platform', 'ios-simulator-12')
1622
1623         self.expectRemoteCommands(
1624             ExpectShell(command=['hostname'], workdir='wkdir', timeout=60, logEnviron=False) + 0
1625             + ExpectShell.log('stdio', stdout='ews152.apple.com'),
1626             ExpectShell(command=['df', '-hl'], workdir='wkdir', timeout=60, logEnviron=False) + 0
1627             + ExpectShell.log('stdio', stdout='''Filesystem     Size   Used  Avail Capacity iused  ifree %iused  Mounted on
1628 /dev/disk1s1  119Gi   95Gi   23Gi    81%  937959 9223372036853837848    0%   /
1629 /dev/disk1s4  119Gi   20Ki   23Gi     1%       0 9223372036854775807    0%   /private/var/vm
1630 /dev/disk0s3  119Gi   22Gi   97Gi    19%  337595          4294629684    0%   /Volumes/Data'''),
1631             ExpectShell(command=['date'], workdir='wkdir', timeout=60, logEnviron=False) + 0
1632             + ExpectShell.log('stdio', stdout='Tue Apr  9 15:30:52 PDT 2019'),
1633             ExpectShell(command=['sw_vers'], workdir='wkdir', timeout=60, logEnviron=False) + 0
1634             + ExpectShell.log('stdio', stdout='''ProductName:   Mac OS X
1635 ProductVersion: 10.14.5
1636 BuildVersion:   18F132'''),
1637             ExpectShell(command=['xcodebuild', '-sdk', '-version'], workdir='wkdir', timeout=60, logEnviron=False)
1638             + ExpectShell.log('stdio', stdout='''iPhoneSimulator12.2.sdk - Simulator - iOS 12.2 (iphonesimulator12.2)
1639 SDKVersion: 12.2
1640 Path: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.2.sdk
1641 PlatformVersion: 12.2
1642 PlatformPath: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform
1643 BuildID: 15C4BAF8-4632-11E9-86EB-BA47F1FFAC3C
1644 ProductBuildVersion: 16E226
1645 ProductCopyright: 1983-2019 Apple Inc.
1646 ProductName: iPhone OS
1647 ProductVersion: 12.2
1648
1649 Xcode 10.2
1650 Build version 10E125''')
1651             + 0,
1652         )
1653         self.expectOutcome(result=SUCCESS, state_string='OS: Mojave (10.14.5), Xcode: 10.2')
1654         return self.runStep()
1655
1656     def test_success_webkitpy(self):
1657         self.setupStep(PrintConfiguration())
1658         self.setProperty('platform', '*')
1659
1660         self.expectRemoteCommands(
1661             ExpectShell(command=['hostname'], workdir='wkdir', timeout=60, logEnviron=False) + 0,
1662             ExpectShell(command=['df', '-hl'], workdir='wkdir', timeout=60, logEnviron=False) + 0,
1663             ExpectShell(command=['date'], workdir='wkdir', timeout=60, logEnviron=False) + 0,
1664             ExpectShell(command=['sw_vers'], workdir='wkdir', timeout=60, logEnviron=False) + 0
1665             + ExpectShell.log('stdio', stdout='''ProductName:   Mac OS X
1666 ProductVersion: 10.13.6
1667 BuildVersion:   17G7024'''),
1668             ExpectShell(command=['xcodebuild', '-sdk', '-version'], workdir='wkdir', timeout=60, logEnviron=False) + 0
1669             + ExpectShell.log('stdio', stdout='''Xcode 10.2\nBuild version 10E125'''),
1670         )
1671         self.expectOutcome(result=SUCCESS, state_string='OS: High Sierra (10.13.6), Xcode: 10.2')
1672         return self.runStep()
1673
1674     def test_success_linux_wpe(self):
1675         self.setupStep(PrintConfiguration())
1676         self.setProperty('platform', 'wpe')
1677
1678         self.expectRemoteCommands(
1679             ExpectShell(command=['hostname'], workdir='wkdir', timeout=60, logEnviron=False) + 0
1680             + ExpectShell.log('stdio', stdout='ews190'),
1681             ExpectShell(command=['df', '-hl'], workdir='wkdir', timeout=60, logEnviron=False) + 0
1682             + ExpectShell.log('stdio', stdout='''Filesystem     Size   Used  Avail Capacity iused  ifree %iused  Mounted on
1683 /dev/disk0s3  119Gi   22Gi   97Gi    19%  337595          4294629684    0%   /'''),
1684             ExpectShell(command=['date'], workdir='wkdir', timeout=60, logEnviron=False) + 0
1685             + ExpectShell.log('stdio', stdout='Tue Apr  9 15:30:52 PDT 2019'),
1686             ExpectShell(command=['uname', '-a'], workdir='wkdir', timeout=60, logEnviron=False) + 0
1687             + ExpectShell.log('stdio', stdout='''Linux kodama-ews 5.0.4-arch1-1-ARCH #1 SMP PREEMPT Sat Mar 23 21:00:33 UTC 2019 x86_64 GNU/Linux'''),
1688         )
1689         self.expectOutcome(result=SUCCESS, state_string='Printed configuration')
1690         return self.runStep()
1691
1692     def test_success_linux_gtk(self):
1693         self.setupStep(PrintConfiguration())
1694         self.setProperty('platform', 'gtk')
1695
1696         self.expectRemoteCommands(
1697             ExpectShell(command=['hostname'], workdir='wkdir', timeout=60, logEnviron=False) + 0,
1698             ExpectShell(command=['df', '-hl'], workdir='wkdir', timeout=60, logEnviron=False) + 0,
1699             ExpectShell(command=['date'], workdir='wkdir', timeout=60, logEnviron=False) + 0,
1700             ExpectShell(command=['uname', '-a'], workdir='wkdir', timeout=60, logEnviron=False) + 0,
1701         )
1702         self.expectOutcome(result=SUCCESS, state_string='Printed configuration')
1703         return self.runStep()
1704
1705     def test_success_win(self):
1706         self.setupStep(PrintConfiguration())
1707         self.setProperty('platform', 'win')
1708
1709         self.expectRemoteCommands(
1710             ExpectShell(command=['hostname'], workdir='wkdir', timeout=60, logEnviron=False) + 0,
1711             ExpectShell(command=['df', '-hl'], workdir='wkdir', timeout=60, logEnviron=False) + 0,
1712             ExpectShell(command=['date'], workdir='wkdir', timeout=60, logEnviron=False) + 0,
1713         )
1714         self.expectOutcome(result=SUCCESS, state_string='Printed configuration')
1715         return self.runStep()
1716
1717     def test_failure(self):
1718         self.setupStep(PrintConfiguration())
1719         self.setProperty('platform', 'ios-12')
1720         self.expectRemoteCommands(
1721             ExpectShell(command=['hostname'], workdir='wkdir', timeout=60, logEnviron=False) + 0,
1722             ExpectShell(command=['df', '-hl'], workdir='wkdir', timeout=60, logEnviron=False) + 0,
1723             ExpectShell(command=['date'], workdir='wkdir', timeout=60, logEnviron=False) + 0,
1724             ExpectShell(command=['sw_vers'], workdir='wkdir', timeout=60, logEnviron=False) + 1
1725             + ExpectShell.log('stdio', stdout='''Upon execvpe sw_vers ['sw_vers'] in environment id 7696545650400
1726 :Traceback (most recent call last):
1727   File "/usr/lib/python2.7/site-packages/twisted/internet/process.py", line 445, in _fork
1728     environment)
1729   File "/usr/lib/python2.7/site-packages/twisted/internet/process.py", line 523, in _execChild
1730     os.execvpe(executable, args, environment)
1731   File "/usr/lib/python2.7/os.py", line 355, in execvpe
1732     _execvpe(file, args, env)
1733   File "/usr/lib/python2.7/os.py", line 382, in _execvpe
1734     func(fullname, *argrest)
1735 OSError: [Errno 2] No such file or directory'''),
1736             ExpectShell(command=['xcodebuild', '-sdk', '-version'], workdir='wkdir', timeout=60, logEnviron=False)
1737             + ExpectShell.log('stdio', stdout='''Upon execvpe xcodebuild ['xcodebuild', '-sdk', '-version'] in environment id 7696545612416
1738 :Traceback (most recent call last):
1739   File "/usr/lib/python2.7/site-packages/twisted/internet/process.py", line 445, in _fork
1740     environment)
1741   File "/usr/lib/python2.7/site-packages/twisted/internet/process.py", line 523, in _execChild
1742     os.execvpe(executable, args, environment)
1743   File "/usr/lib/python2.7/os.py", line 355, in execvpe
1744     _execvpe(file, args, env)
1745   File "/usr/lib/python2.7/os.py", line 382, in _execvpe
1746     func(fullname, *argrest)
1747 OSError: [Errno 2] No such file or directory''')
1748             + 1,
1749         )
1750         self.expectOutcome(result=FAILURE, state_string='Failed to print configuration')
1751         return self.runStep()
1752
1753
1754 if __name__ == '__main__':
1755     unittest.main()