OSDN Git Service

Merge WebKit at r84325: Initial merge by git.
[android-x86/external-webkit.git] / Tools / Scripts / webkitpy / layout_tests / port / mock_drt.py
1 #!/usr/bin/env python
2 # Copyright (C) 2011 Google Inc. All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
6 # met:
7 #
8 #     * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 #     * Redistributions in binary form must reproduce the above
11 # copyright notice, this list of conditions and the following disclaimer
12 # in the documentation and/or other materials provided with the
13 # distribution.
14 #     * Neither the Google name nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 """
31 This is an implementation of the Port interface that overrides other
32 ports and changes the Driver binary to "MockDRT".
33 """
34
35 import base64
36 import logging
37 import optparse
38 import os
39 import sys
40
41 from webkitpy.common.system import filesystem
42
43 from webkitpy.layout_tests.port import base
44 from webkitpy.layout_tests.port import factory
45
46 _log = logging.getLogger(__name__)
47
48
49 class MockDRTPort(object):
50     """MockPort implementation of the Port interface."""
51
52     def __init__(self, **kwargs):
53         prefix = 'mock-'
54         if 'port_name' in kwargs:
55             kwargs['port_name'] = kwargs['port_name'][len(prefix):]
56         self.__delegate = factory.get(**kwargs)
57         self.__real_name = prefix + self.__delegate.name()
58
59     def real_name(self):
60         return self.__real_name
61
62     def __getattr__(self, name):
63         return getattr(self.__delegate, name)
64
65     def acquire_http_lock(self):
66         pass
67
68     def release_http_lock(self):
69         pass
70
71     def check_build(self, needs_http):
72         return True
73
74     def check_sys_deps(self, needs_http):
75         return True
76
77     def driver_cmd_line(self):
78         driver = self.create_driver(0)
79         return driver.cmd_line()
80
81     def _path_to_driver(self):
82         return os.path.abspath(__file__)
83
84     def create_driver(self, worker_number):
85         # We need to create a driver object as the delegate would, but
86         # overwrite the path to the driver binary in its command line. We do
87         # this by actually overwriting its cmd_line() method with a proxy
88         # method that splices in the mock_drt path and command line arguments
89         # in place of the actual path to the driver binary.
90
91         def overriding_cmd_line():
92             cmd = self.__original_driver_cmd_line()
93             index = cmd.index(self.__delegate._path_to_driver())
94             cmd[index:index + 1] = [sys.executable, self._path_to_driver(),
95                                     '--platform', self.name()]
96             return cmd
97
98         delegated_driver = self.__delegate.create_driver(worker_number)
99         self.__original_driver_cmd_line = delegated_driver.cmd_line
100         delegated_driver.cmd_line = overriding_cmd_line
101         return delegated_driver
102
103     def start_helper(self):
104         pass
105
106     def start_http_server(self):
107         pass
108
109     def start_websocket_server(self):
110         pass
111
112     def stop_helper(self):
113         pass
114
115     def stop_http_server(self):
116         pass
117
118     def stop_websocket_server(self):
119         pass
120
121
122 def main(argv, fs, stdin, stdout, stderr):
123     """Run the tests."""
124
125     options, args = parse_options(argv)
126     if options.chromium:
127         drt = MockChromiumDRT(options, args, fs, stdin, stdout, stderr)
128     else:
129         drt = MockDRT(options, args, fs, stdin, stdout, stderr)
130     return drt.run()
131
132
133 def parse_options(argv):
134     # FIXME: We have to do custom arg parsing instead of using the optparse
135     # module.  First, Chromium and non-Chromium DRTs have a different argument
136     # syntax.  Chromium uses --pixel-tests=<path>, and non-Chromium uses
137     # --pixel-tests as a boolean flag. Second, we don't want to have to list
138     # every command line flag DRT accepts, but optparse complains about
139     # unrecognized flags. At some point it might be good to share a common
140     # DRT options class between this file and webkit.py and chromium.py
141     # just to get better type checking.
142     platform_index = argv.index('--platform')
143     platform = argv[platform_index + 1]
144
145     pixel_tests = False
146     pixel_path = None
147     chromium = False
148     if platform.startswith('chromium'):
149         chromium = True
150         for arg in argv:
151             if arg.startswith('--pixel-tests'):
152                 pixel_tests = True
153                 pixel_path = arg[len('--pixel-tests='):]
154     else:
155         pixel_tests = '--pixel-tests' in argv
156     options = base.DummyOptions(chromium=chromium,
157                                 platform=platform,
158                                 pixel_tests=pixel_tests,
159                                 pixel_path=pixel_path)
160     return (options, [])
161
162
163 # FIXME: Should probably change this to use DriverInput after
164 # https://bugs.webkit.org/show_bug.cgi?id=53004 lands.
165 class _DRTInput(object):
166     def __init__(self, line):
167         vals = line.strip().split("'")
168         if len(vals) == 1:
169             self.uri = vals[0]
170             self.checksum = None
171         else:
172             self.uri = vals[0]
173             self.checksum = vals[1]
174
175
176 class MockDRT(object):
177     def __init__(self, options, args, filesystem, stdin, stdout, stderr):
178         self._options = options
179         self._args = args
180         self._filesystem = filesystem
181         self._stdout = stdout
182         self._stdin = stdin
183         self._stderr = stderr
184
185         port_name = None
186         if options.platform:
187             port_name = options.platform
188         self._port = factory.get(port_name, options=options, filesystem=filesystem)
189
190     def run(self):
191         while True:
192             line = self._stdin.readline()
193             if not line:
194                 break
195             self.run_one_test(self.parse_input(line))
196         return 0
197
198     def parse_input(self, line):
199         return _DRTInput(line)
200
201     def run_one_test(self, test_input):
202         port = self._port
203         if test_input.uri.startswith('http'):
204             test_name = port.uri_to_test_name(test_input.uri)
205             test_path = self._filesystem.join(port.layout_tests_dir(), test_name)
206         else:
207             test_path = test_input.uri
208
209         actual_text = port.expected_text(test_path)
210         actual_audio = port.expected_audio(test_path)
211         if self._options.pixel_tests and test_input.checksum:
212             actual_checksum = port.expected_checksum(test_path)
213             actual_image = port.expected_image(test_path)
214
215         if actual_audio:
216             self._stdout.write('Content-Type: audio/wav\n')
217             self._stdout.write('Content-Transfer-Encoding: base64\n')
218             output = base64.b64encode(actual_audio)
219             self._stdout.write('Content-Length: %s\n' % len(output))
220             self._stdout.write(output)
221         else:
222             self._stdout.write('Content-Type: text/plain\n')
223             # FIXME: Note that we don't ensure there is a trailing newline!
224             # This mirrors actual (Mac) DRT behavior but is a bug.
225             self._stdout.write(actual_text)
226
227         self._stdout.write('#EOF\n')
228
229         if self._options.pixel_tests and test_input.checksum:
230             self._stdout.write('\n')
231             self._stdout.write('ActualHash: %s\n' % actual_checksum)
232             self._stdout.write('ExpectedHash: %s\n' % test_input.checksum)
233             if actual_checksum != test_input.checksum:
234                 self._stdout.write('Content-Type: image/png\n')
235                 self._stdout.write('Content-Length: %s\n' % len(actual_image))
236                 self._stdout.write(actual_image)
237         self._stdout.write('#EOF\n')
238         self._stdout.flush()
239         self._stderr.flush()
240
241
242 # FIXME: Should probably change this to use DriverInput after
243 # https://bugs.webkit.org/show_bug.cgi?id=53004 lands.
244 class _ChromiumDRTInput(_DRTInput):
245     def __init__(self, line):
246         vals = line.strip().split()
247         if len(vals) == 3:
248             self.uri, self.timeout, self.checksum = vals
249         else:
250             self.uri = vals[0]
251             self.timeout = vals[1]
252             self.checksum = None
253
254
255 class MockChromiumDRT(MockDRT):
256     def parse_input(self, line):
257         return _ChromiumDRTInput(line)
258
259     def run_one_test(self, test_input):
260         port = self._port
261         test_name = self._port.uri_to_test_name(test_input.uri)
262         test_path = self._filesystem.join(port.layout_tests_dir(), test_name)
263
264         actual_text = port.expected_text(test_path)
265         actual_image = ''
266         actual_checksum = ''
267         if self._options.pixel_tests and test_input.checksum:
268             actual_checksum = port.expected_checksum(test_path)
269             if actual_checksum != test_input.checksum:
270                 actual_image = port.expected_image(test_path)
271
272         self._stdout.write("#URL:%s\n" % test_input.uri)
273         if self._options.pixel_tests and test_input.checksum:
274             self._stdout.write("#MD5:%s\n" % actual_checksum)
275             self._filesystem.write_binary_file(self._options.pixel_path,
276                                                actual_image)
277         self._stdout.write(actual_text)
278
279         # FIXME: (See above FIXME as well). Chromium DRT appears to always
280         # ensure the text output has a trailing newline. Mac DRT does not.
281         if not actual_text.endswith('\n'):
282             self._stdout.write('\n')
283         self._stdout.write('#EOF\n')
284         self._stdout.flush()
285
286
287 if __name__ == '__main__':
288     fs = filesystem.FileSystem()
289     sys.exit(main(sys.argv[1:], fs, sys.stdin, sys.stdout, sys.stderr))