2011-01-26 Dirk Pranke <dpranke@chromium.org>
authordpranke@chromium.org <dpranke@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 26 Jan 2011 20:45:39 +0000 (20:45 +0000)
committerdpranke@chromium.org <dpranke@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 26 Jan 2011 20:45:39 +0000 (20:45 +0000)
        Reviewed by Tony Chang.

        new-run-webkit-tests: add a "mock DRT" port implementation
        and a separate class that emulates what we expect the
        DumpRenderTree behavior to be.

        This will eventually replace port/dryrun.py and allow us to get
        better test coverage of the new-run-webkit-tests code as well as
        a reference for what new-run-webkit-tests expects from DRT.

        This is the first attempt at this, and it is pretty bare-boned. It
        really only has been tested on the 'mac' port (and a little on
        the 'chromium-mac' port.

        https://bugs.webkit.org/show_bug.cgi?id=53126

        * Scripts/webkitpy/layout_tests/port/mock_drt.py: Added.
        * Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py: Added.
        * Scripts/webkitpy/layout_tests/port/factory.py:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@76709 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Tools/ChangeLog
Tools/Scripts/webkitpy/layout_tests/port/factory.py
Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py [new file with mode: 0644]
Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py [new file with mode: 0644]

index 58659e69c65d13bdb654a46d16b13739b47a17df..1a0fcdfb8e6203ecd5246b376beadfab072bceba 100644 (file)
@@ -1,3 +1,25 @@
+2011-01-26  Dirk Pranke  <dpranke@chromium.org>
+
+        Reviewed by Tony Chang.
+
+        new-run-webkit-tests: add a "mock DRT" port implementation
+        and a separate class that emulates what we expect the
+        DumpRenderTree behavior to be.
+
+        This will eventually replace port/dryrun.py and allow us to get
+        better test coverage of the new-run-webkit-tests code as well as
+        a reference for what new-run-webkit-tests expects from DRT.
+
+        This is the first attempt at this, and it is pretty bare-boned. It
+        really only has been tested on the 'mac' port (and a little on
+        the 'chromium-mac' port.
+
+        https://bugs.webkit.org/show_bug.cgi?id=53126
+
+        * Scripts/webkitpy/layout_tests/port/mock_drt.py: Added.
+        * Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py: Added.
+        * Scripts/webkitpy/layout_tests/port/factory.py:
+
 2011-01-26  Xianzhu Wang  <wangxianzhu@google.com>
 
         Reviewed by Tony Chang.
 2011-01-26  Xianzhu Wang  <wangxianzhu@google.com>
 
         Reviewed by Tony Chang.
index 675e0c096889808cb850c60ed1116a916cd83b66..051565933887e8a4b877aee9ef68b04f469ca6b7 100644 (file)
@@ -32,7 +32,7 @@
 
 import sys
 
 
 import sys
 
-ALL_PORT_NAMES = ['test', 'dryrun', 'mac', 'win', 'gtk', 'qt', 'chromium-mac',
+ALL_PORT_NAMES = ['test', 'dryrun', 'mock', 'mac', 'win', 'gtk', 'qt', 'chromium-mac',
                   'chromium-linux', 'chromium-win', 'google-chrome-win',
                   'google-chrome-mac', 'google-chrome-linux32', 'google-chrome-linux64']
 
                   'chromium-linux', 'chromium-win', 'google-chrome-win',
                   'google-chrome-mac', 'google-chrome-linux32', 'google-chrome-linux64']
 
@@ -76,6 +76,9 @@ def _get_kwargs(**kwargs):
     elif port_to_use.startswith('dryrun'):
         import dryrun
         maker = dryrun.DryRunPort
     elif port_to_use.startswith('dryrun'):
         import dryrun
         maker = dryrun.DryRunPort
+    elif port_to_use.startswith('mock'):
+        import mock_drt
+        maker = mock_drt.MockDRTPort
     elif port_to_use.startswith('mac'):
         import mac
         maker = mac.MacPort
     elif port_to_use.startswith('mac'):
         import mac
         maker = mac.MacPort
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 (file)
index 0000000..36c4f71
--- /dev/null
@@ -0,0 +1,207 @@
+#!/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.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:
+            if kwargs['port_name'].startswith(prefix):
+                kwargs['port_name'] = kwargs['port_name'][len(prefix):]
+            else:
+                kwargs['port_name'] = None
+        self.__delegate = factory.get(**kwargs)
+
+    def __getattr__(self, name):
+        return getattr(self.__delegate, name)
+
+    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.
+
+        # FIXME: This doesn't yet work for Chromium test_shell ports.
+        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, stdin, stdout, stderr):
+    """Run the tests."""
+
+    options, args = parse_options(argv)
+    drt = MockDRT(options, args, stdin, stdout, stderr)
+    return drt.run()
+
+
+def parse_options(argv):
+    # FIXME: We need to figure out how to handle variants that have
+    # different command-line conventions.
+    option_list = [
+        optparse.make_option('--platform', action='store',
+                             help='platform to emulate'),
+        optparse.make_option('--layout-tests', action='store_true',
+                             default=True, help='run layout tests'),
+        optparse.make_option('--pixel-tests', action='store_true',
+                             default=False,
+                             help='output image for pixel tests'),
+    ]
+    option_parser = optparse.OptionParser(option_list=option_list)
+    return option_parser.parse_args(argv)
+
+
+class MockDRT(object):
+    def __init__(self, options, args, stdin, stdout, stderr):
+        self._options = options
+        self._args = args
+        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)
+        self._exit_status = 0
+
+    def run(self):
+        try:
+            while True:
+                line = self._stdin.readline()
+                if not line:
+                    break
+
+                url, expected_checksum = self.parse_input(line)
+                self.run_one_test(url, expected_checksum)
+        except ValueError, e:
+            self._stderr.write("MockDRT exiting, ValueError raised: '%s'\n"
+                               % str(e))
+            self._exit_status = 1
+        except Exception, e:
+            self._stderr.write("MockDRT exiting, unexpected exception: '%s'\n"
+                               % str(e))
+            self._exit_status = -1
+
+        return self._exit_status
+
+    def parse_input(self, line):
+        line = line.strip()
+        if "'" in line:
+            return line.split("'", 1)
+        return (line, None)
+
+    def run_one_test(self, url, expected_checksum):
+        port = self._port
+        if url.startswith('file:///') or url.startswith('http'):
+            test_name = port.uri_to_test_name(url)
+            test_path = port.path_from_webkit_base('LayoutTests', test_name)
+        else:
+            test_path = url
+
+        actual_text = port.expected_text(test_path)
+        if self._options.pixel_tests and expected_checksum:
+            actual_checksum = port.expected_checksum(test_path)
+            actual_image = port.expected_image(test_path)
+
+        self._stdout.write("Content-Type: text/plain\n")
+        self._stdout.write(actual_text)
+        self._stdout.write("#EOF\n")
+
+        if self._options.pixel_tests and expected_checksum:
+            self._stdout.write("\n")
+            self._stdout.write("ActualHash: %s\n" % actual_checksum)
+            self._stdout.write("ExpectedHash: %s\n" % expected_checksum)
+            if actual_checksum != expected_checksum:
+                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()
+
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv[1:], sys.stdin, sys.stdout, sys.stderr))
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py
new file mode 100644 (file)
index 0000000..fbe911c
--- /dev/null
@@ -0,0 +1,115 @@
+#!/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 name of Google Inc. 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.
+
+"""Unit tests for MockDRT."""
+
+import unittest
+
+from webkitpy.common import newstringio
+
+from webkitpy.layout_tests.port import mock_drt
+from webkitpy.layout_tests.port import factory
+from webkitpy.layout_tests.port import port_testcase
+
+
+class MockDRTPortTest(port_testcase.PortTestCase):
+    def make_port(self):
+        return mock_drt.MockDRTPort()
+
+
+class MockDRTTest(unittest.TestCase):
+    def setUp(self):
+        # We base our tests on the mac-snowleopard port.
+        self._port = factory.get('mac-snowleopard')
+        self._layout_tests_dir = self._port.layout_tests_dir()
+
+    def to_path(self, test_name):
+        return self._port._filesystem.join(self._layout_tests_dir, test_name)
+
+    def input_line(self, test_name, checksum=None):
+        url = self._port.filename_to_uri(self.to_path(test_name))
+        if checksum:
+            return url + "'" + checksum + '\n'
+        return url + '\n'
+
+    def make_drt(self, input_string, args=None, extra_args=None):
+        args = args or ['--platform', 'mac-snowleopard', '-']
+        extra_args = extra_args or []
+        args += extra_args
+        stdin = newstringio.StringIO(input_string)
+        stdout = newstringio.StringIO()
+        stderr = newstringio.StringIO()
+        options, args = mock_drt.parse_options(args)
+        drt = mock_drt.MockDRT(options, args, stdin, stdout, stderr)
+        return (drt, stdout, stderr)
+
+    def make_input_output(self, test_name, pixel_tests):
+        path = self.to_path(test_name)
+        expected_checksum = None
+        if pixel_tests:
+            expected_checksum = self._port.expected_checksum(path)
+        drt_input = self.input_line(test_name, expected_checksum)
+        text_output = self._port.expected_text(path)
+
+        if pixel_tests:
+            drt_output = (
+                "Content-Type: text/plain\n"
+                "%s#EOF\n"
+                "\n"
+                "ActualHash: %s\n"
+                "ExpectedHash: %s\n"
+                "#EOF\n") % (text_output, expected_checksum, expected_checksum)
+        else:
+            drt_output = (
+                "Content-Type: text/plain\n"
+                "%s#EOF\n"
+                "#EOF\n") % text_output
+
+        return (drt_input, drt_output)
+
+    def assertTest(self, test_name, pixel_tests):
+        drt_input, drt_output = self.make_input_output(test_name, pixel_tests)
+        extra_args = []
+        if pixel_tests:
+            extra_args = ['--pixel-tests']
+        drt, stdout, stderr = self.make_drt(drt_input, extra_args)
+        res = drt.run()
+        self.assertEqual(res, 0)
+        self.assertEqual(stdout.getvalue(), drt_output)
+        self.assertEqual(stderr.getvalue(), '')
+
+    def test_pixeltest(self):
+        self.assertTest('fast/html/keygen.html', True)
+
+    def test_textonly(self):
+        self.assertTest('fast/html/article-element.html', False)
+
+
+if __name__ == '__main__':
+    unittest.main()