Title: [106416] trunk/Tools
Revision
106416
Author
dpra...@chromium.org
Date
2012-01-31 17:41:35 -0800 (Tue, 31 Jan 2012)

Log Message

nrwt: fix the mock port to work with DriverProxy, reftests
https://bugs.webkit.org/show_bug.cgi?id=77170

Reviewed by Eric Seidel.

The DryrunPort used for benchmarking and testing NRWT has been
broken since we added the DriverProxy code. It isn't really
needed any more, so I've removed it.

The MockDRT port was also broken by DriverProxy, and moreover,
never worked w/ reftests. Since we don't exercise this module in
the unit tests, the code had also bitrotted some. I have cleaned
it up and made it use DriverInput and DriverOutput for
consistency.

* Scripts/webkitpy/layout_tests/port/dryrun.py:
(DryRunPort.__init__):
(DryRunPort):
(DryRunPort.real_name):
(DryRunPort.create_driver):
(DryRunPort.driver_cmd_line):
(DryRunPort._driver_class):
(DryrunDriver):
(DryrunDriver.run_test):
* Scripts/webkitpy/layout_tests/port/mock_drt.py:
(MockDRTPort.create_driver):
(MockChromiumDRT.run_one_test):

Modified Paths

Removed Paths

Diff

Modified: trunk/Tools/ChangeLog (106415 => 106416)


--- trunk/Tools/ChangeLog	2012-02-01 01:21:32 UTC (rev 106415)
+++ trunk/Tools/ChangeLog	2012-02-01 01:41:35 UTC (rev 106416)
@@ -1,3 +1,33 @@
+2012-01-31  Dirk Pranke  <dpra...@chromium.org>
+
+        nrwt: fix the mock port to work with DriverProxy, reftests
+        https://bugs.webkit.org/show_bug.cgi?id=77170
+
+        Reviewed by Eric Seidel.
+
+        The DryrunPort used for benchmarking and testing NRWT has been
+        broken since we added the DriverProxy code. It isn't really
+        needed any more, so I've removed it.
+
+        The MockDRT port was also broken by DriverProxy, and moreover,
+        never worked w/ reftests. Since we don't exercise this module in
+        the unit tests, the code had also bitrotted some. I have cleaned
+        it up and made it use DriverInput and DriverOutput for
+        consistency.
+
+        * Scripts/webkitpy/layout_tests/port/dryrun.py:
+        (DryRunPort.__init__):
+        (DryRunPort):
+        (DryRunPort.real_name):
+        (DryRunPort.create_driver):
+        (DryRunPort.driver_cmd_line):
+        (DryRunPort._driver_class):
+        (DryrunDriver):
+        (DryrunDriver.run_test):
+        * Scripts/webkitpy/layout_tests/port/mock_drt.py:
+        (MockDRTPort.create_driver):
+        (MockChromiumDRT.run_one_test):
+
 2012-01-31  Ojan Vafai  <o...@chromium.org>
 
         run-webkit-tests calls out to webkit-build-directory twice

Deleted: trunk/Tools/Scripts/webkitpy/layout_tests/port/dryrun.py (106415 => 106416)


