2011-02-02 Dirk Pranke <dpranke@chromium.org>
authordpranke@chromium.org <dpranke@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 3 Feb 2011 00:33:29 +0000 (00:33 +0000)
committerdpranke@chromium.org <dpranke@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 3 Feb 2011 00:33:29 +0000 (00:33 +0000)
        Reviewed by Tony Chang.

        new-run-webkit-tests: support chromium code paths in mock_drt

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

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

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

Tools/ChangeLog
Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py
Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py

index 84c471a5253bc525f4feda4993016d493cfd5343..4e044487dc127341f38106f5aa2dc4490e827070 100644 (file)
@@ -1,3 +1,14 @@
+2011-02-02  Dirk Pranke  <dpranke@chromium.org>
+
+        Reviewed by Tony Chang.
+
+        new-run-webkit-tests: support chromium code paths in mock_drt
+
+        https://bugs.webkit.org/show_bug.cgi?id=53471
+
+        * Scripts/webkitpy/layout_tests/port/mock_drt.py:
+        * Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py:
+
 2011-02-02  Adam Klein  <adamk@chromium.org>
 
         Reviewed by Tony Chang.
index a261aa2cebd741090bd8a6ce7dd2638e5a6c68e1..370327fb01b583c0dd02587e643d978b184eb01e 100644 (file)
@@ -37,6 +37,8 @@ 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
 
@@ -81,7 +83,6 @@ class MockDRTPort(object):
         # 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())
@@ -113,34 +114,65 @@ class MockDRTPort(object):
         pass
 
 
-def main(argv, stdin, stdout, stderr):
+def main(argv, fs, stdin, stdout, stderr):
     """Run the tests."""
 
     options, args = parse_options(argv)
-    drt = MockDRT(options, args, stdin, stdout, stderr)
+    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 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)
+    # 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, stdin, stdout, stderr):
+    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
@@ -148,57 +180,98 @@ class MockDRT(object):
         port_name = None
         if options.platform:
             port_name = options.platform
-        self._port = factory.get(port_name, options=options)
+        self._port = factory.get(port_name, options=options, filesystem=filesystem)
 
     def run(self):
         while True:
             line = self._stdin.readline()
             if not line:
                 break
-
-            url, expected_checksum = self.parse_input(line)
-            self.run_one_test(url, expected_checksum)
+            self.run_one_test(self.parse_input(line))
         return 0
 
     def parse_input(self, line):
-        line = line.strip()
-        if "'" in line:
-            return line.split("'", 1)
-        return (line, None)
+        return _DRTInput(line)
 
-    def raw_bytes(self, unicode_str):
-        return unicode_str.encode('utf-8')
-
-    def run_one_test(self, url, expected_checksum):
+    def run_one_test(self, test_input):
         port = self._port
-        if url.startswith('http'):
-            test_name = port.uri_to_test_name(url)
-            test_path = port._filesystem.join(port.layout_tests_dir(), test_name)
+        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 = url
+            test_path = test_input.uri
 
-        actual_text_bytes = self.raw_bytes(port.expected_text(test_path))
-        if self._options.pixel_tests and expected_checksum:
-            actual_checksum_bytes = self.raw_bytes(port.expected_checksum(test_path))
-            actual_image_bytes = port.expected_image(test_path)
+        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')
-        self._stdout.write(actual_text_bytes)
+
+        # 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 expected_checksum:
-            expected_checksum_bytes = self.raw_bytes(expected_checksum)
+        if self._options.pixel_tests and test_input.checksum:
             self._stdout.write('\n')
-            self._stdout.write('ActualHash: %s\n' % actual_checksum_bytes)
-            self._stdout.write('ExpectedHash: %s\n' % expected_checksum_bytes)
-            if actual_checksum_bytes != expected_checksum_bytes:
+            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_bytes))
-                self._stdout.write(actual_image_bytes)
+                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__':
-    sys.exit(main(sys.argv[1:], sys.stdin, sys.stdout, sys.stderr))
+    fs = filesystem.FileSystem()
+    sys.exit(main(sys.argv[1:], fs, sys.stdin, sys.stdout, sys.stderr))
index 3aeafafac481e2af28c5f9f5d6a7d0297b9bd712..150631531c5d001f045dfe2d040afc92d8d6e04f 100644 (file)
@@ -36,6 +36,7 @@ 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
+from webkitpy.layout_tests.port import test
 
 
 class MockDRTPortTest(port_testcase.PortTestCase):
