Diff
Modified: trunk/Tools/ChangeLog (254339 => 254340)
--- trunk/Tools/ChangeLog 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/ChangeLog 2020-01-10 16:16:19 UTC (rev 254340)
@@ -1,3 +1,90 @@
+2020-01-10 Jonathan Bedard <[email protected]>
+
+ Python 3: Add support to run-webkit-tests
+ https://bugs.webkit.org/show_bug.cgi?id=205291
+
+ Reviewed by Stephanie Lewis.
+
+ * Scripts/test-webkitpy-python3: Add webkitpy.layout_tests.
+ * Scripts/webkitpy/common/message_pool.py:
+ (_MessagePool._loop): Move exception inside of loop.
+ (_Message.__repr__): Use .format strings.
+ (_Worker.__init__): Ditto.
+ * Scripts/webkitpy/common/wavediff.py:
+ (WaveDiff.__init__): Use Python 3 compatible BytesIO and StringIO.
+ * Scripts/webkitpy/layout_tests/controllers/layout_test_finder.py:
+ (LayoutTestFinder._read_test_names_from_file): Use .format string.
+ (LayoutTestFinder.split_into_chunks): Explicitly use integer division.
+ * Scripts/webkitpy/layout_tests/controllers/manager.py:
+ (Manager._get_test_inputs): Use range over xrange.
+ * Scripts/webkitpy/layout_tests/controllers/single_test_runner.py:
+ (SingleTestRunner._handle_error): Use .format strings.
+ * Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py:
+ (JSONLayoutResultsGenerator._insert_failure_summaries): Use Python 3 compatible itervalues.
+ * Scripts/webkitpy/layout_tests/models/test_results.py:
+ (TestResult.__init__): Sort type list.
+ * Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py:
+ (RunTest.setUp): Multiple processes are buggy in test-webkitpy.
+ (RunTest.test_basic): replace buflist with getvalue().
+ (RunTest.test_child_processes_2): Ditto.
+ (RunTest.test_child_processes_min): Ditto.
+ (RunTest.test_keyboard_interrupt): Ditto.
+ (RunTest.test_missing_and_unexpected_results): Compare dictionaries instead of json strings.
+ (RunTest.test_crash_with_stderr): Ditto.
+ (RunTest.test_reftest_should_not_use_naming_convention_if_not_listed_in_reftestlist): Ditto.
+ (EndToEndTest.test_reftest_with_two_notrefs): Ditto.
+ * Scripts/webkitpy/layout_tests/views/metered_stream.py:
+ (MeteredStream.write): Flush stream after writing.
+ (MeteredStream._erase_last_partial_line): Ditto.
+ * Scripts/webkitpy/layout_tests/views/printing.py:
+ (Printer._print_directory_timings): Can't compare string to integer.
+ (Printer._print_statistics_for_test_timings): Use integer division.
+ * Scripts/webkitpy/port/darwin.py:
+ (DarwinPort._merge_crash_logs): Use items over iteritems.
+ * Scripts/webkitpy/port/device.py:
+ (Device.__hash__): Allow hashing of devices.
+ * Scripts/webkitpy/port/device_port.py:
+ (DevicePort._install): Use range over xrange.
+ (DevicePort.setup_test_run): Ditto.
+ (DevicePort.clean_up_test_run): Ditto.
+ * Scripts/webkitpy/port/driver.py:
+ (DriverOutput.__init__): Text should be decoded, audio encoded.
+ (Driver.__init__):
+ (Driver.run_test):
+ (Driver._parse_child_processes_output): Output is byte array.
+ (Driver._check_for_driver_timeout): Ditto.
+ (Driver._check_for_address_sanitizer_violation): Error lines are byte arrays.
+ (Driver._check_for_driver_crash_or_unresponsiveness): Ditto.
+ (Driver._read_optional_image_block): If a block is base64 encoded, we want the decoded
+ content, otherwise, we want the encoded content.
+ (Driver._read_header): Lines are byte arrays, decode them before processing.
+ (Driver._process_stdout_line): Blocks are byte arrays.
+ (Driver._strip_eof): Lines should be byte arrays, not strings.
+ (Driver._read_block): Standardize encoding in blocks.
+ (ContentBlock.__init__): Content should be a byte array.
+ (ContentBlock.decode_content): Attempt to decode content.
+ * Scripts/webkitpy/port/driver_unittest.py:
+ (DriverTest.test_read_binary_block): Content should be encoded.
+ (DriverTest.test_read_base64_block): Ditto.
+ (DriverTest.test_check_for_driver_crash): ServerProcess output should be a byte array.
+ * Scripts/webkitpy/port/image_diff.py:
+ (ImageDiffer.diff_image): ImageDiff output is in byte arrays.
+ (ImageDiffer._read): Ditto.
+ * Scripts/webkitpy/port/server_process.py:
+ (ServerProcess.write): Encode data before writing it.
+ * Scripts/webkitpy/port/server_process_mock.py:
+ (MockServerProcess.__init__): Convert string mock output to bytes.
+ (MockServerProcess.read_stdout_line): Stdout lines are byte arrays.
+ (MockServerProcess.read_stdout): Ditto.
+ * Scripts/webkitpy/port/simulator_process.py:
+ (SimulatorProcess.NonBlockingFileFromSocket.close): Don't double close socket in Python 3.
+ (SimulatorProcess._start): Stdin should be a binary stream.
+ * Scripts/webkitpy/port/test.py:
+ (unit_test_list): Convert audio streams to byte arrays.
+ * Scripts/webkitpy/xcode/simulated_device.py:
+ (SimulatedDevice.is_usable): Decode xcrun output.
+ (SimulatedDevice.install_app): Use xrange over range.
+
2020-01-10 Adrian Perez de Castro <[email protected]>
[Flatpak] Update IceCC to version 1.2
Modified: trunk/Tools/Scripts/test-webkitpy-python3 (254339 => 254340)
--- trunk/Tools/Scripts/test-webkitpy-python3 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/test-webkitpy-python3 2020-01-10 16:16:19 UTC (rev 254340)
@@ -37,11 +37,7 @@
'webkitpy.benchmark_runner',
'webkitpy.browserperfdash',
'webkitpy.common',
- 'webkitpy.layout_tests.controllers',
- 'webkitpy.layout_tests.layout_package',
- 'webkitpy.layout_tests.models',
- 'webkitpy.layout_tests.servers',
- 'webkitpy.layout_tests.views',
+ 'webkitpy.layout_tests',
'webkitpy.performance_tests',
'webkitpy.port',
'webkitpy.results',
Modified: trunk/Tools/Scripts/webkitpy/common/message_pool.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/common/message_pool.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/common/message_pool.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -185,22 +185,24 @@
return False
def _loop(self, block):
- try:
- while True:
- if len(self._workers_stopped) == len(self._workers):
- block = False
+ while True:
+ if len(self._workers_stopped) == len(self._workers):
+ block = False
+
+ try:
message = self._messages_to_manager.get(block)
- self._log_messages(message.logs)
- if message.from_user:
- self._caller.handle(message.name, message.src, *message.args)
- continue
- method = getattr(self, '_handle_' + message.name)
- assert method, 'bad message %s' % repr(message)
- method(message.src, *message.args)
- except queue.Empty:
- pass
+ except queue.Empty:
+ break
+ self._log_messages(message.logs)
+ if message.from_user:
+ self._caller.handle(message.name, message.src, *message.args)
+ continue
+ method = getattr(self, '_handle_' + message.name)
+ assert method, 'bad message %s' % repr(message)
+ method(message.src, *message.args)
+
class WorkerException(BaseException):
"""Raised when we receive an unexpected/unknown exception from a worker."""
pass
@@ -215,7 +217,13 @@
self.logs = logs
def __repr__(self):
- return '_Message(src="" name=%s, args=%s, from_user=%s, logs=%s)' % (self.src, self.name, self.args, self.from_user, self.logs)
+ return '_Message(src="" name={name}, args={args}, from_user={from_user}, logs={logs})'.format(
+ src=""
+ name=self.name,
+ args=self.args,
+ from_user=self.from_user,
+ logs=self.logs,
+ )
class _Worker(multiprocessing.Process):
@@ -223,7 +231,7 @@
super(_Worker, self).__init__()
self.host = host
self.worker_number = worker_number
- self.name = 'worker/%d' % worker_number
+ self.name = 'worker/{}'.format(worker_number)
self.log_messages = []
self.log_level = log_level
self._running_inline = running_inline
Modified: trunk/Tools/Scripts/webkitpy/common/wavediff.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/common/wavediff.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/common/wavediff.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -25,7 +25,7 @@
import tempfile
import wave
-from io import BytesIO
+from webkitpy.common.unicode_compatibility import BytesIO, StringIO
class WaveDiff(object):
@@ -35,12 +35,12 @@
_tolerance = 1
def __init__(self, in1, in2):
- if isinstance(in1, file):
- waveFile1 = wave.open(in1, 'rb')
+ if isinstance(in1, str):
+ waveFile1 = wave.open(StringIO(in1), 'r')
else:
waveFile1 = wave.open(BytesIO(in1), 'rb')
- if isinstance(in2, file):
- waveFile1 = wave.open(in2, 'rb')
+ if isinstance(in2, str):
+ waveFile2 = wave.open(StringIO(in2), 'r')
else:
waveFile2 = wave.open(BytesIO(in2), 'rb')
@@ -66,12 +66,12 @@
allData1 = self._readSamples(waveFile1, sampleWidth1, frameCount1 * channelCount1)
allData2 = self._readSamples(waveFile2, sampleWidth2, frameCount2 * channelCount2)
- results = map(self._diffSample, allData1, allData2, xrange(max(frameCount1 * channelCount1, frameCount2 * channelCount2)))
+ results = list(map(self._diffSample, allData1, allData2, range(max(frameCount1 * channelCount1, frameCount2 * channelCount2))))
cumulativeSampleDiff = sum(results)
- differingSampleCount = len(filter(bool, results))
+ differingSampleCount = len(list(filter(bool, results)))
self._filesAreIdentical = not differingSampleCount
- self._filesAreIdenticalWithinTolerance = not len(filter(lambda x: x > self._tolerance, results))
+ self._filesAreIdenticalWithinTolerance = not len(list(filter(lambda x: x > self._tolerance, results)))
if differingSampleCount:
self._diff += '\n'
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_finder.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_finder.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_finder.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -102,7 +102,7 @@
except IOError as e:
if e.errno == errno.ENOENT:
_log.critical('')
- _log.critical('--test-list file "%s" not found' % file)
+ _log.critical('--test-list file "{}" not found'.format(filenames))
raise
return tests
@@ -176,7 +176,7 @@
if rounded_tests % test_size != 0:
rounded_tests = (num_tests + test_size - (num_tests % test_size))
- chunk_len = rounded_tests / test_size
+ chunk_len = rounded_tests // test_size
slice_start = chunk_len * (chunk_num - 1)
# It does not mind if we go over test_size.
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -145,9 +145,9 @@
def _get_test_inputs(self, tests_to_run, repeat_each, iterations, device_type=None):
test_inputs = []
- for _ in xrange(iterations):
+ for _ in range(iterations):
for test in tests_to_run:
- for _ in xrange(repeat_each):
+ for _ in range(repeat_each):
test_inputs.append(self._test_input_for_file(test, device_type=device_type))
return test_inputs
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/controllers/single_test_runner.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -31,6 +31,7 @@
import re
import time
+from webkitpy.common.unicode_compatibility import decode_for
from webkitpy.layout_tests.controllers import test_result_writer
from webkitpy.port.driver import DriverInput, DriverOutput
from webkitpy.layout_tests.models import test_expectations
@@ -214,7 +215,7 @@
elif driver_output.error:
_log.debug("%s %s output stderr lines:" % (self._worker_name, testname))
for line in driver_output.error.splitlines():
- _log.debug(" %s" % line)
+ _log.debug(" {}".format(decode_for(line, str)))
return failures
def _compare_output(self, expected_driver_output, driver_output):
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -31,6 +31,7 @@
from webkitpy.layout_tests.layout_package import json_results_generator
from webkitpy.layout_tests.models import test_expectations
from webkitpy.layout_tests.models import test_failures
+from webkitpy.common.iteration_compatibility import itervalues
class JSONLayoutResultsGenerator(json_results_generator.JSONResultsGenerator):
@@ -132,7 +133,7 @@
self.FIXABLE)
num_fixable = 0
- for expectation in self._expectations.itervalues():
+ for expectation in itervalues(self._expectations):
num_fixable += len(expectation.model().get_tests_with_timeline(test_expectations.NOW))
self._insert_item_into_raw_list(results_for_builder, num_fixable, self.ALL_FIXABLE_COUNT)
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/models/test_results.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/layout_tests/models/test_results.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/models/test_results.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -47,7 +47,7 @@
self.failures = failures or []
self.test_run_time = test_run_time or 0 # The time taken to execute the test itself.
self.has_stderr = has_stderr
- self.reftest_type = reftest_type or []
+ self.reftest_type = sorted(reftest_type or [])
self.pid = pid
self.references = references or []
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -29,8 +29,10 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import json
+import sys
import unittest
+from webkitpy.common.unicode_compatibility import StringIO
from webkitpy.common.system import outputcapture, path
from webkitpy.common.system.crashlogs_unittest import make_mock_crash_report_darwin
from webkitpy.common.system.systemhost import SystemHost
@@ -176,7 +178,8 @@
# FIXME: Remove this when we fix test-webkitpy to work
# properly on cygwin (bug 63846).
- self.should_test_processes = not self._platform.is_win()
+ # FIXME: Multiprocessing doesn't do well when nested in Python 3 (https://bugs.webkit.org/show_bug.cgi?id=205280)
+ self.should_test_processes = not self._platform.is_win() and sys.version_info < (3, 0)
def test_basic(self):
options, args = parse_args(tests_included=True)
@@ -195,7 +198,7 @@
_one_line_summary_ = "%d tests ran as expected, %d didn't:\n" % (
details.initial_results.total - details.initial_results.expected_skips - len(details.initial_results.unexpected_results_by_name),
len(details.initial_results.unexpected_results_by_name))
- self.assertTrue(one_line_summary in logging_stream.buflist)
+ self.assertTrue(one_line_summary in logging_stream.getvalue())
# Ensure the results were summarized properly.
self.assertEqual(details.summarized_results['num_regressions'], details.exit_code)
@@ -219,7 +222,7 @@
if self.should_test_processes:
_, regular_output, _ = logging_run(
['--debug-rwt-logging', '--child-processes', '2'], shared_port=False)
- self.assertTrue(any(['Running 2 ' in line for line in regular_output.buflist]))
+ self.assertTrue(any(['Running 2 ' in line for line in regular_output.getvalue().splitlines()]))
def test_child_processes_min(self):
if self.should_test_processes:
@@ -226,7 +229,7 @@
_, regular_output, _ = logging_run(
['--debug-rwt-logging', '--child-processes', '2', '-i', 'passes/passes', 'passes'],
tests_included=True, shared_port=False)
- self.assertTrue(any(['Running 1 ' in line for line in regular_output.buflist]))
+ self.assertTrue(any(['Running 1 ' in line for line in regular_output.getvalue().splitlines()]))
def test_dryrun(self):
tests_run = get_tests_run(['--dry-run'])
@@ -272,7 +275,7 @@
if self.should_test_processes:
_, regular_output, _ = logging_run(['failures/expected/keyboard.html', 'passes/text.html', '--child-processes', '2', '--force'], tests_included=True, shared_port=False)
- self.assertTrue(any(['Interrupted, exiting' in line for line in regular_output.buflist]))
+ self.assertTrue(any(['Interrupted, exiting' in line for line in regular_output.getvalue().splitlines()]))
def test_no_tests_found(self):
details, err, _ = logging_run(['resources'], tests_included=True)
@@ -476,12 +479,57 @@
tests_included=True, host=host)
file_list = host.filesystem.written_files.keys()
self.assertEqual(details.exit_code, 1)
- expected_token = '"unexpected":{"text-image-checksum.html":{"report":"REGRESSION","expected":"PASS","actual":"IMAGE+TEXT","image_diff_percent":1},"missing_text.html":{"report":"MISSING","expected":"PASS","is_missing_text":true,"actual":"MISSING"}'
- json_string = host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json')
- self.assertTrue(json_string.find(expected_token) != -1)
- self.assertTrue(json_string.find('"num_regressions":1') != -1)
- self.assertTrue(json_string.find('"num_flaky":0') != -1)
- self.assertTrue(json_string.find('"num_missing":1') != -1)
+ expected_dictionary = {
+ 'version': 4,
+ 'fixable': 3,
+ 'skipped': 0,
+ 'num_passes': 0,
+ 'num_flaky': 0,
+ 'num_missing': 1,
+ 'num_regressions': 1,
+ 'uses_expectations_file': True,
+ 'interrupted': False,
+ 'layout_tests_dir': '/test.checkout/LayoutTests',
+ 'has_pretty_patch': False,
+ 'pixel_tests_enabled': True,
+ 'other_crashes': {},
+ 'date': '10:10AM on December 13, 2019',
+ 'tests': {
+ 'failures': {
+ 'expected': {
+ 'missing_image.html': {
+ 'expected': 'PASS MISSING',
+ 'actual': 'MISSING',
+ 'is_missing_image': True,
+ },
+ }, 'unexpected': {
+ 'missing_text.html': {
+ 'report': 'MISSING',
+ 'expected': 'PASS',
+ 'actual': 'MISSING',
+ 'is_missing_text': True,
+ }, 'text-image-checksum.html': {
+ 'report': 'REGRESSION',
+ 'expected': 'PASS',
+ 'actual': 'IMAGE+TEXT',
+ 'image_diff_percent': 1,
+ },
+ },
+ },
+ },
+ }
+ actual_dictionary = json.loads(host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json')[len('ADD_RESULTS('):-2])
+ self.assertEqual(
+ sorted(list(expected_dictionary['tests']['failures']['expected'])),
+ sorted(list(actual_dictionary['tests']['failures']['expected'])),
+ )
+ self.assertEqual(
+ sorted(list(expected_dictionary['tests']['failures']['unexpected'])),
+ sorted(list(actual_dictionary['tests']['failures']['unexpected'])),
+ )
+ self.assertEqual(expected_dictionary['num_regressions'], actual_dictionary['num_regressions'])
+ self.assertEqual(expected_dictionary['num_flaky'], actual_dictionary['num_flaky'])
+ self.assertEqual(expected_dictionary['num_missing'], actual_dictionary['num_missing'])
def test_pixel_test_directories(self):
host = MockHost()
@@ -517,7 +565,39 @@
def test_crash_with_stderr(self):
host = MockHost()
_, regular_output, _ = logging_run(['failures/unexpected/crash-with-stderr.html'], tests_included=True, host=host)
- self.assertTrue(host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json').find('{"crash-with-stderr.html":{"report":"REGRESSION","expected":"PASS","actual":"CRASH","has_stderr":true}}') != -1)
+ actual_dictionary = json.loads(host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json')[len('ADD_RESULTS('):-2])
+ expected_dictionary = {
+ 'version': 4,
+ 'fixable': 1,
+ 'skipped': 0,
+ 'num_passes': 0,
+ 'num_flaky': 0,
+ 'num_missing': 0,
+ 'num_regressions': 1,
+ 'uses_expectations_file': True,
+ 'interrupted': False,
+ 'layout_tests_dir': '/test.checkout/LayoutTests',
+ 'has_pretty_patch': False,
+ 'pixel_tests_enabled': True,
+ 'other_crashes': {},
+ 'date': '10:18AM on December 13, 2019',
+ 'tests': {
+ 'failures': {
+ 'unexpected': {
+ 'crash-with-stderr.html': {
+ 'has_stderr': True,
+ 'report': 'REGRESSION',
+ 'expected': 'PASS',
+ 'actual': 'CRASH',
+ },
+ },
+ },
+ },
+ }
+ self.assertEqual(
+ sorted(list(expected_dictionary['tests']['failures']['unexpected'])),
+ sorted(list(actual_dictionary['tests']['failures']['unexpected'])),
+ )
def test_no_image_failure_with_image_diff(self):
host = MockHost()
@@ -740,12 +820,67 @@
def test_reftest_should_not_use_naming_convention_if_not_listed_in_reftestlist(self):
host = MockHost()
_, err, _ = logging_run(['--no-show-results', 'reftests/foo/'], tests_included=True, host=host)
- json_string = host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json')
- self.assertTrue(json_string.find('"unlistedtest.html":{"report":"MISSING","expected":"PASS","is_missing_text":true,"actual":"MISSING","is_missing_image":true}') != -1)
- self.assertTrue(json_string.find('"num_regressions":4') != -1)
- self.assertTrue(json_string.find('"num_flaky":0') != -1)
- self.assertTrue(json_string.find('"num_missing":1') != -1)
+ expected_dictionary = {
+ 'version': 4,
+ 'fixable': 5,
+ 'skipped': 0,
+ 'num_passes': 3,
+ 'num_flaky': 0,
+ 'num_missing': 1,
+ 'num_regressions': 4,
+ 'uses_expectations_file': True,
+ 'interrupted': False,
+ 'layout_tests_dir': '/test.checkout/LayoutTests',
+ 'has_pretty_patch': False,
+ 'pixel_tests_enabled': True,
+ 'other_crashes': {},
+ 'date': '10:27AM on December 13, 2019',
+ 'tests': {
+ 'reftests': {
+ 'foo': {
+ 'multiple-both-failure.html': {
+ 'reftest_type': ['!=', '=='],
+ 'report': 'REGRESSION',
+ 'expected': 'PASS',
+ 'actual': 'IMAGE',
+ }, 'multiple-match-failure.html': {
+ 'reftest_type': ['=='],
+ 'report': 'REGRESSION',
+ 'expected': 'PASS',
+ 'actual': 'IMAGE',
+ 'image_diff_percent': 1,
+ }, 'multiple-mismatch-failure.html': {
+ 'reftest_type': ['!='],
+ 'report': 'REGRESSION',
+ 'expected': 'PASS',
+ 'actual': 'IMAGE',
+ }, 'test.html': {
+ 'reftest_type': ['=='],
+ 'report': 'REGRESSION',
+ 'expected': 'PASS',
+ 'actual': 'IMAGE',
+ 'image_diff_percent': None,
+ }, 'unlistedtest.html': {
+ 'report': 'MISSING',
+ 'expected': 'PASS',
+ 'actual': 'MISSING',
+ 'is_missing_text': True,
+ 'is_missing_image': True,
+ },
+ },
+ },
+ },
+ }
+ actual_dictionary = json.loads(host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json')[len('ADD_RESULTS('):-2])
+ self.assertEqual(
+ expected_dictionary['tests']['reftests']['foo']['unlistedtest.html'],
+ actual_dictionary['tests']['reftests']['foo']['unlistedtest.html'],
+ )
+ self.assertEqual(expected_dictionary['num_regressions'], actual_dictionary['num_regressions'])
+ self.assertEqual(expected_dictionary['num_flaky'], actual_dictionary['num_flaky'])
+ self.assertEqual(expected_dictionary['num_missing'], actual_dictionary['num_missing'])
+
def test_additional_platform_directory(self):
self.assertTrue(passing_run(['--additional-platform-directory', '/tmp/foo']))
self.assertTrue(passing_run(['--additional-platform-directory', '/tmp/../foo']))
@@ -948,12 +1083,18 @@
self.assertTrue("multiple-match-success.html" not in json["tests"]["reftests"]["foo"])
self.assertTrue("multiple-mismatch-success.html" not in json["tests"]["reftests"]["foo"])
self.assertTrue("multiple-both-success.html" not in json["tests"]["reftests"]["foo"])
- self.assertEqual(json["tests"]["reftests"]["foo"]["multiple-match-failure.html"],
- {"expected": "PASS", "actual": "IMAGE", "reftest_type": ["=="], "image_diff_percent": 1, "report": "REGRESSION"})
- self.assertEqual(json["tests"]["reftests"]["foo"]["multiple-mismatch-failure.html"],
- {"expected": "PASS", "actual": "IMAGE", "reftest_type": ["!="], "report": "REGRESSION"})
- self.assertEqual(json["tests"]["reftests"]["foo"]["multiple-both-failure.html"],
- {"expected": "PASS", "actual": "IMAGE", "reftest_type": ["==", "!="], "report": "REGRESSION"})
+ self.assertEqual(
+ json["tests"]["reftests"]["foo"]["multiple-match-failure.html"],
+ {"expected": "PASS", "actual": "IMAGE", "reftest_type": ["=="], "image_diff_percent": 1, "report": "REGRESSION"},
+ )
+ self.assertEqual(
+ json["tests"]["reftests"]["foo"]["multiple-mismatch-failure.html"],
+ {"expected": "PASS", "actual": "IMAGE", "reftest_type": ["!="], "report": "REGRESSION"},
+ )
+ self.assertEqual(
+ json["tests"]["reftests"]["foo"]["multiple-both-failure.html"],
+ {"expected": "PASS", "actual": "IMAGE", "reftest_type": sorted(["==", "!="]), "report": "REGRESSION"},
+ )
class RebaselineTest(unittest.TestCase, StreamTestingMixin):
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/views/metered_stream.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/layout_tests/views/metered_stream.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/views/metered_stream.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -109,6 +109,7 @@
try:
self._stream.write(timestamp_string + txt)
+ self._stream.flush()
except UnicodeEncodeError:
output = ''
for c in timestamp_string + txt:
@@ -117,6 +118,7 @@
except UnicodeEncodeError:
output += '?'
self._stream.write(output)
+ self._stream.flush()
def writeln(self, txt, now=None, pid=None):
self.write(self._ensure_newline(txt), now, pid)
@@ -125,6 +127,7 @@
num_chars = len(self._last_partial_line)
self._stream.write(self._erasure(self._last_partial_line))
self._last_partial_line = ''
+ self._stream.flush()
def flush(self):
if self._last_partial_line:
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/views/printing.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/layout_tests/views/printing.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/views/printing.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -239,7 +239,7 @@
self._print_debug("Time to process slowest subdirectories:")
min_seconds_to_print = 10
for timing in timings:
- if timing[0] > min_seconds_to_print:
+ if timing[1] > min_seconds_to_print:
self._print_debug(" %s took %s seconds to run %s tests." % timing)
self._print_debug("")
@@ -254,10 +254,10 @@
percentile99 = timings[int(.99 * num_tests)]
if num_tests % 2 == 1:
- median = timings[((num_tests - 1) / 2) - 1]
+ median = timings[(num_tests - 1) // 2 - 1]
else:
- lower = timings[num_tests / 2 - 1]
- upper = timings[num_tests / 2]
+ lower = timings[num_tests // 2 - 1]
+ upper = timings[num_tests // 2]
median = (float(lower + upper)) / 2
mean = sum(timings) / num_tests
Modified: trunk/Tools/Scripts/webkitpy/port/darwin.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/port/darwin.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/port/darwin.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -98,7 +98,7 @@
return self.host.filesystem.join(log_directory, 'CrashReporter')
def _merge_crash_logs(self, logs, new_logs, crashed_processes):
- for test, crash_log in new_logs.iteritems():
+ for test, crash_log in new_logs.items():
try:
if test.split('-')[0] == 'Sandbox':
process_name = test.split('-')[1]
Modified: trunk/Tools/Scripts/webkitpy/port/device.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/port/device.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/port/device.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -116,3 +116,6 @@
def __repr__(self):
return u'{}'.format(self.platform_device)
+
+ def __hash__(self):
+ return hash(self.udid)
Modified: trunk/Tools/Scripts/webkitpy/port/device_port.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/port/device_port.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/port/device_port.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -95,7 +95,7 @@
_log.debug('Skipping installation')
return
- for i in xrange(self.child_processes()):
+ for i in range(self.child_processes()):
device = self.target_host(i)
_log.debug(u'Installing to {}'.format(device))
# Without passing DYLD_LIBRARY_PATH, libWebCoreTestSupport cannot be loaded and DRT/WKTR will crash pre-launch,
@@ -186,7 +186,7 @@
self._install()
- for i in xrange(self.child_processes()):
+ for i in range(self.child_processes()):
host = self.target_host(i)
host.prepare_for_testing(
self.ports_to_forward(),
@@ -201,7 +201,7 @@
# Best effort to let every device teardown before throwing any exceptions here.
# Failure to teardown devices can leave things in a bad state.
exception_list = []
- for i in xrange(self.child_processes()):
+ for i in range(self.child_processes()):
device = self.target_host(i)
if not device:
continue
Modified: trunk/Tools/Scripts/webkitpy/port/driver.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/port/driver.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/port/driver.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -39,6 +39,7 @@
from os.path import normpath
from webkitpy.common.system import path
from webkitpy.common.system.profiler import ProfilerFactory
+from webkitpy.common.unicode_compatibility import encode_if_necessary, decode_for
_log = logging.getLogger(__name__)
@@ -86,11 +87,11 @@
test_time=0, measurements=None, timeout=False, error='', crashed_process_name='??',
crashed_pid=None, crash_log=None, pid=None):
# FIXME: Args could be renamed to better clarify what they do.
- self.text = text
+ self.text = decode_for(text, str) if text else None
self.image = image # May be empty-string if the test crashes.
self.image_hash = image_hash
self.image_diff = None # image_diff gets filled in after construction.
- self.audio = audio # Binary format is port-dependent.
+ self.audio = encode_if_necessary(audio) if audio else None # Binary format is port-dependent.
self.crash = crash
self.crashed_process_name = crashed_process_name
self.crashed_pid = crashed_pid
@@ -161,7 +162,7 @@
# stderr output, as well as if we've seen #EOF on this driver instance.
# FIXME: We should probably remove _read_first_block and _read_optional_image_block and
# instead scope these locally in run_test.
- self.error_from_test = str()
+ self.error_from_test = ''
self.err_seen_eof = False
self._server_name = self._port.driver_name()
@@ -196,7 +197,7 @@
test_begin_time = time.time()
self._driver_timed_out = False
self._crash_report_from_driver = None
- self.error_from_test = str()
+ self.error_from_test = ''
self.err_seen_eof = False
command = self._command_from_driver_input(driver_input)
@@ -214,6 +215,7 @@
self._server_process.write(command)
text, audio = self._read_first_block(deadline, driver_input.test_name) # First block is either text or audio
image, actual_image_hash = self._read_optional_image_block(deadline, driver_input.test_name) # The second (optional) block is image data.
+ text = decode_for(text, str)
crashed = self.has_crashed()
timed_out = self._server_process.timed_out
@@ -227,9 +229,9 @@
# In the timeout case, we kill the hung process as well.
out, err = self._server_process.stop(self._port.driver_stop_timeout() if stop_when_done else 0.0)
if out:
- text += out
+ text += decode_for(out, str)
if err:
- self.error_from_test += err
+ self.error_from_test += decode_for(err, str)
self._server_process = None
crash_log = None
@@ -280,10 +282,10 @@
child_processes = defaultdict(list)
for line in output.splitlines():
- m = re.match('^([^:]+): ([0-9]+)$', line)
+ m = re.match(b'^([^:]+): ([0-9]+)$', line)
if m:
- process_name = m.group(1)
- process_id = m.group(2)
+ process_name = decode_for(m.group(1), str)
+ process_id = decode_for(m.group(2), str)
child_processes[process_name].append(process_id)
return child_processes
@@ -540,10 +542,10 @@
return cmd
def _check_for_driver_timeout(self, out_line):
- if out_line.startswith("#PID UNRESPONSIVE - "):
- match = re.match('#PID UNRESPONSIVE - (\S+)', out_line)
- child_process_name = match.group(1) if match else 'WebProcess'
- match = re.search('pid (\d+)', out_line)
+ if out_line.startswith(b"#PID UNRESPONSIVE - "):
+ match = re.match(b'#PID UNRESPONSIVE - (\S+)', out_line)
+ child_process_name = decode_for(match.group(1), str) if match else 'WebProcess'
+ match = re.search(b'pid (\d+)', out_line)
child_process_pid = int(match.group(1)) if match else None
err_line = 'Wait on notifyDone timed out, process ' + child_process_name + ' pid = ' + str(child_process_pid)
self.error_from_test += err_line
@@ -554,32 +556,32 @@
self._driver_timed_out = True
def _check_for_address_sanitizer_violation(self, error_line):
- if "ERROR: AddressSanitizer" in error_line:
+ if b"ERROR: AddressSanitizer" in error_line:
return True
def _check_for_driver_crash_or_unresponsiveness(self, error_line):
- crashed_check = error_line.rstrip('\r\n')
- if crashed_check == "#CRASHED":
+ crashed_check = error_line.rstrip(b'\r\n')
+ if crashed_check == b"#CRASHED":
self._crashed_process_name = self._server_process.process_name()
self._crashed_pid = self._server_process.system_pid()
return True
- elif error_line.startswith("#CRASHED - "):
- match = re.match('#CRASHED - (\S+)', error_line)
- self._crashed_process_name = match.group(1) if match else 'WebProcess'
- match = re.search('pid (\d+)', error_line)
+ elif error_line.startswith(b"#CRASHED - "):
+ match = re.match(b'#CRASHED - (\S+)', error_line)
+ self._crashed_process_name = decode_for(match.group(1), str) if match else 'WebProcess'
+ match = re.search(b'pid (\d+)', error_line)
self._crashed_pid = int(match.group(1)) if match else None
_log.debug('%s crash, pid = %s' % (self._crashed_process_name, str(self._crashed_pid)))
return True
- elif error_line.startswith("#PROCESS UNRESPONSIVE - "):
- match = re.match('#PROCESS UNRESPONSIVE - (\S+)', error_line)
- child_process_name = match.group(1) if match else 'WebProcess'
- match = re.search('pid (\d+)', error_line)
+ elif error_line.startswith(b"#PROCESS UNRESPONSIVE - "):
+ match = re.match(b'#PROCESS UNRESPONSIVE - (\S+)', error_line)
+ child_process_name = decode_for(match.group(1), str) if match else 'WebProcess'
+ match = re.search(b'pid (\d+)', error_line)
child_process_pid = int(match.group(1)) if match else None
_log.debug('%s is unresponsive, pid = %s' % (child_process_name, str(child_process_pid)))
self._driver_timed_out = True
if child_process_pid:
self._port.sample_process(child_process_name, child_process_pid, self._target_host)
- self.error_from_test += error_line
+ self.error_from_test += decode_for(error_line, str)
self._server_process.write('#SAMPLE FINISHED\n', True) # Must be able to ignore a broken pipe here, target process may already be closed.
return True
return self.has_crashed()
@@ -628,12 +630,12 @@
# returns (image, actual_image_hash)
block = self._read_block(deadline, test_name, wait_for_stderr_eof=True)
if block.content and block.content_type == 'image/png':
- return (block.decoded_content, block.content_hash)
+ return (block.decoded_content if block.encoding == 'base64' else block.content, block.content_hash)
return (None, block.content_hash)
def _read_header(self, block, line, header_text, header_attr, header_filter=None):
if line.startswith(header_text) and getattr(block, header_attr) is None:
- value = line.split()[1]
+ value = decode_for(line.split()[1], str)
if header_filter:
value = header_filter(value)
setattr(block, header_attr, value)
@@ -641,19 +643,23 @@
return False
def _process_stdout_line(self, block, line):
- if (self._read_header(block, line, 'Content-Type: ', 'content_type')
- or self._read_header(block, line, 'Content-Transfer-Encoding: ', 'encoding')
- or self._read_header(block, line, 'Content-Length: ', '_content_length', int)
- or self._read_header(block, line, 'ActualHash: ', 'content_hash')
- or self._read_header(block, line, 'DumpMalloc: ', 'malloc')
- or self._read_header(block, line, 'DumpJSHeap: ', 'js_heap')):
- return
+ for header in [
+ (b'Content-Type: ', 'content_type', None),
+ (b'Content-Transfer-Encoding: ', 'encoding', None),
+ (b'Content-Length: ', '_content_length', int),
+ (b'ActualHash: ', 'content_hash', None),
+ (b'DumpMalloc: ', 'malloc', None),
+ (b'DumpJSHeap: ', 'js_heap', None),
+ ]:
+ if self._read_header(block, line, header[0], header[1], header[2]):
+ return
+
# Note, we're not reading ExpectedHash: here, but we could.
# If the line wasn't a header, we just append it to the content.
- block.content += line
+ block.content = encode_if_necessary(block.content) + line
def _strip_eof(self, line):
- if line and line.endswith("#EOF\n"):
+ if line and line.endswith(b"#EOF\n"):
return line[:-5], True
return line, False
@@ -688,7 +694,7 @@
if out_line:
self._check_for_driver_timeout(out_line)
- if out_line[-1] != "\n":
+ if out_line[-1] != '\n' and out_line[-1] != 10:
_log.error(" %s -> Last character read from DRT stdout line was not a newline! This indicates either a NRWT or DRT bug." % test_name)
content_length_before_header_check = block._content_length
self._process_stdout_line(block, out_line)
@@ -695,7 +701,7 @@
# FIXME: Unlike HTTP, DRT dumps the content right after printing a Content-Length header.
# Don't wait until we're done with headers, just read the binary blob right now.
if content_length_before_header_check != block._content_length:
- block.content = self._server_process.read_stdout(deadline, block._content_length)
+ block.content = encode_if_necessary(self._server_process.read_stdout(deadline, block._content_length))
if err_line:
if self._check_for_driver_crash_or_unresponsiveness(err_line):
@@ -702,20 +708,20 @@
break
elif self._check_for_address_sanitizer_violation(err_line):
asan_violation_detected = True
- self._crash_report_from_driver = ""
+ self._crash_report_from_driver = b''
# ASan report starts with a nondescript line, we only detect the second line.
end_of_previous_error_line = self.error_from_test.rfind('\n', 0, -1)
if end_of_previous_error_line > 0:
self.error_from_test = self.error_from_test[:end_of_previous_error_line]
else:
- self.error_from_test = ""
+ self.error_from_test = ''
# Symbolication can take a very long time, give it 10 extra minutes to finish.
# FIXME: This can likely be removed once <rdar://problem/18701447> is fixed.
deadline += 10 * 60 * 1000
if asan_violation_detected:
- self._crash_report_from_driver += err_line
+ self._crash_report_from_driver += decode_for(err_line, str)
else:
- self.error_from_test += err_line
+ self.error_from_test += decode_for(err_line, str)
if asan_violation_detected and not self._crashed_process_name:
self._crashed_process_name = self._server_process.process_name()
@@ -738,7 +744,7 @@
self.content_hash = None
self._content_length = None
# Content is treated as binary data even though the text output is usually UTF-8.
- self.content = str() # FIXME: Should be bytearray() once we require Python 2.6.
+ self.content = b''
self.decoded_content = None
self.malloc = None
self.js_heap = None
@@ -747,7 +753,10 @@
if self.encoding == 'base64' and self.content is not None:
self.decoded_content = base64.b64decode(self.content)
else:
- self.decoded_content = self.content
+ try:
+ self.decoded_content = decode_for(self.content, str)
+ except UnicodeDecodeError:
+ self.decoded_content = None
class DriverProxy(object):
Modified: trunk/Tools/Scripts/webkitpy/port/driver_unittest.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/port/driver_unittest.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/port/driver_unittest.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -182,7 +182,7 @@
content_block = driver._read_block(0, "")
self.assertEqual(content_block.content_type, 'image/png')
self.assertEqual(content_block.content_hash, 'actual')
- self.assertEqual(content_block.content, '12345678\n')
+ self.assertEqual(content_block.content, b'12345678\n')
self.assertEqual(content_block.decoded_content, '12345678\n')
driver._server_process = None
@@ -201,7 +201,7 @@
self.assertEqual(content_block.content_type, 'image/png')
self.assertEqual(content_block.content_hash, 'actual')
self.assertEqual(content_block.encoding, 'base64')
- self.assertEqual(content_block.content, 'MTIzNDU2NzgK')
+ self.assertEqual(content_block.content, b'MTIzNDU2NzgK')
self.assertEqual(content_block.decoded_content, b'12345678\n')
def test_no_timeout(self):
@@ -247,43 +247,43 @@
driver.stop()
driver._server_process = FakeServerProcess(False)
- assert_crash(driver, '', False, None, None)
+ assert_crash(driver, b'', False, None, None)
driver._crashed_process_name = None
driver._crashed_pid = None
driver._server_process = FakeServerProcess(False)
driver._driver_timed_out = False
- assert_crash(driver, '#CRASHED\n', True, 'FakeServerProcess', 1234)
+ assert_crash(driver, b'#CRASHED\n', True, 'FakeServerProcess', 1234)
driver._crashed_process_name = None
driver._crashed_pid = None
driver._server_process = FakeServerProcess(False)
driver._driver_timed_out = False
- assert_crash(driver, '#CRASHED - WebProcess\n', True, 'WebProcess', None)
+ assert_crash(driver, b'#CRASHED - WebProcess\n', True, 'WebProcess', None)
driver._crashed_process_name = None
driver._crashed_pid = None
driver._server_process = FakeServerProcess(False)
driver._driver_timed_out = False
- assert_crash(driver, '#CRASHED - WebProcess (pid 8675)\n', True, 'WebProcess', 8675)
+ assert_crash(driver, b'#CRASHED - WebProcess (pid 8675)\n', True, 'WebProcess', 8675)
driver._crashed_process_name = None
driver._crashed_pid = None
driver._server_process = FakeServerProcess(False)
driver._driver_timed_out = False
- assert_crash(driver, '#PROCESS UNRESPONSIVE - WebProcess (pid 8675)\n', True, None, None, True)
+ assert_crash(driver, b'#PROCESS UNRESPONSIVE - WebProcess (pid 8675)\n', True, None, None, True)
driver._crashed_process_name = None
driver._crashed_pid = None
driver._server_process = FakeServerProcess(False)
driver._driver_timed_out = False
- assert_crash(driver, '#CRASHED - renderer (pid 8675)\n', True, 'renderer', 8675)
+ assert_crash(driver, b'#CRASHED - renderer (pid 8675)\n', True, 'renderer', 8675)
driver._crashed_process_name = None
driver._crashed_pid = None
driver._server_process = FakeServerProcess(True)
driver._driver_timed_out = False
- assert_crash(driver, '', True, 'FakeServerProcess', 1234)
+ assert_crash(driver, b'', True, 'FakeServerProcess', 1234)
def test_creating_a_port_does_not_write_to_the_filesystem(self):
port = TestWebKitPort()
Modified: trunk/Tools/Scripts/webkitpy/port/image_diff.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/port/image_diff.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/port/image_diff.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -35,6 +35,7 @@
import time
from webkitpy.port import server_process
+from webkitpy.common.unicode_compatibility import decode_for
_log = logging.getLogger(__name__)
@@ -57,9 +58,10 @@
if not self._process:
self._start(tolerance)
# Note that although we are handed 'old', 'new', ImageDiff wants 'new', 'old'.
- self._process.write('Content-Length: %d\n%sContent-Length: %d\n%s' % (
- len(actual_contents), actual_contents,
- len(expected_contents), expected_contents))
+ self._process.write('Content-Length: {}\n'.format(len(actual_contents)))
+ self._process.write(actual_contents)
+ self._process.write('Content-Length: {}\n'.format(len(expected_contents)))
+ self._process.write(expected_contents)
return self._read()
except IOError as exception:
return (None, 0, "Failed to compute an image diff: %s" % str(exception))
@@ -76,7 +78,7 @@
def _read(self):
deadline = time.time() + 2.0
output = None
- output_image = ""
+ output_image = b''
while not self._process.timed_out and not self._process.has_crashed():
output = self._process.read_stdout_line(deadline)
@@ -83,17 +85,17 @@
if self._process.timed_out or self._process.has_crashed() or not output:
break
- if output.startswith('diff'): # This is the last line ImageDiff prints.
+ if output.startswith(b'diff'): # This is the last line ImageDiff prints.
break
- if output.startswith('Content-Length'):
- m = re.match('Content-Length: (\d+)', output)
- content_length = int(m.group(1))
+ if output.startswith(b'Content-Length'):
+ m = re.match(b'Content-Length: (\d+)', output)
+ content_length = int(decode_for(m.group(1), str))
output_image = self._process.read_stdout(deadline, content_length)
output = self._process.read_stdout_line(deadline)
break
- stderr = self._process.pop_all_buffered_stderr()
+ stderr = decode_for(self._process.pop_all_buffered_stderr(), str)
err_str = ''
if stderr:
err_str += "ImageDiff produced stderr output:\n" + stderr
@@ -103,11 +105,11 @@
err_str += "ImageDiff crashed\n"
diff_percent = 0
- if output and output.startswith('diff'):
- m = re.match('diff: (.+)% (passed|failed)', output)
- if m.group(2) == 'passed':
+ if output and output.startswith(b'diff'):
+ m = re.match(b'diff: (.+)% (passed|failed)', output)
+ if m.group(2) == b'passed':
return (None, 0, None)
- diff_percent = float(m.group(1))
+ diff_percent = float(decode_for(m.group(1), str))
return (output_image, diff_percent, err_str or None)
Modified: trunk/Tools/Scripts/webkitpy/port/server_process.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/port/server_process.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/port/server_process.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -35,6 +35,9 @@
import sys
import time
+from webkitpy.common.system.executive import ScriptError
+from webkitpy.common.unicode_compatibility import encode_if_necessary
+
# Note that although win32 python does provide an implementation of
# the win32 select API, it only works on sockets, and not on the named pipes
# used by subprocess, so we have to use the native APIs directly.
@@ -47,9 +50,7 @@
import os
import select
-from webkitpy.common.system.executive import ScriptError
-
_log = logging.getLogger(__name__)
@@ -178,9 +179,9 @@
if not self._proc:
self._start()
try:
- self._proc.stdin.write(bytes)
+ self._proc.stdin.write(encode_if_necessary(bytes))
self._proc.stdin.flush()
- except IOError as e:
+ except (IOError, ValueError) as e:
self.stop(0.0)
# stop() calls _reset(), so we have to set crashed to True after calling stop()
# unless we already know that this is a timeout.
Modified: trunk/Tools/Scripts/webkitpy/port/server_process_mock.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/port/server_process_mock.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/port/server_process_mock.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -26,11 +26,13 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+from webkitpy.common.unicode_compatibility import encode_if_necessary
+
class MockServerProcess(object):
def __init__(self, port_obj=None, name=None, cmd=None, env=None, universal_newlines=False, lines=None, crashed=False, target_host=None):
self.timed_out = False
- self.lines = lines or []
+ self.lines = [encode_if_necessary(line) for line in (lines or [])]
self.crashed = crashed
self.writes = []
self.cmd = cmd
@@ -52,7 +54,7 @@
def read_stdout_line(self, deadline):
if self.has_crashed():
return None
- return self.lines.pop(0) + "\n"
+ return self.lines.pop(0) + b'\n'
def has_available_stdout(self):
if self.has_crashed():
@@ -67,8 +69,8 @@
self.lines.pop(0)
remaining_size = size - len(first_line) - 1
if not remaining_size:
- return first_line + "\n"
- return first_line + "\n" + self.read_stdout(deadline, remaining_size)
+ return first_line + b'\n'
+ return first_line + b'\n' + self.read_stdout(deadline, remaining_size)
result = self.lines[0][:size]
self.lines[0] = self.lines[0][size:]
return result
Modified: trunk/Tools/Scripts/webkitpy/port/simulator_process.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/port/simulator_process.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/port/simulator_process.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -22,6 +22,7 @@
import os
+import sys
import time
from webkitpy.common.timeout_context import Timeout
@@ -67,7 +68,9 @@
def close(self):
result = self._file.close()
- self.socket.close()
+ # Closing the file implicitly closes the socket in Python 3
+ if sys.version_info < (3, 0):
+ self.socket.close()
return result
def __init__(self, port_obj, name, cmd, env=None, universal_newlines=False, treat_no_data_as_crash=False, target_host=None):
@@ -103,7 +106,7 @@
stderr = None
try:
# This order matches the client side connections in Tools/TestRunnerShared/IOSLayoutTestCommunication.cpp setUpIOSLayoutTestCommunication()
- stdin = SimulatorProcess._accept_connection_create_file(self._target_host.listening_socket, 'w')
+ stdin = SimulatorProcess._accept_connection_create_file(self._target_host.listening_socket, 'wb')
stdout = SimulatorProcess._accept_connection_create_file(self._target_host.listening_socket, 'rb')
stderr = SimulatorProcess._accept_connection_create_file(self._target_host.listening_socket, 'rb')
except:
Modified: trunk/Tools/Scripts/webkitpy/port/test.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/port/test.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/port/test.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -32,6 +32,7 @@
from webkitpy.layout_tests.models.test_configuration import TestConfiguration
from webkitpy.common.system.crashlogs import CrashLogs
from webkitpy.common.version_name_map import PUBLIC_TABLE, VersionNameMap
+from webkitpy.common.unicode_compatibility import decode_for, encode_if_necessary
# This sets basic expectations for a test. Each individual expectation
@@ -111,9 +112,9 @@
def unit_test_list():
- silent_audio = "RIFF2\x00\x00\x00WAVEfmt \x10\x00\x00\x00\x01\x00\x01\x00\x22\x56\x00\x00\x44\xAC\x00\x00\x02\x00\x10\x00data\x0E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- silent_audio_with_single_bit_difference = "RIFF2\x00\x00\x00WAVEfmt \x10\x00\x00\x00\x01\x00\x01\x00\x22\x56\x00\x00\x44\xAC\x00\x00\x02\x00\x10\x00data\x0E\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
- audio2 = "RIFF2\x00\x00\x00WAVEfmt \x10\x00\x00\x00\x01\x00\x01\x00\x22\x56\x00\x00\x44\xAC\x00\x00\x02\x00\x10\x00data\x0E\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ silent_audio = b"RIFF2\x00\x00\x00WAVEfmt \x10\x00\x00\x00\x01\x00\x01\x00\x22\x56\x00\x00\x44\xAC\x00\x00\x02\x00\x10\x00data\x0E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ silent_audio_with_single_bit_difference = b"RIFF2\x00\x00\x00WAVEfmt \x10\x00\x00\x00\x01\x00\x01\x00\x22\x56\x00\x00\x44\xAC\x00\x00\x02\x00\x10\x00data\x0E\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ audio2 = b"RIFF2\x00\x00\x00WAVEfmt \x10\x00\x00\x00\x01\x00\x01\x00\x22\x56\x00\x00\x44\xAC\x00\x00\x02\x00\x10\x00data\x0E\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
tests = TestList()
tests.add('failures/expected/crash.html', crash=True)
tests.add('failures/expected/exception.html', exception=True)
@@ -434,15 +435,20 @@
return 'Release'
def diff_image(self, expected_contents, actual_contents, tolerance=None):
+ expected_contents = encode_if_necessary(expected_contents)
+ actual_contents = encode_if_necessary(actual_contents)
diffed = actual_contents != expected_contents
if not actual_contents and not expected_contents:
return (None, 0, None)
if not actual_contents or not expected_contents:
return (True, 0, None)
- if 'ref' in expected_contents:
+ if b'ref' in expected_contents:
assert tolerance == 0
if diffed:
- return ("< %s\n---\n> %s\n" % (expected_contents, actual_contents), 1, None)
+ return ("< {}\n---\n> {}\n".format(
+ decode_for(expected_contents, str),
+ decode_for(actual_contents, str),
+ ), 1, None)
return (None, 0, None)
def layout_tests_dir(self):
@@ -563,7 +569,7 @@
test_args = test_input.args or []
test = self._port._tests[test_name]
if test.keyboard:
- raise KeyboardInterrupt
+ raise KeyboardInterrupt()
if test.exception:
raise ValueError('exception from ' + test_name)
if test.hang:
Modified: trunk/Tools/Scripts/webkitpy/xcode/simulated_device.py (254339 => 254340)
--- trunk/Tools/Scripts/webkitpy/xcode/simulated_device.py 2020-01-10 15:46:26 UTC (rev 254339)
+++ trunk/Tools/Scripts/webkitpy/xcode/simulated_device.py 2020-01-10 16:16:19 UTC (rev 254340)
@@ -563,7 +563,7 @@
_log.debug(u'{} has no service to check if the device is usable'.format(self.device_type.software_variant))
return True
- system_processes = self.executive.run_command([SimulatedDeviceManager.xcrun, 'simctl', 'spawn', self.udid, 'launchctl', 'print', 'system'], decode_output=False)
+ system_processes = self.executive.run_command([SimulatedDeviceManager.xcrun, 'simctl', 'spawn', self.udid, 'launchctl', 'print', 'system'], decode_output=True)
if re.search(r'"{}"'.format(home_screen_service), system_processes) or re.search(r'A\s+{}'.format(home_screen_service), system_processes):
return True
return False
@@ -604,7 +604,7 @@
def install_app(self, app_path, env=None):
# Even after carousel is running, it takes a few seconds for watchOS to allow installs.
- for i in xrange(self.NUM_INSTALL_RETRIES):
+ for i in range(self.NUM_INSTALL_RETRIES):
exit_code = self.executive.run_command(['xcrun', 'simctl', 'install', self.udid, app_path], return_exit_code=True)
if exit_code == 0:
return True