Diff
Modified: trunk/Tools/ChangeLog (276435 => 276436)
--- trunk/Tools/ChangeLog 2021-04-22 14:48:51 UTC (rev 276435)
+++ trunk/Tools/ChangeLog 2021-04-22 15:17:56 UTC (rev 276436)
@@ -1,5 +1,38 @@
2021-04-22 Sam Sneddon <[email protected]>
+ Add an xfail marker for webkitpy's tests; get SCM passing
+ https://bugs.webkit.org/show_bug.cgi?id=224886
+
+ Reviewed by Jonathan Bedard.
+
+ Also:
+
+ Delete the old, unused skip_if decorator.
+
+ Fix our runner to detect unexpected-success and report them as failures.
+
+ * Scripts/webkitpy/common/checkout/scm/scm_unittest.py:
+ (GitSVNTest.test_rebase_in_progress):
+ (GitTestWithMock.test_create_patch):
+ * Scripts/webkitpy/test/markers.py:
+ (xfail):
+ (xfail.decorator):
+ * Scripts/webkitpy/test/runner.py:
+ (Runner.handle):
+ (_Worker.handle):
+ (TestResult):
+ (TestResult.__init__):
+ (TestResult.addSuccess):
+ * Scripts/webkitpy/test/runner_unittest.py:
+ (FakeTestCase):
+ (FakeTestCase.__init__):
+ (FakeTestCase.id):
+ (FakeModuleSuite.run):
+ * Scripts/webkitpy/test/skip.py: Removed.
+ * Scripts/webkitpy/test/skip_unittest.py: Removed.
+
+2021-04-22 Sam Sneddon <[email protected]>
+
server_process_unittest.py's MockFile should all be bytes
https://bugs.webkit.org/show_bug.cgi?id=224877
Modified: trunk/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py (276435 => 276436)
--- trunk/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py 2021-04-22 14:48:51 UTC (rev 276435)
+++ trunk/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py 2021-04-22 15:17:56 UTC (rev 276436)
@@ -59,6 +59,8 @@
from webkitpy.common.checkout.scm.scm import CheckoutNeedsUpdate, commit_error_handler, AuthenticationError
from webkitpy.common.checkout.scm.svn import SVN
+from webkitpy.test.markers import xfail
+
from webkitcorepy import OutputCapture
try:
@@ -1242,6 +1244,7 @@
self.assertNotRegexpMatches(diff_to_common_base, b'foo')
self.assertRegexpMatches(diff_to_merge_base, b'foo')
+ @xfail
def test_rebase_in_progress(self):
svn_test_file = os.path.join(self.svn_checkout_path, 'test_file')
write_into_file_at_path(svn_test_file, "svn_checkout")
@@ -1722,6 +1725,7 @@
scm._executive._should_log = logging_executive
return scm
+ @xfail
def test_create_patch(self):
scm = self.make_scm(logging_executive=True)
with OutputCapture(level=logging.INFO) as captured:
Copied: trunk/Tools/Scripts/webkitpy/test/markers.py (from rev 276435, trunk/Tools/Scripts/webkitpy/test/skip.py) (0 => 276436)
--- trunk/Tools/Scripts/webkitpy/test/markers.py (rev 0)
+++ trunk/Tools/Scripts/webkitpy/test/markers.py 2021-04-22 15:17:56 UTC (rev 276436)
@@ -0,0 +1,54 @@
+# Copyright (C) 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 unittest
+
+
+def xfail(*args, **kwargs):
+ """a pytest.mark.xfail-like wrapper for unittest.expectedFailure
+
+ c.f. pytest.mark.xfail(condition, ..., *, reason=..., run=True, raises=None, strict=[from config])
+
+ Note that this doesn't support raises or strict"""
+
+ # shortcut if we're being called as a decorator ourselves
+ if len(args) == 1 and callable(args[0]) and not kwargs:
+ return unittest.expectedFailure(args[0])
+
+ def decorator(func):
+ conditions = args
+ reason = kwargs.get(reason, None)
+ run = kwargs.get(run, True)
+ if "raises" in kwargs:
+ raise TypeError("xfail(raises=...) is not supported")
+ if "strict" in kwargs:
+ raise TypeError("strict is not supported")
+
+ if not run:
+ return unittest.skip(reason)(func)
+
+ if all(conditions):
+ return unittest.expectedFailure(func)
+ else:
+ return func
+
+ return decorator
Modified: trunk/Tools/Scripts/webkitpy/test/runner.py (276435 => 276436)
--- trunk/Tools/Scripts/webkitpy/test/runner.py 2021-04-22 14:48:51 UTC (rev 276435)
+++ trunk/Tools/Scripts/webkitpy/test/runner.py 2021-04-22 15:17:56 UTC (rev 276436)
@@ -60,6 +60,9 @@
self.printer.print_started_test(source, test_name)
return
+ if message_name != 'finished_test':
+ raise ValueError("unknown message: %r" % message_type)
+
self.tests_run.append(test_name)
if failures:
self.failures.append((test_name, failures))
@@ -75,11 +78,28 @@
def handle(self, message_name, source, test_name):
assert message_name == 'test'
- result = unittest.TestResult()
+ result = TestResult()
start = time.time()
self._caller.post('started_test', test_name)
# We will need to rework this if a test_name results in multiple tests.
self._loader.loadTestsFromName(test_name, None).run(result)
+
+ assert(len(result.errors) + len(result.failures) +
+ len(result.skipped) + len(result.expectedFailures) +
+ len(result.unexpectedSuccesses) + result.successes) == result.testsRun
+
+ failures = ([failure[1] for failure in result.failures]
+ + ["UNEXPECTED SUCCESS" for _ in result.unexpectedSuccesses])
+
self._caller.post('finished_test', test_name, time.time() - start,
- [failure[1] for failure in result.failures], [error[1] for error in result.errors])
+ failures, [error[1] for error in result.errors])
+
+
+class TestResult(unittest.TestResult):
+ def __init__(self, *args, **kwargs):
+ super(TestResult, self).__init__(*args, **kwargs)
+ self.successes = 0
+
+ def addSuccess(self, test):
+ self.successes += 1
Modified: trunk/Tools/Scripts/webkitpy/test/runner_unittest.py (276435 => 276436)
--- trunk/Tools/Scripts/webkitpy/test/runner_unittest.py 2021-04-22 14:48:51 UTC (rev 276435)
+++ trunk/Tools/Scripts/webkitpy/test/runner_unittest.py 2021-04-22 15:17:56 UTC (rev 276436)
@@ -31,6 +31,15 @@
from webkitpy.test.runner import Runner
+class FakeTestCase(object):
+ def __init__(self, name):
+ self.name = name
+ self.failureException = AssertionError
+
+ def id(self):
+ return self.name
+
+
class FakeModuleSuite(object):
def __init__(self, name, result, msg):
self.name = name
@@ -41,11 +50,19 @@
return self.name
def run(self, result):
- result.testsRun += 1
- if self.result == 'F':
- result.failures.append((self.name, self.msg))
- elif self.result == 'E':
- result.errors.append((self.name, self.msg))
+ tc = FakeTestCase(self.name)
+ result.startTest(tc)
+ try:
+ if self.result == 'F':
+ result.addFailure(tc, (None, None, None))
+ elif self.result == 'E':
+ result.addError(tc, (None, None, None))
+ elif self.result == '.':
+ result.addSuccess(tc)
+ else:
+ assert False, "unreachable"
+ finally:
+ result.stopTest(tc)
class FakeTopSuite(object):
Deleted: trunk/Tools/Scripts/webkitpy/test/skip.py (276435 => 276436)
--- trunk/Tools/Scripts/webkitpy/test/skip.py 2021-04-22 14:48:51 UTC (rev 276435)
+++ trunk/Tools/Scripts/webkitpy/test/skip.py 2021-04-22 15:17:56 UTC (rev 276436)
@@ -1,52 +0,0 @@
-# Copyright (C) 2010 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 logging
-
-_log = logging.getLogger(__name__)
-
-
-def skip_if(klass, condition, message=None, logger=None):
- """Makes all test_* methods in a given class no-ops if the given condition
- is False. Backported from Python 3.1+'s unittest.skipIf decorator."""
- if not logger:
- logger = _log
- if not condition:
- return klass
- for name in dir(klass):
- attr = getattr(klass, name)
- if not callable(attr):
- continue
- if not name.startswith('test_'):
- continue
- setattr(klass, name, _skipped_method(attr, message, logger))
- klass._printed_skipped_message = False
- return klass
-
-
-def _skipped_method(method, message, logger):
- def _skip(self, *args):
- if self._printed_skipped_message:
- return
- self._printed_skipped_message = True
- logger.info('Skipping %s.%s: %s' % (method.__module__, type(self).__name__, message))
- return _skip
Deleted: trunk/Tools/Scripts/webkitpy/test/skip_unittest.py (276435 => 276436)
--- trunk/Tools/Scripts/webkitpy/test/skip_unittest.py 2021-04-22 14:48:51 UTC (rev 276435)
+++ trunk/Tools/Scripts/webkitpy/test/skip_unittest.py 2021-04-22 15:17:56 UTC (rev 276436)
@@ -1,75 +0,0 @@
-# Copyright (C) 2010 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 logging
-import unittest
-
-from webkitcorepy import StringIO
-
-from webkitpy.test.skip import skip_if
-
-
-class SkipTest(unittest.TestCase):
- def setUp(self):
- self.logger = logging.getLogger(__name__)
-
- self.old_level = self.logger.level
- self.logger.setLevel(logging.INFO)
-
- self.old_propagate = self.logger.propagate
- self.logger.propagate = False
-
- self.log_stream = StringIO()
- self.handler = logging.StreamHandler(self.log_stream)
- self.logger.addHandler(self.handler)
-
- self.foo_was_called = False
-
- def tearDown(self):
- self.logger.removeHandler(self.handler)
- self.propagate = self.old_propagate
- self.logger.setLevel(self.old_level)
-
- def create_fixture_class(self):
- class TestSkipFixture(object):
- def __init__(self, callback):
- self.callback = callback
-
- def test_foo(self):
- self.callback()
-
- return TestSkipFixture
-
- def foo_callback(self):
- self.foo_was_called = True
-
- def test_skip_if_false(self):
- klass = skip_if(self.create_fixture_class(), False, 'Should not see this message.', logger=self.logger)
- klass(self.foo_callback).test_foo()
- self.assertEqual(self.log_stream.getvalue(), '')
- self.assertTrue(self.foo_was_called)
-
- def test_skip_if_true(self):
- klass = skip_if(self.create_fixture_class(), True, 'Should see this message.', logger=self.logger)
- klass(self.foo_callback).test_foo()
- self.assertEqual(self.log_stream.getvalue(), 'Skipping webkitpy.test.skip_unittest.TestSkipFixture: Should see this message.\n')
- self.assertFalse(self.foo_was_called)