@@ -87,15 +88,11 @@ class MockDRTPortTest(port_testcase.PortTestCase):
 
 
 class MockDRTTest(unittest.TestCase):
-    def setUp(self):
-        self._port = factory.get('test')
-        self._layout_tests_dir = self._port.layout_tests_dir()
+    def to_path(self, port, test_name):
+        return port._filesystem.join(port.layout_tests_dir(), test_name)
 
-    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))
+    def input_line(self, port, test_name, checksum=None):
+        url = port.filename_to_uri(self.to_path(port, test_name))
         # FIXME: we shouldn't have to work around platform-specific issues
         # here.
         if url.startswith('file:////'):
@@ -107,54 +104,61 @@ class MockDRTTest(unittest.TestCase):
             return url + "'" + checksum + '\n'
         return url + '\n'
 
-    def make_drt(self, input_string, extra_args=None):
-        args = ['--platform', 'test', '-']
-        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 extra_args(self, pixel_tests):
+        if pixel_tests:
+            return ['--pixel-tests', '-']
+        return ['-']
 
-    def make_input_output(self, test_name, pixel_tests, expected_checksum,
-                          drt_output, drt_input=None):
-        path = self.to_path(test_name)
+    def make_drt(self, options, args, filesystem, stdin, stdout, stderr):
+        return mock_drt.MockDRT(options, args, filesystem, stdin, stdout, stderr)
+
+    def make_input_output(self, port, test_name, pixel_tests,
+                          expected_checksum, drt_output, drt_input=None):
+        path = self.to_path(port, test_name)
         if pixel_tests:
             if not expected_checksum:
-                expected_checksum = self._port.expected_checksum(path)
+                expected_checksum = port.expected_checksum(path)
         if not drt_input:
-            drt_input = self.input_line(test_name, expected_checksum)
-        text_output = self._port.expected_text(path)
+            drt_input = self.input_line(port, test_name, expected_checksum)
+        text_output = port.expected_text(path)
 
         if not drt_output:
