diff options
Diffstat (limited to 'Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py')
-rw-r--r-- | Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py b/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py new file mode 100644 index 0000000..1147846 --- /dev/null +++ b/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py @@ -0,0 +1,280 @@ +#!/usr/bin/env python +# Copyright (C) 2011 Google 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: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the Google name nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +# OWNER OR 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. + +""" +This is an implementation of the Port interface that overrides other +ports and changes the Driver binary to "MockDRT". +""" + +import logging +import optparse +import os +import sys + +from webkitpy.common.system import filesystem + +from webkitpy.layout_tests.port import base +from webkitpy.layout_tests.port import factory + +_log = logging.getLogger(__name__) + + +class MockDRTPort(object): + """MockPort implementation of the Port interface.""" + + def __init__(self, **kwargs): + prefix = 'mock-' + if 'port_name' in kwargs: + kwargs['port_name'] = kwargs['port_name'][len(prefix):] + self.__delegate = factory.get(**kwargs) + self.__real_name = prefix + self.__delegate.name() + + def real_name(self): + return self.__real_name + + def __getattr__(self, name): + return getattr(self.__delegate, name) + + def acquire_http_lock(self): + pass + + def release_http_lock(self): + pass + + def check_build(self, needs_http): + return True + + def check_sys_deps(self, needs_http): + return True + + def driver_cmd_line(self): + driver = self.create_driver(0) + return driver.cmd_line() + + def _path_to_driver(self): + return os.path.abspath(__file__) + + def create_driver(self, worker_number): + # We need to create a driver object as the delegate would, but + # overwrite the path to the driver binary in its command line. We do + # this by actually overwriting its cmd_line() method with a proxy + # method that splices in the mock_drt path and command line arguments + # in place of the actual path to the driver binary. + + def overriding_cmd_line(): + cmd = self.__original_driver_cmd_line() + index = cmd.index(self.__delegate._path_to_driver()) + cmd[index:index + 1] = [sys.executable, self._path_to_driver(), + '--platform', self.name()] + return cmd + + delegated_driver = self.__delegate.create_driver(worker_number) + self.__original_driver_cmd_line = delegated_driver.cmd_line + delegated_driver.cmd_line = overriding_cmd_line + return delegated_driver + + def start_helper(self): + pass + + def start_http_server(self): + pass + + def start_websocket_server(self): + pass + + def stop_helper(self): + pass + + def stop_http_server(self): + pass + + def stop_websocket_server(self): + pass + + +def main(argv, fs, stdin, stdout, stderr): + """Run the tests.""" + + options, args = parse_options(argv) + if options.chromium: + drt = MockChromiumDRT(options, args, fs, stdin, stdout, stderr) + else: + drt = MockDRT(options, args, fs, stdin, stdout, stderr) + return drt.run() + + +def parse_options(argv): + # FIXME: We have to do custom arg parsing instead of using the optparse + # module. First, Chromium and non-Chromium DRTs have a different argument + # syntax. Chromium uses --pixel-tests=<path>, and non-Chromium uses + # --pixel-tests as a boolean flag. Second, we don't want to have to list + # every command line flag DRT accepts, but optparse complains about + # unrecognized flags. At some point it might be good to share a common + # DRT options class between this file and webkit.py and chromium.py + # just to get better type checking. + platform_index = argv.index('--platform') + platform = argv[platform_index + 1] + + pixel_tests = False + pixel_path = None + chromium = False + if platform.startswith('chromium'): + chromium = True + for arg in argv: + if arg.startswith('--pixel-tests'): + pixel_tests = True + pixel_path = arg[len('--pixel-tests='):] + else: + pixel_tests = '--pixel-tests' in argv + options = base.DummyOptions(chromium=chromium, + platform=platform, + pixel_tests=pixel_tests, + pixel_path=pixel_path) + return (options, []) + + +# FIXME: Should probably change this to use DriverInput after +# https://bugs.webkit.org/show_bug.cgi?id=53004 lands. +class _DRTInput(object): + def __init__(self, line): + vals = line.strip().split("'") + if len(vals) == 1: + self.uri = vals[0] + self.checksum = None + else: + self.uri = vals[0] + self.checksum = vals[1] + + +class MockDRT(object): + def __init__(self, options, args, filesystem, stdin, stdout, stderr): + self._options = options + self._args = args + self._filesystem = filesystem + self._stdout = stdout + self._stdin = stdin + self._stderr = stderr + + port_name = None + if options.platform: + port_name = options.platform + self._port = factory.get(port_name, options=options, filesystem=filesystem) + + def run(self): + while True: + line = self._stdin.readline() + if not line: + break + self.run_one_test(self.parse_input(line)) + return 0 + + def parse_input(self, line): + return _DRTInput(line) + + def run_one_test(self, test_input): + port = self._port + if test_input.uri.startswith('http'): + test_name = port.uri_to_test_name(test_input.uri) + test_path = self._filesystem.join(port.layout_tests_dir(), test_name) + else: + test_path = test_input.uri + + actual_text = port.expected_text(test_path) + if self._options.pixel_tests and test_input.checksum: + actual_checksum = port.expected_checksum(test_path) + actual_image = port.expected_image(test_path) + + self._stdout.write('Content-Type: text/plain\n') + + # FIXME: Note that we don't ensure there is a trailing newline! + # This mirrors actual (Mac) DRT behavior but is a bug. + self._stdout.write(actual_text) + self._stdout.write('#EOF\n') + + if self._options.pixel_tests and test_input.checksum: + self._stdout.write('\n') + self._stdout.write('ActualHash: %s\n' % actual_checksum) + self._stdout.write('ExpectedHash: %s\n' % test_input.checksum) + if actual_checksum != test_input.checksum: + self._stdout.write('Content-Type: image/png\n') + self._stdout.write('Content-Length: %s\n\n' % len(actual_image)) + self._stdout.write(actual_image) + self._stdout.write('#EOF\n') + self._stdout.flush() + self._stderr.flush() + + +# FIXME: Should probably change this to use DriverInput after +# https://bugs.webkit.org/show_bug.cgi?id=53004 lands. +class _ChromiumDRTInput(_DRTInput): + def __init__(self, line): + vals = line.strip().split() + if len(vals) == 3: + self.uri, self.timeout, self.checksum = vals + else: + self.uri = vals[0] + self.timeout = vals[1] + self.checksum = None + + +class MockChromiumDRT(MockDRT): + def parse_input(self, line): + return _ChromiumDRTInput(line) + + def run_one_test(self, test_input): + port = self._port + test_name = self._port.uri_to_test_name(test_input.uri) + test_path = self._filesystem.join(port.layout_tests_dir(), test_name) + + actual_text = port.expected_text(test_path) + actual_image = '' + actual_checksum = '' + if self._options.pixel_tests and test_input.checksum: + actual_checksum = port.expected_checksum(test_path) + if actual_checksum != test_input.checksum: + actual_image = port.expected_image(test_path) + + self._stdout.write("#URL:%s\n" % test_input.uri) + if self._options.pixel_tests and test_input.checksum: + self._stdout.write("#MD5:%s\n" % actual_checksum) + self._filesystem.write_binary_file(self._options.pixel_path, + actual_image) + self._stdout.write(actual_text) + + # FIXME: (See above FIXME as well). Chromium DRT appears to always + # ensure the text output has a trailing newline. Mac DRT does not. + if not actual_text.endswith('\n'): + self._stdout.write('\n') + self._stdout.write('#EOF\n') + self._stdout.flush() + + +if __name__ == '__main__': + fs = filesystem.FileSystem() + sys.exit(main(sys.argv[1:], fs, sys.stdin, sys.stdout, sys.stderr)) |