--- trunk/Tools/Scripts/webkitpy/layout_tests/port/dryrun.py	2012-02-01 01:21:32 UTC (rev 106415)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/port/dryrun.py	2012-02-01 01:41:35 UTC (rev 106416)
@@ -1,136 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2010 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 a test implementation of the Port interface that generates the
-   correct output for every test. It can be used for perf testing, because
-   it is pretty much a lower limit on how fast a port can possibly run.
-
-   This implementation acts as a wrapper around a real port (the real port
-   is held as a delegate object). To specify which port, use the port name
-   'dryrun-XXX' (e.g., 'dryrun-chromium-mac-leopard'). If you use just
-   'dryrun', it uses the default port.
-
-   Note that because this is really acting as a wrapper around the underlying
-   port, you must be able to run the underlying port as well
-   (check_build() and check_sys_deps() must pass and auxiliary binaries
-   like layout_test_helper and httpd must work).
-
-   This implementation also modifies the test expectations so that all
-   tests are either SKIPPED or expected to PASS."""
-
-from __future__ import with_statement
-
-import os
-import sys
-import time
-
-from webkitpy.layout_tests.port import Driver, DriverOutput, factory
-
-
-# Note that we don't inherit from base.Port in order for delegation to
-# work properly: except for the methods defined here, we want to ensure that
-# all of the methods are passed to the __delegate, not to the base class.
-class DryRunPort(object):
-    """DryRun implementation of the Port interface."""
-    port_name = 'dryrun'
-
-    @classmethod
-    def determine_full_port_name(cls, host, options, port_name):
-        """Return a fully-specified port name that can be used to construct objects."""
-        # Subclasses will usually override this.
-        return port_name
-
-    def __init__(self, host, port_name, **kwargs):
-        self.__delegate = factory.PortFactory(host).get(port_name.replace('dryrun-', ''), **kwargs)
-
-    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 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 driver_class(self):
-        return DryrunDriver
-
-
-class DryrunDriver(Driver):
-    """Dryrun implementation of the DumpRenderTree / Driver interface."""
-
-    def cmd_line(self):
-        return ['None']
-
-    def run_test(self, driver_input):
-        start_time = time.time()
-        fs = self._port._filesystem
-        if (self._port.is_reftest(driver_input.test_name) or driver_input.test_name.endswith('-expected.html')):
-            text = 'test-text'
-            image = 'test-image'
-            checksum = 'test-checksum'
-            audio = None
-        elif driver_input.test_name.endswith('-expected-mismatch.html'):
-            text = 'test-text-mismatch'
-            image = 'test-image-mismatch'
-            checksum = 'test-checksum-mismatch'
-            audio = None
-        else:
-            text = self._port.expected_text(driver_input.test_name)
-            image = self._port.expected_image(driver_input.test_name)
-            checksum = self._port.expected_checksum(driver_input.test_name)
-            audio = self._port.expected_audio(driver_input.test_name)
-        return DriverOutput(text, image, checksum, audio, crash=False, test_time=time.time() - start_time, timeout=False, error='')
-
-    def stop(self):
-        pass

Modified: trunk/Tools/Scripts/webkitpy/layout_tests/port/factory.py (106415 => 106416)


--- trunk/Tools/Scripts/webkitpy/layout_tests/port/factory.py	2012-02-01 01:21:32 UTC (rev 106415)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/port/factory.py	2012-02-01 01:41:35 UTC (rev 106416)
@@ -48,7 +48,6 @@
         'chromium_linux.ChromiumLinuxPort',
         'chromium_mac.ChromiumMacPort',
         'chromium_win.ChromiumWinPort',
-        'dryrun.DryRunPort',
         'efl.EflPort',
         'google_chrome.GoogleChromeLinux32Port',
         'google_chrome.GoogleChromeLinux64Port',

Modified: trunk/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py (106415 => 106416)


--- trunk/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py	2012-02-01 01:21:32 UTC (rev 106415)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py	2012-02-01 01:41:35 UTC (rev 106416)
@@ -35,7 +35,6 @@
 from webkitpy.layout_tests.port import chromium_linux
 from webkitpy.layout_tests.port import chromium_mac
 from webkitpy.layout_tests.port import chromium_win
-from webkitpy.layout_tests.port import dryrun
 from webkitpy.layout_tests.port import factory
 from webkitpy.layout_tests.port import google_chrome
 from webkitpy.layout_tests.port import gtk

Modified: trunk/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py (106415 => 106416)


--- trunk/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py	2012-02-01 01:21:32 UTC (rev 106415)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py	2012-02-01 01:41:35 UTC (rev 106416)
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-# Copyright (C) 2011 Google Inc. All rights reserved.
+# Copyright (c) 2012 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
@@ -39,9 +39,17 @@
 
 import base64
 import logging
+import os
 import sys
 
+# Since we execute this script directly as part of the unit tests, we need to ensure
+# that Tools/Scripts is in sys.path for the next imports to work correctly.
+script_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
+if script_dir not in sys.path:
+    sys.path.append(script_dir)
+
 from webkitpy.common.system.systemhost import SystemHost
+from webkitpy.layout_tests.port.driver import DriverInput, DriverOutput, DriverProxy
 from webkitpy.layout_tests.port.factory import PortFactory
 from webkitpy.tool.mocktool import MockOptions
 
@@ -49,19 +57,15 @@
 
 
 class MockDRTPort(object):
-    """MockPort implementation of the Port interface."""
     port_name = 'mock'
 
     @classmethod
     def determine_full_port_name(cls, host, options, port_name):
-        """Return a fully-specified port name that can be used to construct objects."""
-        # Subclasses will usually override this.
         return port_name
 
     def __init__(self, host, port_name, **kwargs):
         self.__delegate = PortFactory(host).get(port_name.replace('mock-', ''), **kwargs)
         self.__real_name = port_name
-        self._host = host
 
     def real_name(self):
         return self.__real_name
@@ -75,32 +79,32 @@
     def check_sys_deps(self, needs_http):
         return True
 
-    def driver_cmd_line(self):
-        driver = self.create_driver(0)
-        return driver.cmd_line()
+    def create_driver(self, worker_number, no_timeout=False):
+        # The magic of the MockDRTPort is that we create a driver that has a
+        # cmd_line() method monkey-patched to invoke this script instead of DRT.
+        return DriverProxy(self, worker_number, self._mocked_driver_maker, pixel_tests=self.get_option('pixel_tests'), no_timeout=no_timeout)
 
-    def _path_to_driver(self):
-        return self._host.filesystem.abspath(__file__)
+    @staticmethod
+    def _mocked_driver_maker(port, worker_number, pixel_tests, no_timeout=False):
+        path_to_this_file = port.host.filesystem.abspath(__file__.replace('.pyc', '.py'))
+        driver = port.__delegate._driver_class()(port, worker_number, pixel_tests, no_timeout)
+        driver.cmd_line = port._overriding_cmd_line(driver.cmd_line,
+                                                    port.__delegate._path_to_driver(),
+                                                    sys.executable,
+                                                    path_to_this_file,
+                                                    port.__delegate.name())
+        return driver
 
-    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.
+    @staticmethod
+    def _overriding_cmd_line(original_cmd_line, driver_path, python_exe, this_file, port_name):
+        def new_cmd_line():
+            cmd_line = original_cmd_line()
+            index = cmd_line.index(driver_path)
+            cmd_line[index:index + 1] = [python_exe, this_file, '--platform', port_name]
+            return cmd_line
 
-        def overriding_cmd_line():
-            cmd = self.__original_driver_cmd_line()
-            index = cmd.index(self.__delegate._path_to_driver())
-            # FIXME: Why does this need to use sys.executable (instead of something mockable)?
-            cmd[index:index + 1] = [sys.executable, self._path_to_driver(), '--platform', self.name()]
-            return cmd
+        return new_cmd_line
 
-        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
 
@@ -164,26 +168,7 @@
     return (options, [])
 
 
-# FIXME: Should probably change this to use DriverInput after
-# https://bugs.webkit.org/show_bug.cgi?id=53004 lands (it's landed as of 2/3/11).
-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):
-    @classmethod
-    def determine_full_port_name(cls, host, options, port_name):
-        """Return a fully-specified port name that can be used to construct objects."""
-        # Subclasses will usually override this.
-        return cls.port_name
-
     def __init__(self, options, args, host, stdin, stdout, stderr):
         self._options = options
         self._args = args
@@ -202,91 +187,105 @@
         while True:
             line = self._stdin.readline()
             if not line:
-                break
-            self.run_one_test(self.parse_input(line))
-        return 0
+                return 0
+            self.run_one_test(self.input_from_line(line))
 
-    def parse_input(self, line):
-        return _DRTInput(line)
+    def input_from_line(self, line):
+        vals = line.strip().split("'")
+        if len(vals) == 1:
+            uri = vals[0]
+            checksum = None
+        else:
+            uri = vals[0]
+            checksum = vals[1]
+        if uri.startswith('http://') or uri.startswith('https://'):
+            test_name = self._driver.uri_to_test(uri)
+        else:
+            test_name = self._port.relative_test_filename(uri)
 
-    def run_one_test(self, test_input):
+        is_reftest = (self._port.is_reftest(test_name) or
+                      test_name.endswith('-expected.html') or
+                      test_name.endswith('-mismatch.html'))
+        return DriverInput(test_name, 0, checksum, is_reftest)
+
+    def output_for_test(self, test_input):
         port = self._port
-        if test_input.uri.startswith('http://') or test_input.uri.startswith('https://'):
-            test_name = self._driver.uri_to_test(test_input.uri)
-        else:
-            test_name = port.relative_test_filename(test_input.uri)
+        actual_text = port.expected_text(test_input.test_name)
+        actual_audio = port.expected_audio(test_input.test_name)
+        actual_image = None
+        actual_checksum = None
+        if test_input.is_reftest:
+            # Make up some output for reftests.
+            actual_text = 'reference text\n'
+            actual_checksum = 'None'
+            actual_image = 'blank'
+            if test_name.endswith('-mismatch.html'):
+                actual_checksum = 'True'
+                actual_image = 'not blank'
+        elif self._options.pixel_tests and test_input.image_hash:
+            actual_checksum = port.expected_checksum(test_input.test_name)
+            actual_image = port.expected_image(test_input.test_name)
 
-        actual_text = port.expected_text(test_name)
-        actual_audio = port.expected_audio(test_name)
-        if self._options.pixel_tests and test_input.checksum:
-            actual_checksum = port.expected_checksum(test_name)
-            actual_image = port.expected_image(test_name)
+        return DriverOutput(actual_text, actual_image, actual_checksum, actual_audio)
 
-        if actual_audio:
+    def run_one_test(self, test_input):
+        output = self.output_for_test(test_input)
+
+        if output.audio:
             self._stdout.write('Content-Type: audio/wav\n')
             self._stdout.write('Content-Transfer-Encoding: base64\n')
-            output = base64.b64encode(actual_audio)
-            self._stdout.write(output)
+            self._stdout.write(base64.b64encode(output.audio))
         else:
             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(output.text)
 
         self._stdout.write('#EOF\n')
 
-        if self._options.pixel_tests and test_input.checksum:
+        if self._options.pixel_tests and (test_input.image_hash or is_reftest):
             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('ActualHash: %s\n' % output.image_hash)
+            self._stdout.write('ExpectedHash: %s\n' % test_input.image_hash)
+            if output.image_hash != test_input.image_hash:
                 self._stdout.write('Content-Type: image/png\n')
-                self._stdout.write('Content-Length: %s\n' % len(actual_image))
-                self._stdout.write(actual_image)
+                self._stdout.write('Content-Length: %s\n' % len(output.image))
+                self._stdout.write(output.image)
         self._stdout.write('#EOF\n')
         self._stdout.flush()
+        self._stderr.write('#EOF\n')
         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):
+class MockChromiumDRT(MockDRT):
+    def input_from_line(self, line):
         vals = line.strip().split()
         if len(vals) == 3:
-            self.uri, self.timeout, self.checksum = vals
+            uri, timeout, checksum = vals
         else:
-            self.uri = vals[0]
-            self.timeout = vals[1]
-            self.checksum = None
+            uri, timeout = vals
+            checksum = None
 
+        test_name = self._driver.uri_to_test(uri)
+        is_reftest = (self._port.is_reftest(test_name) or
+                      test_name.endswith('-expected.html') or
+                      test_name.endswith('-mismatch.html'))
 
-class MockChromiumDRT(MockDRT):
-    def parse_input(self, line):
-        return _ChromiumDRTInput(line)
+        return DriverInput(test_name, timeout, checksum, is_reftest)
 
     def run_one_test(self, test_input):
-        port = self._port
-        test_name = self._driver.uri_to_test(test_input.uri)
+        output = self.output_for_test(test_input)
 
-        actual_text = port.expected_text(test_name)
-        actual_image = ''
-        actual_checksum = ''
-        if self._options.pixel_tests and test_input.checksum:
-            actual_checksum = port.expected_checksum(test_name)
-            if actual_checksum != test_input.checksum:
-                actual_image = port.expected_image(test_name)
-
-        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._stdout.write("#URL:%s\n" % self._driver.test_to_uri(test_input.test_name))
+        if self._options.pixel_tests and (test_input.image_hash or test_input.is_reftest):
+            self._stdout.write("#MD5:%s\n" % output.image_hash)
             self._host.filesystem.write_binary_file(self._options.pixel_path,
-                                               actual_image)
-        self._stdout.write(actual_text)
+                                                    output.image)
+        self._stdout.write(output.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'):
+        if not output.text.endswith('\n'):
             self._stdout.write('\n')
         self._stdout.write('#EOF\n')
         self._stdout.flush()

Modified: trunk/Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py (106415 => 106416)


--- trunk/Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py	2012-02-01 01:21:32 UTC (rev 106415)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py	2012-02-01 01:41:35 UTC (rev 106416)
@@ -163,7 +163,7 @@
         # We use the StringIO.buflist here instead of getvalue() because
         # the StringIO might be a mix of unicode/ascii and 8-bit strings.
         self.assertEqual(stdout.buflist, drt_output)
-        self.assertEqual(stderr.getvalue(), '')
+        self.assertEqual(stderr.getvalue(), '' if options.chromium else '#EOF\n')
 
     def test_main(self):
         host = MockSystemHost()

Modified: trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py (106415 => 106416)


--- trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py	2012-02-01 01:21:32 UTC (rev 106415)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py	2012-02-01 01:41:35 UTC (rev 106416)
@@ -923,21 +923,5 @@
             "/platform/test-mac-leopard/failures/expected/missing_image", [".txt", ".png"], err)
 
 
-class DryrunTest(unittest.TestCase):
-    # FIXME: it's hard to know which platforms are safe to test; the
-    # chromium platforms require a chromium checkout, and the mac platform
-    # requires fcntl, so it can't be tested on win32, etc. There is
-    # probably a better way of handling this.
-    def disabled_test_darwin(self):
-        if sys.platform != "darwin":
-            return
-
-        self.assertTrue(passing_run(['--platform', 'dryrun', 'fast/html'], tests_included=True))
-        self.assertTrue(passing_run(['--platform', 'dryrun-mac', 'fast/html'], tests_included=True))
-
-    def test_test(self):
-        self.assertTrue(passing_run(['--platform', 'dryrun-test', '--pixel-tests']))
-
-
 if __name__ == '__main__':
     unittest.main()
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to