-            if pixel_tests:
-                drt_output = [
-                    'Content-Type: text/plain\n',
-                    text_output.encode('utf-8'),
+            drt_output = self.expected_output(port, test_name, pixel_tests,
+                                              text_output, expected_checksum)
+        return (drt_input, drt_output)
+
+    def expected_output(self, port, test_name, pixel_tests, text_output, expected_checksum):
+        if pixel_tests and expected_checksum:
+            return ['Content-Type: text/plain\n',
+                    text_output,
                     '#EOF\n',
                     '\n',
-                    'ActualHash: %s\n' % expected_checksum.encode('utf-8'),
-                    'ExpectedHash: %s\n' % expected_checksum.encode('utf-8'),
+                    'ActualHash: %s\n' % expected_checksum,
+                    'ExpectedHash: %s\n' % expected_checksum,
                     '#EOF\n']
-            else:
-                drt_output = [
-                    'Content-Type: text/plain\n',
-                    text_output.encode('utf-8'),
+        else:
+            return ['Content-Type: text/plain\n',
+                    text_output,
                     '#EOF\n',
                     '#EOF\n']
 
-        return (drt_input, drt_output)
+    def assertTest(self, test_name, pixel_tests, expected_checksum=None,
+                   drt_output=None, filesystem=None):
+        platform = 'test'
+        filesystem = filesystem or test.unit_test_filesystem()
+        port = factory.get(platform, filesystem=filesystem)
+        drt_input, drt_output = self.make_input_output(port, test_name,
+            pixel_tests, expected_checksum, drt_output)
 
-    def assertTest(self, test_name, pixel_tests, expected_checksum=None, drt_output=None):
-        drt_input, drt_output = self.make_input_output(test_name, pixel_tests,
-            expected_checksum, drt_output)
-        extra_args = []
-        if pixel_tests:
-            extra_args = ['--pixel-tests']
-        drt, stdout, stderr = self.make_drt(drt_input, extra_args)
+        args = ['--platform', 'test'] + self.extra_args(pixel_tests)
+        stdin = newstringio.StringIO(drt_input)
+        stdout = newstringio.StringIO()
+        stderr = newstringio.StringIO()
+        options, args = mock_drt.parse_options(args)
+
+        drt = self.make_drt(options, args, filesystem, stdin, stdout, stderr)
         res = drt.run()
+
         self.assertEqual(res, 0)
 
         # We use the StringIO.buflist here instead of getvalue() because
@@ -163,13 +167,16 @@ class MockDRTTest(unittest.TestCase):
         self.assertEqual(stderr.getvalue(), '')
 
     def test_main(self):
+        filesystem = test.unit_test_filesystem()
         stdin = newstringio.StringIO()
         stdout = newstringio.StringIO()
         stderr = newstringio.StringIO()
-        res = mock_drt.main(['--platform', 'test', '-'], stdin, stdout, stderr)
+        res = mock_drt.main(['--platform', 'test'] + self.extra_args(False),
+                            filesystem, stdin, stdout, stderr)
         self.assertEqual(res, 0)
         self.assertEqual(stdout.getvalue(), '')
         self.assertEqual(stderr.getvalue(), '')
+        self.assertEqual(filesystem.written_files, {})
 
     def test_pixeltest_passes(self):
         # This also tests that we handle HTTP: test URLs properly.
@@ -193,5 +200,62 @@ class MockDRTTest(unittest.TestCase):
         self.assertTest('passes/image.html', False)
 
 
+class MockChromiumDRTTest(MockDRTTest):
+    def extra_args(self, pixel_tests):
+        if pixel_tests:
+            return ['--pixel-tests=/tmp/png_result0.png']
+        return []
+
+    def make_drt(self, options, args, filesystem, stdin, stdout, stderr):
+        options.chromium = True
+
+        # We have to set these by hand because --platform test won't trigger
+        # the Chromium code paths.
+        options.pixel_path = '/tmp/png_result0.png'
+        options.pixel_tests = True
+
+        return mock_drt.MockChromiumDRT(options, args, filesystem, stdin, stdout, stderr)
+
+    def input_line(self, port, test_name, checksum=None):
+        url = port.filename_to_uri(self.to_path(port, test_name))
+        if checksum:
+            return url + ' 6000 ' + checksum + '\n'
+        return url + ' 6000\n'
+
+    def expected_output(self, port, test_name, pixel_tests, text_output, expected_checksum):
+        url = port.filename_to_uri(self.to_path(port, test_name))
+        if pixel_tests and expected_checksum:
+            return ['#URL:%s\n' % url,
+                    '#MD5:%s\n' % expected_checksum,
+                    text_output,
+                    '\n',
+                    '#EOF\n']
+        else:
+            return ['#URL:%s\n' % url,
+                    text_output,
+                    '\n',
+                    '#EOF\n']
+
+    def test_pixeltest__fails(self):
+        filesystem = test.unit_test_filesystem()
+        self.assertTest('failures/expected/checksum.html', pixel_tests=True,
+            expected_checksum='wrong-checksum',
+            drt_output=['#URL:file:///test.checkout/LayoutTests/failures/expected/checksum.html\n',
+                        '#MD5:checksum-checksum\n',
+                        'checksum-txt',
+                        '\n',
+                        '#EOF\n'],
+            filesystem=filesystem)
+        self.assertEquals(filesystem.written_files,
+            {'/tmp/png_result0.png': 'checksum\x8a-png'})
+
+    def test_chromium_parse_options(self):
+        options, args = mock_drt.parse_options(['--platform', 'chromium-mac',
+            '--pixel-tests=/tmp/png_result0.png'])
+        self.assertTrue(options.chromium)
+        self.assertTrue(options.pixel_tests)
+        self.assertEquals(options.pixel_path, '/tmp/png_result0.png')
+
+
 if __name__ == '__main__':
     unittest.main()