blob: c8c262e1541d4bf9a1c75959ce3fccbd86151d0b [file] [log] [blame]
# Copyright (C) 2018-2021 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import inspect
import json
import operator
import os
import shutil
import sys
import tempfile
from buildbot.process import remotetransfer
from buildbot.process.results import Results, SUCCESS, FAILURE, WARNINGS, SKIPPED, EXCEPTION, RETRY
from buildbot.test.fake.remotecommand import Expect, ExpectRemoteRef, ExpectShell
from buildbot.test.util.misc import TestReactorMixin
from buildbot.test.util.steps import BuildStepMixin
from buildbot.util import identifiers as buildbot_identifiers
from mock import call, patch
from twisted.internet import defer, error, reactor
from twisted.python import failure, log
from twisted.trial import unittest
from steps import (AnalyzeAPITestsResults, AnalyzeCompileWebKitResults, AnalyzeJSCTestsResults,
AnalyzeLayoutTestsResults, ApplyPatch, ApplyWatchList, ArchiveBuiltProduct, ArchiveTestResults,
CheckOutSource, CheckOutSpecificRevision, CheckPatchRelevance, CheckPatchStatusOnEWSQueues, CheckStyle,
CleanBuild, CleanUpGitIndexLock, CleanGitRepo, CleanWorkingDirectory, CompileJSC, CompileJSCWithoutPatch,
CompileWebKit, CompileWebKitWithoutPatch, ConfigureBuild, CreateLocalGITCommit,
DownloadBuiltProduct, DownloadBuiltProductFromMaster, EWS_BUILD_HOSTNAME, ExtractBuiltProduct, ExtractTestResults,
FetchBranches, FindModifiedChangeLogs, FindModifiedLayoutTests, GitResetHard,
InstallBuiltProduct, InstallGtkDependencies, InstallWpeDependencies,
KillOldProcesses, PrintConfiguration, PushCommitToWebKitRepo, ReRunAPITests, ReRunJavaScriptCoreTests, ReRunWebKitPerlTests,
ReRunWebKitTests, RunAPITests, RunAPITestsWithoutPatch, RunBindingsTests, RunBuildWebKitOrgUnitTests,
RunBuildbotCheckConfigForBuildWebKit, RunBuildbotCheckConfigForEWS, RunEWSUnitTests, RunResultsdbpyTests,
RunJavaScriptCoreTests, RunJSCTestsWithoutPatch, RunWebKit1Tests, RunWebKitPerlTests, RunWebKitPyPython2Tests,
RunWebKitPyPython3Tests, RunWebKitTests, RunWebKitTestsInStressMode, RunWebKitTestsInStressGuardmallocMode,
RunWebKitTestsWithoutPatch, TestWithFailureCount, ShowIdentifier,
Trigger, TransferToS3, UnApplyPatchIfRequired, UpdateWorkingDirectory, UploadBuiltProduct,
UploadTestResults, ValidateChangeLogAndReviewer, ValidateCommiterAndReviewer, ValidatePatch, VerifyGitHubIntegrity)
# Workaround for https://github.com/buildbot/buildbot/issues/4669
from buildbot.test.fake.fakebuild import FakeBuild
FakeBuild.addStepsAfterCurrentStep = lambda FakeBuild, step_factories: None
def mock_step(step, logs='', results=SUCCESS, stopped=False, properties=None):
step.logs = logs
step.results = results
step.stopped = stopped
return step
class ExpectMasterShellCommand(object):
def __init__(self, command, workdir=None, env=None, usePTY=0):
self.args = command
self.usePTY = usePTY
self.rc = None
self.path = None
self.logs = []
if env is not None:
self.env = env
else:
self.env = os.environ
if workdir:
self.path = os.path.join(os.getcwd(), workdir)
@classmethod
def log(self, name, value):
return ('log', name, value)
def __add__(self, other):
if isinstance(other, int):
self.rc = other
elif isinstance(other, tuple) and other[0] == 'log':
self.logs.append((other[1], other[2]))
return self
def __repr__(self):
return 'ExpectMasterShellCommand({0})'.format(repr(self.args))
class BuildStepMixinAdditions(BuildStepMixin, TestReactorMixin):
def setUpBuildStep(self):
self.patch(reactor, 'spawnProcess', lambda *args, **kwargs: self._checkSpawnProcess(*args, **kwargs))
self._expected_local_commands = []
self.setUpTestReactor()
self._temp_directory = tempfile.mkdtemp()
os.chdir(self._temp_directory)
self._expected_uploaded_files = []
super(BuildStepMixinAdditions, self).setUpBuildStep()
def tearDownBuildStep(self):
shutil.rmtree(self._temp_directory)
super(BuildStepMixinAdditions, self).tearDownBuildStep()
def fakeBuildFinished(self, text, results):
self.build.text = text
self.build.results = results
def setupStep(self, step, *args, **kwargs):
self.previous_steps = kwargs.get('previous_steps') or []
if self.previous_steps:
del kwargs['previous_steps']
super(BuildStepMixinAdditions, self).setupStep(step, *args, **kwargs)
self.build.terminate = False
self.build.stopped = False
self.build.executedSteps = self.executedSteps
self.build.buildFinished = self.fakeBuildFinished
self._expected_added_urls = []
self._expected_sources = None
@property
def executedSteps(self):
return [step for step in self.previous_steps if not step.stopped]
def setProperty(self, name, value, source='Unknown'):
self.properties.setProperty(name, value, source)
def getProperty(self, name):
return self.properties.getProperty(name)
def expectAddedURLs(self, added_urls):
self._expected_added_urls = added_urls
def expectUploadedFile(self, path):
self._expected_uploaded_files.append(path)
def expectLocalCommands(self, *expected_commands):
self._expected_local_commands.extend(expected_commands)
def expectRemoteCommands(self, *expected_commands):
self.expectCommands(*expected_commands)
def expectSources(self, expected_sources):
self._expected_sources = expected_sources
def _checkSpawnProcess(self, processProtocol, executable, args, env, path, usePTY, **kwargs):
got = (executable, args, env, path, usePTY)
if not self._expected_local_commands:
self.fail('got local command {0} when no further commands were expected'.format(got))
local_command = self._expected_local_commands.pop(0)
try:
self.assertEqual(got, (local_command.args[0], local_command.args, local_command.env, local_command.path, local_command.usePTY))
except AssertionError:
log.err()
raise
for name, value in local_command.logs:
if name == 'stdout':
processProtocol.outReceived(value)
elif name == 'stderr':
processProtocol.errReceived(value)
if local_command.rc != 0:
value = error.ProcessTerminated(exitCode=local_command.rc)
else:
value = error.ProcessDone(None)
processProtocol.processEnded(failure.Failure(value))
def _added_files(self):
results = []
for dirpath, dirnames, filenames in os.walk(self._temp_directory):
relative_root_path = os.path.relpath(dirpath, start=self._temp_directory)
if relative_root_path == '.':
relative_root_path = ''
for name in filenames:
results.append(os.path.join(relative_root_path, name))
return results
def runStep(self):
def check(result):
self.assertEqual(self._expected_local_commands, [], 'assert all expected local commands were run')
self.expectAddedURLs(self._expected_added_urls)
self.assertEqual(self._added_files(), self._expected_uploaded_files)
if self._expected_sources is not None:
# Convert to dictionaries because assertEqual() only knows how to diff Python built-in types.
actual_sources = sorted([source.asDict() for source in self.build.sources], key=operator.itemgetter('codebase'))
expected_sources = sorted([source.asDict() for source in self._expected_sources], key=operator.itemgetter('codebase'))
self.assertEqual(actual_sources, expected_sources)
deferred_result = super(BuildStepMixinAdditions, self).runStep()
deferred_result.addCallback(check)
return deferred_result
def uploadFileWithContentsOfString(string, timestamp=None):
def behavior(command):
writer = command.args['writer']
writer.remote_write(string + '\n')
writer.remote_close()
if timestamp:
writer.remote_utime(timestamp)
return behavior
class TestStepNameShouldBeValidIdentifier(BuildStepMixinAdditions, unittest.TestCase):
def test_step_names_are_valid(self):
import steps
build_step_classes = inspect.getmembers(steps, inspect.isclass)
for build_step in build_step_classes:
if 'name' in vars(build_step[1]):
name = build_step[1].name
self.assertFalse(' ' in name, 'step name "{}" contain space.'.format(name))
self.assertTrue(buildbot_identifiers.ident_re.match(name), 'step name "{}" is not a valid buildbot identifier.'.format(name))
class TestCheckStyle(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success_internal(self):
self.setupStep(CheckStyle())
self.setProperty('try-codebase', 'internal')
self.setProperty('platform', 'mac')
self.setProperty('configuration', 'debug')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['python3', 'Tools/Scripts/check-webkit-style'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='check-webkit-style')
return self.runStep()
def test_failure_unknown_try_codebase(self):
self.setupStep(CheckStyle())
self.setProperty('try-codebase', 'foo')
self.setProperty('platform', 'mac')
self.setProperty('configuration', 'debug')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['python3', 'Tools/Scripts/check-webkit-style'],
)
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='check-webkit-style (failure)')
return self.runStep()
def test_failures_with_style_issues(self):
self.setupStep(CheckStyle())
self.setProperty('try-codebase', 'internal')
self.setProperty('platform', 'mac')
self.setProperty('configuration', 'debug')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['python3', 'Tools/Scripts/check-webkit-style'],
)
+ ExpectShell.log('stdio', stdout='''ERROR: Source/WebCore/layout/FloatingContext.cpp:36: Code inside a namespace should not be indented. [whitespace/indent] [4]
ERROR: Source/WebCore/layout/FormattingContext.h:94: Weird number of spaces at line-start. Are you using a 4-space indent? [whitespace/indent] [3]
ERROR: Source/WebCore/layout/LayoutContext.cpp:52: Place brace on its own line for function definitions. [whitespace/braces] [4]
ERROR: Source/WebCore/layout/LayoutContext.cpp:55: Extra space before last semicolon. If this should be an empty statement, use { } instead. [whitespace/semicolon] [5]
ERROR: Source/WebCore/layout/LayoutContext.cpp:60: Tab found; better to use spaces [whitespace/tab] [1]
ERROR: Source/WebCore/layout/Verification.cpp:88: Missing space before ( in while( [whitespace/parens] [5]
Total errors found: 8 in 48 files''')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='8 style errors')
return self.runStep()
def test_failures_no_style_issues(self):
self.setupStep(CheckStyle())
self.setProperty('try-codebase', 'internal')
self.setProperty('platform', 'mac')
self.setProperty('configuration', 'debug')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['python3', 'Tools/Scripts/check-webkit-style'],
)
+ ExpectShell.log('stdio', stdout='Total errors found: 0 in 6 files')
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='check-webkit-style')
return self.runStep()
def test_failures_no_changes(self):
self.setupStep(CheckStyle())
self.setProperty('try-codebase', 'internal')
self.setProperty('platform', 'mac')
self.setProperty('configuration', 'debug')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['python3', 'Tools/Scripts/check-webkit-style'],
)
+ ExpectShell.log('stdio', stdout='Total errors found: 0 in 0 files')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='check-webkit-style (failure)')
return self.runStep()
class TestApplyWatchList(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(ApplyWatchList())
self.setProperty('bug_id', '1234')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
timeout=120,
logEnviron=False,
command=['python3', 'Tools/Scripts/webkit-patch', 'apply-watchlist-local', '1234'])
+ ExpectShell.log('stdio', stdout='Result of watchlist: cc "" messages ""')
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Applied WatchList')
return self.runStep()
def test_failure(self):
self.setupStep(ApplyWatchList())
self.setProperty('bug_id', '1234')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
timeout=120,
logEnviron=False,
command=['python3', 'Tools/Scripts/webkit-patch', 'apply-watchlist-local', '1234'])
+ ExpectShell.log('stdio', stdout='Unexpected failure')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='Failed to apply watchlist')
return self.runStep()
class TestValidateChangeLogAndReviewer(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(ValidateChangeLogAndReviewer())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
timeout=180,
logEnviron=False,
command=['python3', 'Tools/Scripts/webkit-patch', 'validate-changelog', '--check-oops', '--non-interactive'])
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Validated ChangeLog and Reviewer')
return self.runStep()
def test_failure(self):
self.setupStep(ValidateChangeLogAndReviewer())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
timeout=180,
logEnviron=False,
command=['python3', 'Tools/Scripts/webkit-patch', 'validate-changelog', '--check-oops', '--non-interactive'])
+ ExpectShell.log('stdio', stdout='ChangeLog entry in LayoutTests/ChangeLog contains OOPS!.')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='ChangeLog validation failed')
rc = self.runStep()
self.assertEqual(self.getProperty('bugzilla_comment_text'), 'ChangeLog entry in LayoutTests/ChangeLog contains OOPS!.\n')
self.assertEqual(self.getProperty('build_finish_summary'), 'ChangeLog validation failed')
return rc
class TestRunBindingsTests(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
self.jsonFileName = 'bindings_test_results.json'
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(RunBindingsTests())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
timeout=300,
logEnviron=False,
command=['python3', 'Tools/Scripts/run-bindings-tests', '--json-output={0}'.format(self.jsonFileName)],
logfiles={'json': self.jsonFileName},
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Passed bindings tests')
return self.runStep()
def test_failure(self):
self.setupStep(RunBindingsTests())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
timeout=300,
logEnviron=False,
command=['python3', 'Tools/Scripts/run-bindings-tests', '--json-output={0}'.format(self.jsonFileName)],
logfiles={'json': self.jsonFileName},
)
+ ExpectShell.log('stdio', stdout='FAIL: (JS) JSTestInterface.cpp')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='bindings-tests (failure)')
return self.runStep()
class TestRunWebKitPerlTests(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def configureStep(self):
self.setupStep(RunWebKitPerlTests())
def test_success(self):
self.configureStep()
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/test-webkitperl'],
timeout=120,
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Passed webkitperl tests')
return self.runStep()
def test_failure(self):
self.configureStep()
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/test-webkitperl'],
timeout=120,
)
+ ExpectShell.log('stdio', stdout='''Failed tests: 1-3, 5-7, 9, 11-13
Files=40, Tests=630, 4 wallclock secs ( 0.16 usr 0.09 sys + 2.78 cusr 0.64 csys = 3.67 CPU)
Result: FAIL
Failed 1/40 test programs. 10/630 subtests failed.''')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='Failed webkitperl tests')
return self.runStep()
class TestWebKitPyPython2Tests(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
self.jsonFileName = 'webkitpy_test_python2_results.json'
self.json_with_failure = '''{"failures": [{"name": "webkitpy.port.wpe_unittest.WPEPortTest.test_diff_image"}]}\n'''
self.json_with_errros = '''{"failures": [],
"errors": [{"name": "webkitpy.style.checkers.cpp_unittest.WebKitStyleTest.test_os_version_checks"}, {"name": "webkitpy.port.win_unittest.WinPortTest.test_diff_image__missing_actual"}]}\n'''
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(RunWebKitPyPython2Tests())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['python', 'Tools/Scripts/test-webkitpy', '--verbose', '--json-output={0}'.format(self.jsonFileName)],
logfiles={'json': self.jsonFileName},
timeout=120,
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Passed webkitpy python2 tests')
return self.runStep()
def test_unexpected_failure(self):
self.setupStep(RunWebKitPyPython2Tests())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['python', 'Tools/Scripts/test-webkitpy', '--verbose', '--json-output={0}'.format(self.jsonFileName)],
logfiles={'json': self.jsonFileName},
timeout=120,
)
+ ExpectShell.log('stdio', stdout='''Ran 1744 tests in 5.913s
FAILED (failures=1, errors=0)''')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='webkitpy-tests (failure)')
return self.runStep()
def test_failure(self):
self.setupStep(RunWebKitPyPython2Tests())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['python', 'Tools/Scripts/test-webkitpy', '--verbose', '--json-output={0}'.format(self.jsonFileName)],
logfiles={'json': self.jsonFileName},
timeout=120,
) +
ExpectShell.log('json', stdout=self.json_with_failure) +
2,
)
self.expectOutcome(result=FAILURE, state_string='Found 1 webkitpy python2 test failure: webkitpy.port.wpe_unittest.WPEPortTest.test_diff_image')
return self.runStep()
def test_errors(self):
self.setupStep(RunWebKitPyPython2Tests())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['python', 'Tools/Scripts/test-webkitpy', '--verbose', '--json-output={0}'.format(self.jsonFileName)],
logfiles={'json': self.jsonFileName},
timeout=120,
) +
ExpectShell.log('json', stdout=self.json_with_errros) +
2,
)
self.expectOutcome(result=FAILURE, state_string='Found 2 webkitpy python2 test failures: webkitpy.style.checkers.cpp_unittest.WebKitStyleTest.test_os_version_checks, webkitpy.port.win_unittest.WinPortTest.test_diff_image__missing_actual')
return self.runStep()
def test_lot_of_failures(self):
self.setupStep(RunWebKitPyPython2Tests())
json_with_failures = json.dumps({"failures": [{"name": 'test{}'.format(i)} for i in range(1, 31)]})
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['python', 'Tools/Scripts/test-webkitpy', '--verbose', '--json-output={0}'.format(self.jsonFileName)],
logfiles={'json': self.jsonFileName},
timeout=120,
) +
ExpectShell.log('json', stdout=json_with_failures) +
2,
)
self.expectOutcome(result=FAILURE, state_string='Found 30 webkitpy python2 test failures: test1, test2, test3, test4, test5, test6, test7, test8, test9, test10 ...')
return self.runStep()
class TestWebKitPyPython3Tests(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
self.jsonFileName = 'webkitpy_test_python3_results.json'
self.json_with_failure = '''{"failures": [{"name": "webkitpy.port.wpe_unittest.WPEPortTest.test_diff_image"}]}\n'''
self.json_with_errros = '''{"failures": [],
"errors": [{"name": "webkitpy.style.checkers.cpp_unittest.WebKitStyleTest.test_os_version_checks"}, {"name": "webkitpy.port.win_unittest.WinPortTest.test_diff_image__missing_actual"}]}\n'''
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(RunWebKitPyPython3Tests())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['python3', 'Tools/Scripts/test-webkitpy', '--verbose', '--json-output={0}'.format(self.jsonFileName)],
logfiles={'json': self.jsonFileName},
timeout=120,
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Passed webkitpy python3 tests')
return self.runStep()
def test_unexpected_failure(self):
self.setupStep(RunWebKitPyPython3Tests())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['python3', 'Tools/Scripts/test-webkitpy', '--verbose', '--json-output={0}'.format(self.jsonFileName)],
logfiles={'json': self.jsonFileName},
timeout=120,
)
+ ExpectShell.log('stdio', stdout='''Ran 1744 tests in 5.913s
FAILED (failures=1, errors=0)''')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='webkitpy-tests (failure)')
return self.runStep()
def test_failure(self):
self.setupStep(RunWebKitPyPython3Tests())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['python3', 'Tools/Scripts/test-webkitpy', '--verbose', '--json-output={0}'.format(self.jsonFileName)],
logfiles={'json': self.jsonFileName},
timeout=120,
) +
ExpectShell.log('json', stdout=self.json_with_failure) +
2,
)
self.expectOutcome(result=FAILURE, state_string='Found 1 webkitpy python3 test failure: webkitpy.port.wpe_unittest.WPEPortTest.test_diff_image')
return self.runStep()
def test_errors(self):
self.setupStep(RunWebKitPyPython3Tests())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['python3', 'Tools/Scripts/test-webkitpy', '--verbose', '--json-output={0}'.format(self.jsonFileName)],
logfiles={'json': self.jsonFileName},
timeout=120,
) +
ExpectShell.log('json', stdout=self.json_with_errros) +
2,
)
self.expectOutcome(result=FAILURE, state_string='Found 2 webkitpy python3 test failures: webkitpy.style.checkers.cpp_unittest.WebKitStyleTest.test_os_version_checks, webkitpy.port.win_unittest.WinPortTest.test_diff_image__missing_actual')
return self.runStep()
def test_lot_of_failures(self):
self.setupStep(RunWebKitPyPython3Tests())
json_with_failures = json.dumps({"failures": [{"name": 'test{}'.format(i)} for i in range(1, 31)]})
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['python3', 'Tools/Scripts/test-webkitpy', '--verbose', '--json-output={0}'.format(self.jsonFileName)],
logfiles={'json': self.jsonFileName},
timeout=120,
) +
ExpectShell.log('json', stdout=json_with_failures) +
2,
)
self.expectOutcome(result=FAILURE, state_string='Found 30 webkitpy python3 test failures: test1, test2, test3, test4, test5, test6, test7, test8, test9, test10 ...')
return self.runStep()
class TestRunBuildbotCheckConfigForEWS(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(RunBuildbotCheckConfigForEWS())
self.expectRemoteCommands(
ExpectShell(workdir='build/Tools/CISupport/ews-build',
timeout=120,
logEnviron=False,
command=['buildbot', 'checkconfig'],
env={'LC_CTYPE': 'en_US.UTF-8'}
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Passed buildbot checkconfig')
return self.runStep()
def test_failure(self):
self.setupStep(RunBuildbotCheckConfigForEWS())
self.expectRemoteCommands(
ExpectShell(workdir='build/Tools/CISupport/ews-build',
timeout=120,
logEnviron=False,
command=['buildbot', 'checkconfig'],
env={'LC_CTYPE': 'en_US.UTF-8'}
)
+ ExpectShell.log('stdio', stdout='Configuration Errors: builder(s) iOS-14-Debug-Build-EWS have no schedulers to drive them')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='Failed buildbot checkconfig')
return self.runStep()
class TestRunBuildbotCheckConfigForBuildWebKit(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(RunBuildbotCheckConfigForBuildWebKit())
self.expectRemoteCommands(
ExpectShell(workdir='build/Tools/CISupport/build-webkit-org',
timeout=120,
logEnviron=False,
command=['buildbot', 'checkconfig'],
env={'LC_CTYPE': 'en_US.UTF-8'}
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Passed buildbot checkconfig')
return self.runStep()
def test_failure(self):
self.setupStep(RunBuildbotCheckConfigForBuildWebKit())
self.expectRemoteCommands(
ExpectShell(workdir='build/Tools/CISupport/build-webkit-org',
timeout=120,
logEnviron=False,
command=['buildbot', 'checkconfig'],
env={'LC_CTYPE': 'en_US.UTF-8'}
)
+ ExpectShell.log('stdio', stdout='Configuration Errors: builder(s) Apple-iOS-14-Release-Build have no schedulers to drive them')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='Failed buildbot checkconfig')
return self.runStep()
class TestRunEWSUnitTests(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(RunEWSUnitTests())
self.expectRemoteCommands(
ExpectShell(workdir='build/Tools/CISupport',
timeout=120,
logEnviron=False,
command=['python3', 'runUnittests.py', 'ews-build'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Passed EWS unit tests')
return self.runStep()
def test_failure(self):
self.setupStep(RunEWSUnitTests())
self.expectRemoteCommands(
ExpectShell(workdir='build/Tools/CISupport',
timeout=120,
logEnviron=False,
command=['python3', 'runUnittests.py', 'ews-build'],
)
+ ExpectShell.log('stdio', stdout='Unhandled Error. Traceback (most recent call last): Keys in cmd missing from expectation: [logfiles.json]')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='Failed EWS unit tests')
return self.runStep()
class TestRunResultsdbpyTests(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(RunResultsdbpyTests())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
timeout=120,
logEnviron=False,
command=['python3', 'Tools/Scripts/libraries/resultsdbpy/resultsdbpy/run-tests', '--verbose', '--no-selenium', '--fast-tests'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Passed resultsdbpy unit tests')
return self.runStep()
def test_failure(self):
self.setupStep(RunResultsdbpyTests())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
timeout=120,
logEnviron=False,
command=['python3', 'Tools/Scripts/libraries/resultsdbpy/resultsdbpy/run-tests', '--verbose', '--no-selenium', '--fast-tests'],
)
+ ExpectShell.log('stdio', stdout='FAILED (errors=5, skipped=224)')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='Failed resultsdbpy unit tests')
return self.runStep()
class TestRunBuildWebKitOrgUnitTests(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(RunBuildWebKitOrgUnitTests())
self.expectRemoteCommands(
ExpectShell(workdir='build/Tools/CISupport',
timeout=120,
logEnviron=False,
command=['python3', 'runUnittests.py', 'build-webkit-org'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Passed build.webkit.org unit tests')
return self.runStep()
def test_failure(self):
self.setupStep(RunBuildWebKitOrgUnitTests())
self.expectRemoteCommands(
ExpectShell(workdir='build/Tools/CISupport',
timeout=120,
logEnviron=False,
command=['python3', 'runUnittests.py', 'build-webkit-org'],
)
+ ExpectShell.log('stdio', stdout='Unhandled Error. Traceback (most recent call last): Keys in cmd missing from expectation: [logfiles.json]')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='Failed build.webkit.org unit tests')
return self.runStep()
class TestKillOldProcesses(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(KillOldProcesses())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
command=['python3', 'Tools/CISupport/kill-old-processes', 'buildbot'],
logEnviron=False,
timeout=120,
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Killed old processes')
return self.runStep()
def test_failure(self):
self.setupStep(KillOldProcesses())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
command=['python3', 'Tools/CISupport/kill-old-processes', 'buildbot'],
logEnviron=False,
timeout=120,
)
+ ExpectShell.log('stdio', stdout='Unexpected error.')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='Failed to kill old processes')
return self.runStep()
class TestGitResetHard(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(GitResetHard())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
command=['git', 'reset', 'HEAD~10', '--hard'],
logEnviron=False,
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Performed git reset --hard')
return self.runStep()
def test_failure(self):
self.setupStep(GitResetHard())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
command=['git', 'reset', 'HEAD~10', '--hard'],
logEnviron=False,
)
+ ExpectShell.log('stdio', stdout='Unexpected error.')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='Performed git reset --hard (failure)')
return self.runStep()
class TestCleanBuild(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(CleanBuild())
self.setProperty('fullPlatform', 'ios-11')
self.setProperty('configuration', 'release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
command=['python3', 'Tools/CISupport/clean-build', '--platform=ios-11', '--release'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Deleted WebKitBuild directory')
return self.runStep()
def test_failure(self):
self.setupStep(CleanBuild())
self.setProperty('fullPlatform', 'ios-simulator-11')
self.setProperty('configuration', 'debug')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
command=['python3', 'Tools/CISupport/clean-build', '--platform=ios-simulator-11', '--debug'],
)
+ ExpectShell.log('stdio', stdout='Unexpected error.')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='Deleted WebKitBuild directory (failure)')
return self.runStep()
class TestCleanUpGitIndexLock(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(CleanUpGitIndexLock())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
timeout=120,
logEnviron=False,
command=['rm', '-f', '.git/index.lock'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Deleted .git/index.lock')
return self.runStep()
def test_success_windows(self):
self.setupStep(CleanUpGitIndexLock())
self.setProperty('platform', 'win')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
timeout=120,
logEnviron=False,
command=['rm', '-f', '.git/index.lock'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Deleted .git/index.lock')
return self.runStep()
def test_success_wincairo(self):
self.setupStep(CleanUpGitIndexLock())
self.setProperty('platform', 'wincairo')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
timeout=120,
logEnviron=False,
command=['del', r'.git\index.lock'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Deleted .git/index.lock')
return self.runStep()
def test_failure(self):
self.setupStep(CleanUpGitIndexLock())
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
timeout=120,
logEnviron=False,
command=['rm', '-f', '.git/index.lock'],
)
+ ExpectShell.log('stdio', stdout='Unexpected error.')
+ 1,
)
self.expectOutcome(result=FAILURE, state_string='Deleted .git/index.lock (failure)')
return self.runStep()
class TestInstallGtkDependencies(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(InstallGtkDependencies())
self.setProperty('configuration', 'release')
self.assertEqual(InstallGtkDependencies.haltOnFailure, True)
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/update-webkitgtk-libs', '--release'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Updated gtk dependencies')
return self.runStep()
def test_failure(self):
self.setupStep(InstallGtkDependencies())
self.setProperty('configuration', 'release')
self.assertEqual(InstallGtkDependencies.haltOnFailure, True)
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/update-webkitgtk-libs', '--release'],
)
+ ExpectShell.log('stdio', stdout='Unexpected error.')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='Updated gtk dependencies (failure)')
return self.runStep()
class TestInstallWpeDependencies(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(InstallWpeDependencies())
self.setProperty('configuration', 'release')
self.assertEqual(InstallWpeDependencies.haltOnFailure, True)
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/update-webkitwpe-libs', '--release'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Updated wpe dependencies')
return self.runStep()
def test_failure(self):
self.setupStep(InstallWpeDependencies())
self.setProperty('configuration', 'release')
self.assertEqual(InstallWpeDependencies.haltOnFailure, True)
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/update-webkitwpe-libs', '--release'],
)
+ ExpectShell.log('stdio', stdout='Unexpected error.')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='Updated wpe dependencies (failure)')
return self.runStep()
class TestCompileWebKit(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(CompileWebKit())
self.setProperty('fullPlatform', 'ios-simulator-11')
self.setProperty('configuration', 'release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/build-webkit', '--release'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Compiled WebKit')
return self.runStep()
def test_success_gtk(self):
self.setupStep(CompileWebKit())
self.setProperty('platform', 'gtk')
self.setProperty('fullPlatform', 'gtk')
self.setProperty('configuration', 'release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/build-webkit', '--release', '--prefix=/app/webkit/WebKitBuild/release/install', '--gtk'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Compiled WebKit')
return self.runStep()
def test_success_wpe(self):
self.setupStep(CompileWebKit())
self.setProperty('platform', 'wpe')
self.setProperty('fullPlatform', 'wpe')
self.setProperty('configuration', 'release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/build-webkit', '--release', '--wpe'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Compiled WebKit')
return self.runStep()
def test_failure(self):
self.setupStep(CompileWebKit())
self.setProperty('fullPlatform', 'mac-sierra')
self.setProperty('configuration', 'debug')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/build-webkit', '--debug'],
)
+ ExpectShell.log('stdio', stdout='1 error generated.')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='Failed to compile WebKit')
return self.runStep()
def test_skip_for_revert_patches_on_commit_queue(self):
self.setupStep(CompileWebKit())
self.setProperty('buildername', 'Commit-Queue')
self.setProperty('configuration', 'debug')
self.setProperty('fast_commit_queue', True)
self.expectOutcome(result=SKIPPED, state_string='Skipped compiling WebKit in fast-cq mode')
return self.runStep()
class TestCompileWebKitWithoutPatch(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(CompileWebKitWithoutPatch())
self.setProperty('fullPlatform', 'ios-simulator-11')
self.setProperty('configuration', 'release')
self.setProperty('patchFailedToBuild', True)
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/build-webkit', '--release'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Compiled WebKit')
return self.runStep()
def test_failure(self):
self.setupStep(CompileWebKitWithoutPatch())
self.setProperty('fullPlatform', 'mac-sierra')
self.setProperty('configuration', 'debug')
self.setProperty('patchFailedTests', True)
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/build-webkit', '--debug'],
)
+ ExpectShell.log('stdio', stdout='1 error generated.')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='Failed to compile WebKit')
return self.runStep()
def test_skip(self):
self.setupStep(CompileWebKitWithoutPatch())
self.setProperty('fullPlatform', 'ios-simulator-11')
self.setProperty('configuration', 'release')
self.expectHidden(True)
self.expectOutcome(result=SKIPPED, state_string='Skipped compiling WebKit')
return self.runStep()
class TestAnalyzeCompileWebKitResults(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
AnalyzeCompileWebKitResults.send_email_for_build_failure = lambda self: None
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_patch_with_build_failure(self):
previous_steps = [
mock_step(CompileWebKit(), results=FAILURE),
mock_step(CompileWebKitWithoutPatch(), results=SUCCESS),
]
self.setupStep(AnalyzeCompileWebKitResults(), previous_steps=previous_steps)
self.setProperty('patch_id', '1234')
self.expectOutcome(result=FAILURE, state_string='Patch 1234 does not build (failure)')
rc = self.runStep()
self.assertEqual(self.getProperty('bugzilla_comment_text'), None)
self.assertEqual(self.getProperty('build_finish_summary'), 'Patch 1234 does not build')
return rc
def test_patch_with_build_failure_on_commit_queue(self):
previous_steps = [
mock_step(CompileWebKit(), results=FAILURE),
mock_step(CompileWebKitWithoutPatch(), results=SUCCESS),
]
self.setupStep(AnalyzeCompileWebKitResults(), previous_steps=previous_steps)
self.setProperty('patch_id', '1234')
self.setProperty('buildername', 'commit-queue')
self.expectOutcome(result=FAILURE, state_string='Patch 1234 does not build (failure)')
rc = self.runStep()
self.assertEqual(self.getProperty('bugzilla_comment_text'), 'Patch 1234 does not build')
self.assertEqual(self.getProperty('build_finish_summary'), 'Patch 1234 does not build')
return rc
def test_patch_with_trunk_failure(self):
previous_steps = [
mock_step(CompileWebKit(), results=FAILURE),
mock_step(CompileWebKitWithoutPatch(), results=FAILURE),
]
self.setupStep(AnalyzeCompileWebKitResults(), previous_steps=previous_steps)
self.expectOutcome(result=FAILURE, state_string='Unable to build WebKit without patch, retrying build (failure)')
return self.runStep()
def test_filter_logs_containing_error(self):
logs = 'In file included from WebCore/unified-sources/UnifiedSource263.cpp:4:\nImageBufferIOSurfaceBackend.cpp:108:30: error: definition of implicitly declared destructor'
expected_output = 'ImageBufferIOSurfaceBackend.cpp:108:30: error: definition of implicitly declared destructor'
output = AnalyzeCompileWebKitResults().filter_logs_containing_error(logs)
self.assertEqual(expected_output, output)
def test_filter_logs_containing_error_with_too_many_errors(self):
logs = 'Error:1\nError:2\nerror:3\nerror:4\nerror:5\nrandom-string\nerror:6\nerror:7\nerror8\nerror:9\nerror:10\nerror:11\nerror:12\nerror:13'
expected_output = 'error:3\nerror:4\nerror:5\nerror:6\nerror:7\nerror:9\nerror:10\nerror:11\nerror:12\nerror:13'
output = AnalyzeCompileWebKitResults().filter_logs_containing_error(logs)
self.assertEqual(expected_output, output)
def test_filter_logs_containing_error_with_no_error(self):
logs = 'CompileC /Volumes/Data/worker/macOS-Catalina-Release-Build-EWS'
expected_output = ''
output = AnalyzeCompileWebKitResults().filter_logs_containing_error(logs)
self.assertEqual(expected_output, output)
class TestCompileJSC(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(CompileJSC())
self.setProperty('fullPlatform', 'jsc-only')
self.setProperty('configuration', 'release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/build-jsc', '--release'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Compiled JSC')
return self.runStep()
def test_failure(self):
self.setupStep(CompileJSC())
self.setProperty('fullPlatform', 'jsc-only')
self.setProperty('configuration', 'debug')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/build-jsc', '--debug'],
)
+ ExpectShell.log('stdio', stdout='1 error generated.')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='Failed to compile JSC')
return self.runStep()
class TestCompileJSCWithoutPatch(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(CompileJSCWithoutPatch())
self.setProperty('fullPlatform', 'jsc-only')
self.setProperty('configuration', 'release')
self.setProperty('patchFailedToBuild', 'True')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/build-jsc', '--release'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Compiled JSC')
return self.runStep()
def test_failure(self):
self.setupStep(CompileJSCWithoutPatch())
self.setProperty('fullPlatform', 'jsc-only')
self.setProperty('configuration', 'debug')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/build-jsc', '--debug'],
)
+ ExpectShell.log('stdio', stdout='1 error generated.')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='Failed to compile JSC')
return self.runStep()
class TestRunJavaScriptCoreTests(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
self.jsonFileName = 'jsc_results.json'
self.jsc_masm_failure = '''{"allDFGTestsPassed":true,"allMasmTestsPassed":false,"allB3TestsPassed":true,"allAirTestsPassed":true,"stressTestFailures":[],"allApiTestsPassed":true}\n'''
self.jsc_b3_and_stress_test_failure = '''{"allDFGTestsPassed":true,"allMasmTestsPassed":true,"allB3TestsPassed":false,"allAirTestsPassed":true,"allApiTestsPassed":true,"stressTestFailures":["stress/weakset-gc.js"]}\n'''
self.jsc_dfg_air_and_stress_test_failure = '''{"allDFGTestsPassed":false,"allMasmTestsPassed":true,"allB3TestsPassed":true,"allAirTestsPassed":false,"allApiTestsPassed":true,"stressTestFailures":["stress/weakset-gc.js"]}\n'''
self.jsc_single_stress_test_failure = '''{"allDFGTestsPassed":true,"allMasmTestsPassed":true,"allB3TestsPassed":true,"allAirTestsPassed":true,"stressTestFailures":["stress/switch-on-char-llint-rope.js.dfg-eager"],"allApiTestsPassed":true}\n'''
self.jsc_multiple_stress_test_failures = '''{"allDFGTestsPassed":true,"allMasmTestsPassed":true,"allB3TestsPassed":true,"allAirTestsPassed":true,"stressTestFailures":["stress/switch-on-char-llint-rope.js.dfg-eager","stress/switch-on-char-llint-rope.js.dfg-eager-no-cjit-validate","stress/switch-on-char-llint-rope.js.eager-jettison-no-cjit","stress/switch-on-char-llint-rope.js.ftl-eager","stress/switch-on-char-llint-rope.js.ftl-eager-no-cjit","stress/switch-on-char-llint-rope.js.ftl-eager-no-cjit-b3o1","stress/switch-on-char-llint-rope.js.ftl-no-cjit-b3o0","stress/switch-on-char-llint-rope.js.ftl-no-cjit-no-inline-validate","stress/switch-on-char-llint-rope.js.ftl-no-cjit-no-put-stack-validate","stress/switch-on-char-llint-rope.js.ftl-no-cjit-small-pool","stress/switch-on-char-llint-rope.js.ftl-no-cjit-validate-sampling-profiler","stress/switch-on-char-llint-rope.js.no-cjit-collect-continuously","stress/switch-on-char-llint-rope.js.no-cjit-validate-phases","stress/switch-on-char-llint-rope.js.no-ftl"],"allApiTestsPassed":true}\n'''
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def configureStep(self, platform=None, fullPlatform=None, configuration=None):
self.setupStep(RunJavaScriptCoreTests())
self.prefix = RunJavaScriptCoreTests.prefix
if platform:
self.setProperty('platform', platform)
if fullPlatform:
self.setProperty('fullPlatform', fullPlatform)
if configuration:
self.setProperty('configuration', configuration)
def test_success(self):
self.configureStep(platform='mac', fullPlatform='mac-highsierra', configuration='release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/run-javascriptcore-tests', '--no-build', '--no-fail-fast', '--json-output={0}'.format(self.jsonFileName), '--release'],
logfiles={'json': self.jsonFileName},
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Passed JSC tests')
return self.runStep()
def test_remote_success(self):
self.configureStep(platform='jsc-only', fullPlatform='jsc-only', configuration='release')
self.setProperty('remotes', 'remote-machines.json')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/run-javascriptcore-tests', '--no-build', '--no-fail-fast', '--json-output={0}'.format(self.jsonFileName), '--release', '--remote-config-file=remote-machines.json', '--no-testmasm', '--no-testair', '--no-testb3', '--no-testdfg', '--no-testapi', '--memory-limited', '--verbose', '--jsc-only'],
logfiles={'json': self.jsonFileName},
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Passed JSC tests')
return self.runStep()
def test_failure(self):
self.configureStep(platform='mac', fullPlatform='mac-highsierra', configuration='debug')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/run-javascriptcore-tests', '--no-build', '--no-fail-fast', '--json-output={0}'.format(self.jsonFileName), '--debug'],
logfiles={'json': self.jsonFileName},
)
+ ExpectShell.log('stdio', stdout='9 failures found.')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='jscore-tests (failure)')
return self.runStep()
def test_single_stress_test_failure(self):
self.configureStep(platform='mac', fullPlatform='mac-highsierra', configuration='debug')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
logfiles={'json': self.jsonFileName},
command=['perl', 'Tools/Scripts/run-javascriptcore-tests', '--no-build', '--no-fail-fast', '--json-output={0}'.format(self.jsonFileName), '--debug'],
)
+ 2
+ ExpectShell.log('json', stdout=self.jsc_single_stress_test_failure),
)
self.expectOutcome(result=FAILURE, state_string='Found 1 jsc stress test failure: stress/switch-on-char-llint-rope.js.dfg-eager')
rc = self.runStep()
self.assertEqual(self.getProperty(self.prefix + 'stress_test_failures'), ['stress/switch-on-char-llint-rope.js.dfg-eager'])
self.assertEqual(self.getProperty(self.prefix + 'binary_failures'), None)
return rc
def test_lot_of_stress_test_failure(self):
self.configureStep(platform='mac', fullPlatform='mac-highsierra', configuration='debug')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
logfiles={'json': self.jsonFileName},
command=['perl', 'Tools/Scripts/run-javascriptcore-tests', '--no-build', '--no-fail-fast', '--json-output={0}'.format(self.jsonFileName), '--debug'],
)
+ 2
+ ExpectShell.log('json', stdout=self.jsc_multiple_stress_test_failures),
)
self.expectOutcome(result=FAILURE, state_string='Found 14 jsc stress test failures: stress/switch-on-char-llint-rope.js.dfg-eager, stress/switch-on-char-llint-rope.js.dfg-eager-no-cjit-validate, stress/switch-on-char-llint-rope.js.eager-jettison-no-cjit, stress/switch-on-char-llint-rope.js.ftl-eager, stress/switch-on-char-llint-rope.js.ftl-eager-no-cjit ...')
rc = self.runStep()
self.assertEqual(self.getProperty(self.prefix + 'stress_test_failures'), ["stress/switch-on-char-llint-rope.js.dfg-eager", "stress/switch-on-char-llint-rope.js.dfg-eager-no-cjit-validate", "stress/switch-on-char-llint-rope.js.eager-jettison-no-cjit", "stress/switch-on-char-llint-rope.js.ftl-eager", "stress/switch-on-char-llint-rope.js.ftl-eager-no-cjit", "stress/switch-on-char-llint-rope.js.ftl-eager-no-cjit-b3o1", "stress/switch-on-char-llint-rope.js.ftl-no-cjit-b3o0", "stress/switch-on-char-llint-rope.js.ftl-no-cjit-no-inline-validate", "stress/switch-on-char-llint-rope.js.ftl-no-cjit-no-put-stack-validate", "stress/switch-on-char-llint-rope.js.ftl-no-cjit-small-pool", "stress/switch-on-char-llint-rope.js.ftl-no-cjit-validate-sampling-profiler", "stress/switch-on-char-llint-rope.js.no-cjit-collect-continuously", "stress/switch-on-char-llint-rope.js.no-cjit-validate-phases", "stress/switch-on-char-llint-rope.js.no-ftl"])
self.assertEqual(self.getProperty(self.prefix + 'binary_failures'), None)
return rc
def test_masm_failure(self):
self.configureStep(platform='mac', fullPlatform='mac-highsierra', configuration='debug')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
logfiles={'json': self.jsonFileName},
command=['perl', 'Tools/Scripts/run-javascriptcore-tests', '--no-build', '--no-fail-fast', '--json-output={0}'.format(self.jsonFileName), '--debug'],
)
+ 2
+ ExpectShell.log('json', stdout=self.jsc_masm_failure),
)
self.expectOutcome(result=FAILURE, state_string='JSC test binary failure: testmasm')
rc = self.runStep()
self.assertEqual(self.getProperty(self.prefix + 'stress_test_failures'), None)
self.assertEqual(self.getProperty(self.prefix + 'binary_failures'), ['testmasm'])
return rc
def test_b3_and_stress_test_failure(self):
self.configureStep(platform='mac', fullPlatform='mac-highsierra', configuration='release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
logfiles={'json': self.jsonFileName},
command=['perl', 'Tools/Scripts/run-javascriptcore-tests', '--no-build', '--no-fail-fast', '--json-output={0}'.format(self.jsonFileName), '--release'],
)
+ 2
+ ExpectShell.log('json', stdout=self.jsc_b3_and_stress_test_failure),
)
self.expectOutcome(result=FAILURE, state_string='Found 1 jsc stress test failure: stress/weakset-gc.js, JSC test binary failure: testb3')
rc = self.runStep()
self.assertEqual(self.getProperty(self.prefix + 'stress_test_failures'), ['stress/weakset-gc.js'])
self.assertEqual(self.getProperty(self.prefix + 'binary_failures'), ['testb3'])
return rc
def test_dfg_air_and_stress_test_failure(self):
self.configureStep(platform='jsc-only', fullPlatform='jsc-only', configuration='release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
logfiles={'json': self.jsonFileName},
command=['perl', 'Tools/Scripts/run-javascriptcore-tests', '--no-build', '--no-fail-fast', '--json-output={0}'.format(self.jsonFileName), '--release', '--memory-limited', '--verbose', '--jsc-only'],
)
+ 2
+ ExpectShell.log('json', stdout=self.jsc_dfg_air_and_stress_test_failure),
)
self.expectOutcome(result=FAILURE, state_string='Found 1 jsc stress test failure: stress/weakset-gc.js, JSC test binary failures: testair, testdfg')
rc = self.runStep()
self.assertEqual(self.getProperty(self.prefix + 'stress_test_failures'), ['stress/weakset-gc.js'])
self.assertEqual(self.getProperty(self.prefix + 'binary_failures'), ['testair', 'testdfg'])
return rc
class TestReRunJavaScriptCoreTests(TestRunJavaScriptCoreTests):
def configureStep(self, platform=None, fullPlatform=None, configuration=None):
self.setupStep(ReRunJavaScriptCoreTests())
self.prefix = ReRunJavaScriptCoreTests.prefix
if platform:
self.setProperty('platform', platform)
if fullPlatform:
self.setProperty('fullPlatform', fullPlatform)
if configuration:
self.setProperty('configuration', configuration)
def test_success(self):
self.configureStep(platform='mac', fullPlatform='mac-highsierra', configuration='release')
self.setProperty('jsc_stress_test_failures', ['test1', 'test2'])
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/run-javascriptcore-tests', '--no-build', '--no-fail-fast', '--json-output={0}'.format(self.jsonFileName), '--release'],
logfiles={'json': self.jsonFileName},
) +
0,
)
self.expectOutcome(result=SUCCESS, state_string='Found flaky tests: test1, test2')
return self.runStep()
def test_remote_success(self):
self.configureStep(platform='jsc-only', fullPlatform='jsc-only', configuration='release')
self.setProperty('remotes', 'remote-machines.json')
self.setProperty('jsc_binary_failures', ['testmasm'])
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/run-javascriptcore-tests', '--no-build', '--no-fail-fast', '--json-output={0}'.format(self.jsonFileName), '--release', '--remote-config-file=remote-machines.json', '--no-testmasm', '--no-testair', '--no-testb3', '--no-testdfg', '--no-testapi', '--memory-limited', '--verbose', '--jsc-only'],
logfiles={'json': self.jsonFileName},
) +
0,
)
self.expectOutcome(result=SUCCESS, state_string='Found flaky test: testmasm')
return self.runStep()
class TestRunJSCTestsWithoutPatch(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
self.jsonFileName = 'jsc_results.json'
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(RunJSCTestsWithoutPatch())
self.setProperty('fullPlatform', 'jsc-only')
self.setProperty('configuration', 'release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/run-javascriptcore-tests', '--no-build', '--no-fail-fast', '--json-output={0}'.format(self.jsonFileName), '--release'],
logfiles={'json': self.jsonFileName},
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='jscore-tests')
return self.runStep()
def test_failure(self):
self.setupStep(RunJSCTestsWithoutPatch())
self.setProperty('fullPlatform', 'jsc-only')
self.setProperty('configuration', 'debug')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logEnviron=False,
command=['perl', 'Tools/Scripts/run-javascriptcore-tests', '--no-build', '--no-fail-fast', '--json-output={0}'.format(self.jsonFileName), '--debug'],
logfiles={'json': self.jsonFileName},
)
+ ExpectShell.log('stdio', stdout='9 failures found.')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='jscore-tests (failure)')
return self.runStep()
class TestAnalyzeJSCTestsResults(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def configureStep(self):
self.setupStep(AnalyzeJSCTestsResults())
self.setProperty('jsc_stress_test_failures', [])
self.setProperty('jsc_binary_failures', [])
self.setProperty('jsc_rerun_stress_test_failures', [])
self.setProperty('jsc_rerun_binary_failures', [])
self.setProperty('jsc_clean_tree_stress_test_failures', [])
self.setProperty('jsc_clean_tree_binary_failures', [])
AnalyzeJSCTestsResults.send_email_for_flaky_failure = lambda self, test: None
AnalyzeJSCTestsResults.send_email_for_pre_existing_failure = lambda self, test: None
def test_single_new_stress_failure(self):
self.configureStep()
self.setProperty('jsc_stress_test_failures', ['stress/force-error.js.bytecode-cache'])
self.setProperty('jsc_rerun_stress_test_failures', ['stress/force-error.js.bytecode-cache'])
self.expectOutcome(result=FAILURE, state_string='Found 1 new JSC stress test failure: stress/force-error.js.bytecode-cache (failure)')
return self.runStep()
def test_single_new_binary_failure(self):
self.configureStep()
self.setProperty('jsc_binary_failures', ['testmasm'])
self.setProperty('jsc_rerun_binary_failures', ['testmasm'])
self.expectOutcome(result=FAILURE, state_string='Found 1 new JSC binary failure: testmasm (failure)')
return self.runStep()
def test_multiple_new_stress_failure(self):
self.configureStep()
self.setProperty('jsc_stress_test_failures', ['test{}'.format(i) for i in range(0, 30)])
self.setProperty('jsc_rerun_stress_test_failures', ['test{}'.format(i) for i in range(0, 30)])
self.expectOutcome(result=FAILURE, state_string='Found 30 new JSC stress test failures: test0, test1, test10, test11, test12, test13, test14, test15, test16, test17 ... (failure)')
return self.runStep()
def test_multiple_new_binary_failure(self):
self.configureStep()
self.setProperty('jsc_binary_failures', ['testmasm', 'testair', 'testb3', 'testdfg', 'testapi'])
self.setProperty('jsc_rerun_binary_failures', ['testmasm', 'testair', 'testb3', 'testdfg', 'testapi'])
self.expectOutcome(result=FAILURE, state_string='Found 5 new JSC binary failures: testair, testapi, testb3, testdfg, testmasm (failure)')
return self.runStep()
def test_new_stress_and_binary_failure(self):
self.configureStep()
self.setProperty('jsc_stress_test_failures', ['es6.yaml/es6/Set_iterator_closing.js.default'])
self.setProperty('jsc_binary_failures', ['testmasm'])
self.setProperty('jsc_rerun_stress_test_failures', ['es6.yaml/es6/Set_iterator_closing.js.default'])
self.setProperty('jsc_rerun_binary_failures', ['testmasm'])
self.expectOutcome(result=FAILURE, state_string='Found 1 new JSC binary failure: testmasm, Found 1 new JSC stress test failure: es6.yaml/es6/Set_iterator_closing.js.default (failure)')
return self.runStep()
def test_stress_failure_on_clean_tree(self):
self.configureStep()
self.setProperty('jsc_stress_test_failures', ['stress/force-error.js.default'])
self.setProperty('jsc_rerun_stress_test_failures', ['stress/force-error.js.default'])
self.setProperty('jsc_clean_tree_stress_test_failures', ['stress/force-error.js.default'])
self.expectOutcome(result=SUCCESS, state_string='Passed JSC tests')
return self.runStep()
def test_binary_failure_on_clean_tree(self):
self.configureStep()
self.setProperty('jsc_binary_failures', ['testdfg'])
self.setProperty('jsc_rerun_binary_failures', ['testdfg'])
self.setProperty('jsc_clean_tree_binary_failures', ['testdfg'])
self.expectOutcome(result=SUCCESS, state_string='Passed JSC tests')
return self.runStep()
def test_stress_and_binary_failure_on_clean_tree(self):
self.configureStep()
self.setProperty('jsc_stress_test_failures', ['es6.yaml/es6/Set_iterator_closing.js.default'])
self.setProperty('jsc_binary_failures', ['testair'])
self.setProperty('jsc_rerun_stress_test_failures', ['es6.yaml/es6/Set_iterator_closing.js.default'])
self.setProperty('jsc_rerun_binary_failures', ['testair'])
self.setProperty('jsc_clean_tree_stress_test_failures', ['es6.yaml/es6/Set_iterator_closing.js.default'])
self.setProperty('jsc_clean_tree_binary_failures', ['testair'])
self.expectOutcome(result=SUCCESS, state_string='Passed JSC tests')
return self.runStep()
def test_flaky_stress_and_binary_failures(self):
self.configureStep()
self.setProperty('jsc_stress_test_failures', ['stress/force-error.js.default'])
self.setProperty('jsc_binary_failures', ['testapi'])
self.expectOutcome(result=SUCCESS, state_string='Passed JSC tests')
return self.runStep()
def test_flaky_and_consistent_stress_failures(self):
self.configureStep()
self.setProperty('jsc_stress_test_failures', ['test1', 'test2'])
self.setProperty('jsc_rerun_stress_test_failures', ['test2'])
self.expectOutcome(result=FAILURE, state_string='Found 1 new JSC stress test failure: test2 (failure)')
return self.runStep()
def test_flaky_and_consistent_failures_with_clean_tree_failures(self):
self.configureStep()
self.setProperty('jsc_stress_test_failures', ['test1', 'test2'])
self.setProperty('jsc_rerun_stress_test_failures', ['test1'])
self.setProperty('jsc_clean_tree_stress_test_failures', ['test1', 'test2'])
self.expectOutcome(result=SUCCESS, state_string='Passed JSC tests')
return self.runStep()
def test_unexpected_infra_issue(self):
self.configureStep()
self.setProperty('jsc_stress_test_failures', [])
self.setProperty('jsc_rerun_stress_test_failures', [])
self.setProperty('jsc_clean_tree_stress_test_failures', [])
self.setProperty('clean_tree_run_status', FAILURE)
self.expectOutcome(result=RETRY, state_string='Unexpected infrastructure issue, retrying build (retry)')
return self.runStep()
def test_patch_breaking_jsc_test_suite(self):
self.configureStep()
self.setProperty('jsc_stress_test_failures', [])
self.setProperty('jsc_rerun_stress_test_failures', [])
self.setProperty('jsc_clean_tree_stress_test_failures', [])
self.setProperty('clean_tree_run_status', SUCCESS)
self.expectOutcome(result=FAILURE, state_string='Found unexpected failure with patch (failure)')
return self.runStep()
class TestRunWebKitTests(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
self.jsonFileName = 'layout-test-results/full_results.json'
self.results_json_regressions = '''ADD_RESULTS({"tests":{"imported":{"w3c":{"web-platform-tests":{"IndexedDB":{"interleaved-cursors-large.html":{"report":"REGRESSION","expected":"PASS","actual":"TEXT"}},"wasm":{"jsapi":{"interface.any.html":{"report":"REGRESSION","expected":"PASS","actual":"TEXT"},"instance":{"constructor-bad-imports.any.html":{"report":"REGRESSION","expected":"PASS","actual":"TEXT"}},"global":{"constructor.any.html":{"report":"REGRESSION","expected":"PASS","actual":"TEXT"},"constructor.any.worker.html":{"report":"REGRESSION","expected":"PASS","actual":"TEXT"},"toString.any.html":{"report":"REGRESSION","expected":"PASS","actual":"TEXT"}},"constructor":{"instantiate-bad-imports.any.html":{"report":"REGRESSION","expected":"PASS","actual":"TEXT"},"instantiate-bad-imports.any.worker.html":{"report":"REGRESSION","expected":"PASS","actual":"TEXT"}},"interface.any.worker.html":{"report":"REGRESSION","expected":"PASS","actual":"TEXT"}}}}},"blink":{"storage":{"indexeddb":{"blob-valid-before-commit.html":{"report":"REGRESSION","expected":"PASS","actual":"TIMEOUT","has_stderr":true}}}}}},"skipped":23256,"num_regressions":10,"other_crashes":{},"interrupted":true,"num_missing":0,"layout_tests_dir":"/Volumes/Data/worker/iOS-12-Simulator-WK2-Tests-EWS/build/LayoutTests","version":4,"num_passes":32056,"pixel_tests_enabled":false,"date":"06:21AM on July 15, 2019","has_pretty_patch":true,"fixable":23267,"num_flaky":0,"uses_expectations_file":true});
'''
self.results_json_flakes = '''ADD_RESULTS({"tests":{"http":{"tests":{"workers":{"service":{"service-worker-resource-timing.https.html":{"report":"FLAKY","expected":"PASS","actual":"TIMEOUT PASS","has_stderr":true}}},"xmlhttprequest":{"post-content-type-document.html":{"report":"FLAKY","expected":"PASS","actual":"TIMEOUT PASS"}}}},"imported":{"blink":{"storage":{"indexeddb":{"blob-valid-before-commit.html":{"report":"FLAKY","expected":"PASS","actual":"TIMEOUT PASS","has_stderr":true}}},"fast":{"text":{"international":{"repaint-glyph-bounds.html":{"report":"FLAKY","expected":"PASS","actual":"IMAGE PASS","reftest_type":["=="],"image_diff_percent":0.08}}}}}}},"skipped":13176,"num_regressions":0,"other_crashes":{},"interrupted":false,"num_missing":0,"layout_tests_dir":"/Volumes/Data/worker/iOS-12-Simulator-WK2-Tests-EWS/build/LayoutTests","version":4,"num_passes":42185,"pixel_tests_enabled":false,"date":"06:54AM on July 17, 2019","has_pretty_patch":true,"fixable":55356,"num_flaky":4,"uses_expectations_file":true});
'''
self.results_json_mix_flakes_and_regression = '''ADD_RESULTS({"tests":{"http":{"tests":{"IndexedDB":{"collect-IDB-objects.https.html":{"report":"FLAKY","expected":"PASS","actual":"TEXT PASS"}},"xmlhttprequest":{"on-network-timeout-error-during-preflight.html":{"report":"FLAKY","expected":"PASS","actual":"TIMEOUT PASS"}}}},"transitions":{"lengthsize-transition-to-from-auto.html":{"report":"FLAKY","expected":"PASS","actual":"TIMEOUT PASS"}},"imported":{"blink":{"storage":{"indexeddb":{"blob-valid-before-commit.html":{"report":"FLAKY","expected":"PASS","actual":"TIMEOUT PASS","has_stderr":true}}}}},"fast":{"text":{"font-weight-fallback.html":{"report":"FLAKY","expected":"PASS","actual":"TIMEOUT PASS","has_stderr":true,"reftest_type":["=="]}},"scrolling":{"ios":{"reconcile-layer-position-recursive.html":{"report":"REGRESSION","expected":"PASS","actual":"TEXT"}}}}},"skipped":13174,"num_regressions":1,"other_crashes":{},"interrupted":false,"num_missing":0,"layout_tests_dir":"/Volumes/Data/worker/iOS-12-Simulator-WK2-Tests-EWS/build/LayoutTests","version":4,"num_passes":42158,"pixel_tests_enabled":false,"date":"11:28AM on July 16, 2019","has_pretty_patch":true,"fixable":55329,"num_flaky":5,"uses_expectations_file":true});
'''
self.results_json_with_newlines = '''ADD_RESULTS({"tests":{"http":{"tests":{"IndexedDB":{"collect-IDB-objects.https.html":{"report":"FLAKY","expected":"PASS","actual":"TEXT PASS"}},"xmlhttprequest":{"on-network-timeout-error-during-preflight.html":{"report":"FLAKY","expected":"PASS","actual":"TIMEOUT PASS"}}}},"transitions":{"lengthsize-trans
ition-to-from-auto.html":{"report":"FLAKY","expected":"PASS","actual":"TIMEOUT PASS"}},"imported":{"blink":{"storage":{"indexeddb":{"blob-valid-before-commit.html":{"report":"FLAKY","expected":"PASS","actual":"TIMEOUT PASS","has_stderr":true}}}}},"fast":{"text":{"font-weight-fallback.html":{"report":"FLAKY","expected":"PASS","actual":"TIMEOUT PASS","has_stderr":true,"reftest_type":["=="]}},"scrolling":{"ios":{"reconcile-layer-position-recursive.html":{"report":"REGRESSION","expected":"PASS","actual":"TEXT"}}}}},"skipped":13174,"num_regressions":1,"other_crashes":{},"interrupted":false,"num_missing":0,"layout_tests_dir":"/Volumes/Data/worker/iOS-12-Simulator-WK2-Tests-EWS/build/LayoutTes
ts","version":4,"num_passes":42158,"pixel_tests_enabled":false,"date":"11:28AM on July 16, 2019","has_pretty_patch":true,"fixable":55329,"num_flaky":5,"uses_expectations_file":true});
'''
self.results_with_missing_results = '''ADD_RESULTS({"tests":{"http":{"wpt":{"css":{"css-highlight-api":{"highlight-image-expected-mismatched.html":{"report":"MISSING","expected":"PASS","is_missing_text":true,"actual":"MISSING"},"highlight-image.html":{"report":"MISSING","expected":"PASS","is_missing_text":true,"actual":"MISSING"}}}}}}, "interrupted":false});
'''
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def configureStep(self):
self.setupStep(RunWebKitTests())
self.property_exceed_failure_limit = 'first_results_exceed_failure_limit'
self.property_failures = 'first_run_failures'
def test_success(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python', 'Tools/Scripts/run-webkit-tests', '--no-build', '--no-show-results', '--no-new-test-results', '--clobber-old-results', '--release', '--results-directory', 'layout-test-results', '--debug-rwt-logging', '--exit-after-n-failures', '30', '--skip-failing-tests'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Passed layout tests')
return self.runStep()
def test_warnings(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python', 'Tools/Scripts/run-webkit-tests', '--no-build', '--no-show-results', '--no-new-test-results', '--clobber-old-results', '--release', '--results-directory', 'layout-test-results', '--debug-rwt-logging', '--exit-after-n-failures', '30', '--skip-failing-tests'],
)
+ 0
+ ExpectShell.log('stdio', stdout='''Unexpected flakiness: timeouts (2)
imported/blink/storage/indexeddb/blob-valid-before-commit.html [ Timeout Pass ]
storage/indexeddb/modern/deleteindex-2.html [ Timeout Pass ]'''),
)
self.expectOutcome(result=WARNINGS, state_string='2 flakes')
return self.runStep()
def test_skip_for_revert_patches_on_commit_queue(self):
self.configureStep()
self.setProperty('buildername', 'Commit-Queue')
self.setProperty('fullPlatform', 'mac')
self.setProperty('configuration', 'debug')
self.setProperty('fast_commit_queue', True)
self.expectOutcome(result=SKIPPED, state_string='Skipped layout-tests in fast-cq mode')
return self.runStep()
def test_skip_for_mac_wk2_passed_patch_on_commit_queue(self):
self.configureStep()
self.setProperty('patch_id', '1234')
self.setProperty('buildername', 'Commit-Queue')
self.setProperty('fullPlatform', 'mac')
self.setProperty('configuration', 'debug')
self.setProperty('passed_mac_wk2', True)
self.expectOutcome(result=SKIPPED, state_string='Skipped layout-tests')
return self.runStep()
def test_parse_results_json_regression(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python', 'Tools/Scripts/run-webkit-tests', '--no-build', '--no-show-results', '--no-new-test-results', '--clobber-old-results', '--release', '--results-directory', 'layout-test-results', '--debug-rwt-logging', '--exit-after-n-failures', '30', '--skip-failing-tests'],
)
+ 2
+ ExpectShell.log('json', stdout=self.results_json_regressions),
)
self.expectOutcome(result=FAILURE, state_string='layout-tests (failure)')
rc = self.runStep()
self.assertEqual(self.getProperty(self.property_exceed_failure_limit), True)
self.assertEqual(self.getProperty(self.property_failures),
['imported/blink/storage/indexeddb/blob-valid-before-commit.html',
'imported/w3c/web-platform-tests/IndexedDB/interleaved-cursors-large.html',
'imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate-bad-imports.any.html',
'imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate-bad-imports.any.worker.html',
'imported/w3c/web-platform-tests/wasm/jsapi/global/constructor.any.html',
'imported/w3c/web-platform-tests/wasm/jsapi/global/constructor.any.worker.html',
'imported/w3c/web-platform-tests/wasm/jsapi/global/toString.any.html',
'imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-bad-imports.any.html',
'imported/w3c/web-platform-tests/wasm/jsapi/interface.any.html',
'imported/w3c/web-platform-tests/wasm/jsapi/interface.any.worker.html'])
return rc
def test_parse_results_json_flakes(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python', 'Tools/Scripts/run-webkit-tests', '--no-build', '--no-show-results', '--no-new-test-results', '--clobber-old-results', '--release', '--results-directory', 'layout-test-results', '--debug-rwt-logging', '--exit-after-n-failures', '30', '--skip-failing-tests'],
)
+ 0
+ ExpectShell.log('json', stdout=self.results_json_flakes),
)
self.expectOutcome(result=SUCCESS, state_string='Passed layout tests')
rc = self.runStep()
self.assertEqual(self.getProperty(self.property_exceed_failure_limit), False)
self.assertEqual(self.getProperty(self.property_failures), [])
return rc
def test_parse_results_json_flakes_and_regressions(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python', 'Tools/Scripts/run-webkit-tests', '--no-build', '--no-show-results', '--no-new-test-results', '--clobber-old-results', '--release', '--results-directory', 'layout-test-results', '--debug-rwt-logging', '--exit-after-n-failures', '30', '--skip-failing-tests'],
)
+ 2
+ ExpectShell.log('json', stdout=self.results_json_mix_flakes_and_regression),
)
self.expectOutcome(result=FAILURE, state_string='layout-tests (failure)')
rc = self.runStep()
self.assertEqual(self.getProperty(self.property_exceed_failure_limit), False)
self.assertEqual(self.getProperty(self.property_failures), ['fast/scrolling/ios/reconcile-layer-position-recursive.html'])
return rc
def test_parse_results_json_with_newlines(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python', 'Tools/Scripts/run-webkit-tests', '--no-build', '--no-show-results', '--no-new-test-results', '--clobber-old-results', '--release', '--results-directory', 'layout-test-results', '--debug-rwt-logging', '--exit-after-n-failures', '30', '--skip-failing-tests'],
)
+ 2
+ ExpectShell.log('json', stdout=self.results_json_with_newlines),
)
self.expectOutcome(result=FAILURE, state_string='layout-tests (failure)')
rc = self.runStep()
self.assertEqual(self.getProperty(self.property_exceed_failure_limit), False)
self.assertEqual(self.getProperty(self.property_failures), ['fast/scrolling/ios/reconcile-layer-position-recursive.html'])
return rc
def test_parse_results_json_with_missing_results(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python', 'Tools/Scripts/run-webkit-tests', '--no-build', '--no-show-results', '--no-new-test-results', '--clobber-old-results', '--release', '--results-directory', 'layout-test-results', '--debug-rwt-logging', '--exit-after-n-failures', '30', '--skip-failing-tests'],
)
+ 2
+ ExpectShell.log('json', stdout=self.results_with_missing_results),
)
self.expectOutcome(result=FAILURE, state_string='layout-tests (failure)')
rc = self.runStep()
self.assertEqual(self.getProperty(self.property_exceed_failure_limit), False)
self.assertEqual(self.getProperty(self.property_failures),
['http/wpt/css/css-highlight-api/highlight-image-expected-mismatched.html',
'http/wpt/css/css-highlight-api/highlight-image.html'])
return rc
def test_unexpected_error(self):
self.configureStep()
self.setProperty('fullPlatform', 'mac-highsierra')
self.setProperty('configuration', 'debug')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python', 'Tools/Scripts/run-webkit-tests', '--no-build', '--no-show-results', '--no-new-test-results', '--clobber-old-results', '--debug', '--results-directory', 'layout-test-results', '--debug-rwt-logging', '--exit-after-n-failures', '30', '--skip-failing-tests'],
)
+ ExpectShell.log('stdio', stdout='Unexpected error.')
+ 254,
)
self.expectOutcome(result=FAILURE, state_string='layout-tests (failure)')
return self.runStep()
def test_failure(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python', 'Tools/Scripts/run-webkit-tests', '--no-build', '--no-show-results', '--no-new-test-results', '--clobber-old-results', '--release', '--results-directory', 'layout-test-results', '--debug-rwt-logging', '--exit-after-n-failures', '30', '--skip-failing-tests'],
)
+ ExpectShell.log('stdio', stdout='9 failures found.')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='layout-tests (failure)')
return self.runStep()
def test_success_wpt_import_bot(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.setProperty('patch_author', 'webkit-wpt-import-bot@igalia.com')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python', 'Tools/Scripts/run-webkit-tests', '--no-build', '--no-show-results', '--no-new-test-results', '--clobber-old-results', '--release', '--results-directory', 'layout-test-results', '--debug-rwt-logging', 'imported/w3c/web-platform-tests'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Passed layout tests')
return self.runStep()
class TestReRunWebKitTests(TestRunWebKitTests):
def configureStep(self):
self.setupStep(ReRunWebKitTests())
self.property_exceed_failure_limit = 'second_results_exceed_failure_limit'
self.property_failures = 'second_run_failures'
ReRunWebKitTests.send_email_for_flaky_failure = lambda self, test: None
def test_flaky_failures_in_first_run(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.setProperty('first_run_failures', ['test1', 'test2'])
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python', 'Tools/Scripts/run-webkit-tests', '--no-build', '--no-show-results', '--no-new-test-results', '--clobber-old-results', '--release', '--results-directory', 'layout-test-results', '--debug-rwt-logging', '--exit-after-n-failures', '30', '--skip-failing-tests'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Passed layout tests')
rc = self.runStep()
self.assertEqual(self.getProperty('build_summary'), 'Found flaky tests: test1, test2')
return rc
def test_first_run_failed_unexpectedly(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.setProperty('first_run_failures', [])
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python', 'Tools/Scripts/run-webkit-tests', '--no-build', '--no-show-results', '--no-new-test-results', '--clobber-old-results', '--release', '--results-directory', 'layout-test-results', '--debug-rwt-logging', '--exit-after-n-failures', '30', '--skip-failing-tests'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Passed layout tests')
rc = self.runStep()
self.assertEqual(self.getProperty('build_summary'), 'Passed layout tests')
return rc
class TestRunWebKitTestsInStressMode(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
self.jsonFileName = 'layout-test-results/full_results.json'
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def configureStep(self):
self.setupStep(RunWebKitTestsInStressMode())
self.property_exceed_failure_limit = 'first_results_exceed_failure_limit'
self.property_failures = 'first_run_failures'
def test_success(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.setProperty('modified_tests', ['test1', 'test2'])
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python',
'Tools/Scripts/run-webkit-tests',
'--no-build', '--no-show-results', '--no-new-test-results', '--clobber-old-results',
'--release', '--results-directory', 'layout-test-results', '--debug-rwt-logging',
'--exit-after-n-failures', '10', '--skip-failing-tests',
'--iterations', 100, 'test1', 'test2'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Passed layout tests')
return self.runStep()
def test_failure(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.setProperty('modified_tests', ['test'])
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python',
'Tools/Scripts/run-webkit-tests',
'--no-build', '--no-show-results', '--no-new-test-results', '--clobber-old-results',
'--release', '--results-directory', 'layout-test-results', '--debug-rwt-logging',
'--exit-after-n-failures', '10', '--skip-failing-tests',
'--iterations', 100, 'test'],
)
+ ExpectShell.log('stdio', stdout='9 failures found.')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='layout-tests (failure)')
rc = self.runStep()
self.assertEqual(self.getProperty('build_summary'), 'Found test failures')
return rc
class TestRunWebKitTestsInStressGuardmallocMode(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
self.jsonFileName = 'layout-test-results/full_results.json'
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def configureStep(self):
self.setupStep(RunWebKitTestsInStressGuardmallocMode())
self.property_exceed_failure_limit = 'first_results_exceed_failure_limit'
self.property_failures = 'first_run_failures'
def test_success(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.setProperty('modified_tests', ['test1', 'test2'])
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python',
'Tools/Scripts/run-webkit-tests',
'--no-build', '--no-show-results', '--no-new-test-results', '--clobber-old-results',
'--release', '--results-directory', 'layout-test-results', '--debug-rwt-logging',
'--exit-after-n-failures', '10', '--skip-failing-tests', '--guard-malloc',
'--iterations', 100, 'test1', 'test2'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Passed layout tests')
return self.runStep()
def test_failure(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.setProperty('modified_tests', ['test'])
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python',
'Tools/Scripts/run-webkit-tests',
'--no-build', '--no-show-results', '--no-new-test-results', '--clobber-old-results',
'--release', '--results-directory', 'layout-test-results', '--debug-rwt-logging',
'--exit-after-n-failures', '10', '--skip-failing-tests', '--guard-malloc',
'--iterations', 100, 'test'],
)
+ ExpectShell.log('stdio', stdout='9 failures found.')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='layout-tests (failure)')
rc = self.runStep()
self.assertEqual(self.getProperty('build_summary'), 'Found test failures')
return rc
class TestRunWebKitTestsWithoutPatch(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
self.jsonFileName = 'layout-test-results/full_results.json'
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def configureStep(self):
self.setupStep(RunWebKitTestsWithoutPatch())
self.property_exceed_failure_limit = 'clean_tree_results_exceed_failure_limit'
self.property_failures = 'clean_tree_run_failures'
self.setProperty('buildername', 'iOS-13-Simulator-WK2-Tests-EWS')
self.setProperty('buildnumber', '123')
self.setProperty('workername', 'ews126')
def test_success(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python',
'Tools/Scripts/run-webkit-tests',
'--no-build',
'--no-show-results',
'--no-new-test-results',
'--clobber-old-results',
'--release',
'--results-directory', 'layout-test-results',
'--debug-rwt-logging',
'--exit-after-n-failures', '30',
'--skip-failing-tests'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='layout-tests')
return self.runStep()
def test_success_retry_only_subset(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.setProperty('first_run_failures', ['test1', 'test2', 'test3'])
self.setProperty('second_run_failures', ['test1', 'test3', 'test4'])
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python',
'Tools/Scripts/run-webkit-tests',
'--no-build',
'--no-show-results',
'--no-new-test-results',
'--clobber-old-results',
'--release',
'--results-directory', 'layout-test-results',
'--debug-rwt-logging',
'--exit-after-n-failures', '30',
'--skip-failing-tests',
'test1', 'test2', 'test3', 'test4'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='layout-tests')
return self.runStep()
def test_success_retry_only_subset_limit_exceeded(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.setProperty('first_run_failures', ['test1', 'test2', 'test3'])
self.setProperty('second_results_exceed_failure_limit', True)
self.setProperty('second_run_failures', ['test{}'.format(i) for i in range(0, 30)])
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python',
'Tools/Scripts/run-webkit-tests',
'--no-build',
'--no-show-results',
'--no-new-test-results',
'--clobber-old-results',
'--release',
'--results-directory', 'layout-test-results',
'--debug-rwt-logging',
'--exit-after-n-failures', '30',
'--skip-failing-tests'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='layout-tests')
return self.runStep()
def test_success_retry_only_subset_patch_no_modifies_expectations(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.setProperty('first_run_failures', ['test1', 'test2', 'test3'])
self.setProperty('second_run_failures', ['test1', 'test3', 'test4'])
RunWebKitTests._get_patch = lambda x: b'+++ Tools/ChangeLog\n+++ Tools/WebKitTestRunner/Options.cpp\n'
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python',
'Tools/Scripts/run-webkit-tests',
'--no-build',
'--no-show-results',
'--no-new-test-results',
'--clobber-old-results',
'--release',
'--results-directory', 'layout-test-results',
'--debug-rwt-logging',
'--exit-after-n-failures', '30',
'--skip-failing-tests',
'test1', 'test2', 'test3', 'test4'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='layout-tests')
return self.runStep()
def test_success_retry_only_subset_patch_modifies_expectations(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.setProperty('first_run_failures', ['test1', 'test2', 'test3'])
self.setProperty('second_run_failures', ['test1', 'test3', 'test4'])
RunWebKitTests._get_patch = lambda x: b'+++ LayoutTests/Changelog\n+++ LayoutTests/platform/gtk/TestExpectations\n'
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python',
'Tools/Scripts/run-webkit-tests',
'--no-build',
'--no-show-results',
'--no-new-test-results',
'--clobber-old-results',
'--release',
'--results-directory', 'layout-test-results',
'--debug-rwt-logging',
'--exit-after-n-failures', '30',
'--skip-failing-tests'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='layout-tests')
return self.runStep()
def test_failure(self):
self.configureStep()
self.setProperty('fullPlatform', 'ios-simulator')
self.setProperty('configuration', 'release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python',
'Tools/Scripts/run-webkit-tests',
'--no-build',
'--no-show-results',
'--no-new-test-results',
'--clobber-old-results',
'--release',
'--results-directory', 'layout-test-results',
'--debug-rwt-logging',
'--exit-after-n-failures', '30',
'--skip-failing-tests'],
)
+ ExpectShell.log('stdio', stdout='9 failures found.')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='layout-tests (failure)')
return self.runStep()
class TestRunWebKit1Tests(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
self.jsonFileName = 'layout-test-results/full_results.json'
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(RunWebKit1Tests())
self.setProperty('fullPlatform', 'ios-11')
self.setProperty('configuration', 'debug')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python', 'Tools/Scripts/run-webkit-tests', '--no-build', '--no-show-results', '--no-new-test-results', '--clobber-old-results', '--debug', '--dump-render-tree', '--results-directory', 'layout-test-results', '--debug-rwt-logging', '--exit-after-n-failures', '30', '--skip-failing-tests'],
)
+ 0,
)
self.expectOutcome(result=SUCCESS, state_string='Passed layout tests')
return self.runStep()
def test_failure(self):
self.setupStep(RunWebKit1Tests())
self.setProperty('fullPlatform', 'ios-11')
self.setProperty('configuration', 'release')
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
logfiles={'json': self.jsonFileName},
logEnviron=False,
command=['python', 'Tools/Scripts/run-webkit-tests', '--no-build', '--no-show-results', '--no-new-test-results', '--clobber-old-results', '--release', '--dump-render-tree', '--results-directory', 'layout-test-results', '--debug-rwt-logging', '--exit-after-n-failures', '30', '--skip-failing-tests'],
)
+ ExpectShell.log('stdio', stdout='9 failures found.')
+ 2,
)
self.expectOutcome(result=FAILURE, state_string='layout-tests (failure)')
return self.runStep()
def test_skip_for_revert_patches_on_commit_queue(self):
self.setupStep(RunWebKit1Tests())
self.setProperty('buildername', 'Commit-Queue')
self.setProperty('fullPlatform', 'mac')
self.setProperty('configuration', 'debug')
self.setProperty('fast_commit_queue', True)
self.expectOutcome(result=SKIPPED, state_string='Skipped layout-tests in fast-cq mode')
return self.runStep()
class TestAnalyzeLayoutTestsResults(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def configureStep(self):
AnalyzeLayoutTestsResults.send_email_for_flaky_failure = lambda self, test: None
AnalyzeLayoutTestsResults.send_email_for_pre_existing_failure = lambda self, test: None
self.setupStep(AnalyzeLayoutTestsResults())
self.setProperty('first_results_exceed_failure_limit', False)
self.setProperty('second_results_exceed_failure_limit', False)
self.setProperty('clean_tree_results_exceed_failure_limit', False)
self.setProperty('clean_tree_run_failures', [])
def test_failure_introduced_by_patch(self):
self.configureStep()
self.setProperty('first_run_failures', ["jquery/offset.html"])
self.setProperty('second_run_failures', ["jquery/offset.html"])
self.expectOutcome(result=FAILURE, state_string='Found 1 new test failure: jquery/offset.html (failure)')
return self.runStep()
def test_failure_on_clean_tree(self):
self.configureStep()
self.setProperty('first_run_failures', ["jquery/offset.html"])
self.setProperty('second_run_failures', ["jquery/offset.html"])
self.setProperty('clean_tree_run_failures', ["jquery/offset.html"])
self.expectOutcome(result=SUCCESS, state_string='Passed layout tests')
rc = self.runStep()
self.assertEqual(self.getProperty('build_summary'), 'Found 1 pre-existing test failure: jquery/offset.html')
return rc
def test_flaky_and_consistent_failures_without_clean_tree_failures(self):
self.configureStep()
self.setProperty('buildername', 'iOS-13-Simulator-WK2-Tests-EWS')
self.setProperty('first_run_failures', ['test1', 'test2'])
self.setProperty('second_run_failures', ['test1'])
self.expectOutcome(result=FAILURE, state_string='Found 1 new test failure: test1 (failure)')
rc = self.runStep()
self.assertEqual(self.getProperty('bugzilla_comment_text'), None)
self.assertEqual(self.getProperty('build_finish_summary'), 'Found 1 new test failure: test1')
return rc
def test_consistent_failure_without_clean_tree_failures_commit_queue(self):
self.configureStep()
self.setProperty('buildername', 'Commit-Queue')
self.setProperty('first_run_failures', ['test1'])
self.setProperty('second_run_failures', ['test1'])
self.expectOutcome(result=FAILURE, state_string='Found 1 new test failure: test1 (failure)')
rc = self.runStep()
self.assertEqual(self.getProperty('bugzilla_comment_text'), 'Found 1 new test failure: test1')
self.assertEqual(self.getProperty('build_finish_summary'), 'Found 1 new test failure: test1')
return rc
def test_flaky_and_inconsistent_failures_without_clean_tree_failures(self):
self.configureStep()
self.setProperty('first_run_failures', ['test1', 'test2'])
self.setProperty('second_run_failures', ['test3'])
self.expectOutcome(result=SUCCESS, state_string='Passed layout tests')
return self.runStep()
def test_flaky_failures_in_first_run(self):
self.configureStep()
self.setProperty('first_run_failures', ['test1', 'test2'])
self.setProperty('second_run_failures', [])
self.expectOutcome(result=SUCCESS, state_string='Passed layout tests')
rc = self.runStep()
self.assertEqual(self.getProperty('build_summary'), ' Found flaky tests: test1, test2')
return rc
def test_flaky_and_inconsistent_failures_with_clean_tree_failures(self):
self.configureStep()
self.setProperty('first_run_failures', ['test1', 'test2'])
self.setProperty('second_run_failures', ['test3'])
self.setProperty('clean_tree_run_failures', ['test1', 'test2', 'test3'])
self.expectOutcome(result=SUCCESS, state_string='Passed layout tests')
rc = self.runStep()
self.assertEqual(self.getProperty('build_summary'), 'Found 3 pre-existing test failures: test1, test2, test3 Found flaky tests: test1, test2, test3')
return rc
def test_flaky_and_consistent_failures_with_clean_tree_failures(self):
self.configureStep()
self.setProperty('first_run_failures', ['test1', 'test2'])
self.setProperty('second_run_failures', ['test1'])
self.setProperty('clean_tree_run_failures', ['test1', 'test2'])
self.expectOutcome(result=SUCCESS, state_string='Passed layout tests')
return self.runStep()
def test_mildly_flaky_patch_with_some_tree_redness_and_flakiness(self):
self.configureStep()
self.setProperty('first_run_failures', ['test1', 'test2', 'test3'])
self.setProperty('second_run_failures', ['test1', 'test2'])
self.setProperty('clean_tree_run_failures', ['test1', 'test2', 'test4'])
self.expectOutcome(result=SUCCESS, state_string='Passed layout tests')
rc = self.runStep()
self.assertEqual(self.getProperty('build_summary'), 'Found 3 pre-existing test failures: test1, test2, test4 Found flaky test: test3')
return rc
def test_first_run_exceed_failure_limit(self):
self.configureStep()
self.setProperty('first_results_exceed_failure_limit', True)
self.setProperty('first_run_failures', ['test{}'.format(i) for i in range(0, 30)])
self.setProperty('second_run_failures', [])
self.expectOutcome(result=RETRY, state_string='Unable to confirm if test failures are introduced by patch, retrying build (retry)')
return self.runStep()
def test_second_run_exceed_failure_limit(self):
self.configureStep()
self.setProperty('first_run_failures', [])
self.setProperty('second_results_exceed_failure_limit', True)
self.setProperty('second_run_failures', ['test{}'.format(i) for i in range(0, 30)])
self.expectOutcome(result=RETRY, state_string='Unable to confirm if test failures are introduced by patch, retrying build (retry)')
return self.runStep()
def test_clean_tree_exceed_failure_limit(self):
self.configureStep()
self.setProperty('first_run_failures', ['test1'])
self.setProperty('second_run_failures', ['test1'])
self.setProperty('clean_tree_results_exceed_failure_limit', True)
self.setProperty('clean_tree_run_failures', ['test{}'.format(i) for i in range(0, 30)])
self.expectOutcome(result=RETRY, state_string='Unable to confirm if test failures are introduced by patch, retrying build (retry)')
return self.runStep()
def test_clean_tree_exceed_failure_limit_with_triggered_by(self):
self.configureStep()
self.setProperty('buildername', 'iOS-13-Simulator-WK2-Tests-EWS')
self.setProperty('triggered_by', 'ios-13-sim-build-ews')
self.setProperty('first_run_failures', ['test1'])
self.setProperty('second_run_failures', ['test1'])
self.setProperty('clean_tree_results_exceed_failure_limit', True)
self.setProperty('clean_tree_run_failures', ['test{}'.format(i) for i in range(0, 30)])
message = 'Unable to confirm if test failures are introduced by patch, retrying build'
self.expectOutcome(result=SUCCESS, state_string=message)
rc = self.runStep()
self.assertEqual(self.getProperty('build_summary'), message)
return rc
def test_clean_tree_has_lot_of_failures(self):
self.configureStep()
self.setProperty('first_results_exceed_failure_limit', True)
self.setProperty('first_run_failures', ['test{}'.format(i) for i in range(0, 30)])
self.setProperty('second_results_exceed_failure_limit', True)
self.setProperty('second_run_failures', ['test{}'.format(i) for i in range(0, 30)])
self.setProperty('clean_tree_run_failures', ['test{}'.format(i) for i in range(0, 27)])
self.expectOutcome(result=RETRY, state_string='Unable to confirm if test failures are introduced by patch, retrying build (retry)')
return self.runStep()
def test_clean_tree_has_some_failures(self):
self.configureStep()
self.setProperty('first_results_exceed_failure_limit', True)
self.setProperty('first_run_failures', ['test{}'.format(i) for i in range(0, 30)])
self.setProperty('second_results_exceed_failure_limit', True)
self.setProperty('second_run_failures', ['test{}'.format(i) for i in range(0, 30)])
self.setProperty('clean_tree_run_failures', ['test{}'.format(i) for i in range(0, 10)])
self.expectOutcome(result=FAILURE, state_string='Found 30 new test failures: test0, test1, test10, test11, test12, test13, test14, test15, test16, test17 ... (failure)')
return self.runStep()
def test_clean_tree_has_lot_of_failures_and_no_new_failure(self):
self.configureStep()
self.setProperty('first_run_failures', ['test1'])
self.setProperty('second_run_failures', ['test1'])
self.setProperty('clean_tree_run_failures', ['test{}'.format(i) for i in range(0, 20)])
self.expectOutcome(result=SUCCESS, state_string='Passed layout tests')
rc = self.runStep()
self.assertEqual(self.getProperty('build_summary'), 'Found 20 pre-existing test failures: test0, test1, test10, test11, test12, test13, test14, test15, test16, test17 ...')
return rc
def test_patch_introduces_lot_of_failures(self):
self.configureStep()
self.setProperty('buildername', 'Commit-Queue')
self.setProperty('first_results_exceed_failure_limit', True)
self.setProperty('first_run_failures', ['test{}'.format(i) for i in range(0, 300)])
self.setProperty('second_results_exceed_failure_limit', True)
self.setProperty('second_run_failures', ['test{}'.format(i) for i in range(0, 300)])
failure_message = 'Found 300 new test failures: test0, test1, test10, test100, test101, test102, test103, test104, test105, test106 ...'
self.expectOutcome(result=FAILURE, state_string=failure_message + ' (failure)')
rc = self.runStep()
self.assertEqual(self.getProperty('bugzilla_comment_text'), failure_message)
self.assertEqual(self.getProperty('build_finish_summary'), failure_message)
return rc
def test_unexpected_infra_issue(self):
self.configureStep()
self.setProperty('first_run_failures', [])
self.setProperty('second_run_failures', [])
self.setProperty('clean_tree_run_status', FAILURE)
self.expectOutcome(result=RETRY, state_string='Unexpected infrastructure issue, retrying build (retry)')
return self.runStep()
def test_patch_breaks_layout_tests(self):
self.configureStep()
self.setProperty('first_run_failures', [])
self.setProperty('second_run_failures', [])
self.setProperty('clean_tree_run_failures', [])
self.setProperty('clean_tree_run_status', SUCCESS)
self.expectOutcome(result=FAILURE, state_string='Found unexpected failure with patch (failure)')
return self.runStep()
class TestCheckOutSpecificRevision(BuildStepMixinAdditions, unittest.TestCase):
def setUp(self):
self.longMessage = True
return self.setUpBuildStep()
def tearDown(self):
return self.tearDownBuildStep()
def test_success(self):
self.setupStep(CheckOutSpecificRevision())
self.setProperty('ews_revision', '1a3425cb92dbcbca12a10aa9514f1b77c76dc26')
self.expectHidden(False)
self.expectRemoteCommands(
ExpectShell(workdir='wkdir',
timeout=1200,
logEnviron=False,
command=['git', 'checkout', '1a3425cb92dbcbca12a10aa9514f1b77c76dc26'],
)