OLD | NEW |
---|---|
1 # Copyright (c) 2012 Google Inc. All rights reserved. | 1 # Copyright (c) 2012 Google Inc. All rights reserved. |
2 # | 2 # |
3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
5 # met: | 5 # met: |
6 # | 6 # |
7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
10 # copyright notice, this list of conditions and the following disclaimer | 10 # copyright notice, this list of conditions and the following disclaimer |
(...skipping 23 matching lines...) Expand all Loading... | |
34 return the output a real DRT would return for a given test, assuming that | 34 return the output a real DRT would return for a given test, assuming that |
35 test actually passes (except for reftests, which currently cause the | 35 test actually passes (except for reftests, which currently cause the |
36 MockDRT to crash). | 36 MockDRT to crash). |
37 """ | 37 """ |
38 | 38 |
39 import base64 | 39 import base64 |
40 import logging | 40 import logging |
41 import optparse | 41 import optparse |
42 import os | 42 import os |
43 import sys | 43 import sys |
44 import types | |
44 | 45 |
45 # Since we execute this script directly as part of the unit tests, we need to en sure | 46 # Since we execute this script directly as part of the unit tests, we need to en sure |
46 # that Tools/Scripts is in sys.path for the next imports to work correctly. | 47 # that Tools/Scripts is in sys.path for the next imports to work correctly. |
47 script_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os. path.abspath(__file__))))) | 48 script_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os. path.abspath(__file__))))) |
48 if script_dir not in sys.path: | 49 if script_dir not in sys.path: |
49 sys.path.append(script_dir) | 50 sys.path.append(script_dir) |
50 | 51 |
52 from webkitpy.common import read_checksum_from_png | |
51 from webkitpy.common.system.systemhost import SystemHost | 53 from webkitpy.common.system.systemhost import SystemHost |
52 from webkitpy.layout_tests.port.driver import DriverInput, DriverOutput | 54 from webkitpy.layout_tests.port.driver import DriverInput, DriverOutput |
53 from webkitpy.layout_tests.port.factory import PortFactory | 55 from webkitpy.layout_tests.port.factory import PortFactory |
54 | 56 |
55 _log = logging.getLogger(__name__) | 57 _log = logging.getLogger(__name__) |
56 | 58 |
57 | 59 |
58 class MockDRTPort(object): | 60 class MockDRTPort(object): |
59 port_name = 'mock' | 61 port_name = 'mock' |
60 | 62 |
61 @classmethod | 63 @classmethod |
62 def determine_full_port_name(cls, host, options, port_name): | 64 def determine_full_port_name(cls, host, options, port_name): |
63 return port_name | 65 return port_name |
64 | 66 |
65 def __init__(self, host, port_name, **kwargs): | 67 def __init__(self, host, port_name, **kwargs): |
66 self.__delegate = PortFactory(host).get(port_name.replace('mock-', ''), **kwargs) | 68 self.__delegate = PortFactory(host).get(port_name.replace('mock-', ''), **kwargs) |
69 self.__delegate_driver_class = self.__delegate._driver_class | |
70 self.__delegate._driver_class = types.MethodType(self._driver_class, sel f.__delegate) | |
67 | 71 |
68 def __getattr__(self, name): | 72 def __getattr__(self, name): |
69 return getattr(self.__delegate, name) | 73 return getattr(self.__delegate, name) |
70 | 74 |
71 def check_build(self, needs_http, printer): | 75 def check_build(self, needs_http, printer): |
72 return True | 76 return True |
73 | 77 |
74 def check_sys_deps(self, needs_http): | 78 def check_sys_deps(self, needs_http): |
75 return True | 79 return True |
76 | 80 |
77 def _driver_class(self): | 81 def _driver_class(self, delegate): |
78 return self._mocked_driver_maker | 82 return self._mocked_driver_maker |
79 | 83 |
80 @staticmethod | 84 def _mocked_driver_maker(self, port, worker_number, pixel_tests, no_timeout= False): |
81 def _mocked_driver_maker(port, worker_number, pixel_tests, no_timeout=False) : | 85 path_to_this_file = self.host.filesystem.abspath(__file__.replace('.pyc' , '.py')) |
82 path_to_this_file = port.host.filesystem.abspath(__file__.replace('.pyc' , '.py')) | 86 driver = self.__delegate_driver_class()(self, worker_number, pixel_tests , no_timeout) |
83 driver = port.__delegate._driver_class()(port, worker_number, pixel_test s, no_timeout) | 87 driver.cmd_line = self._overriding_cmd_line(driver.cmd_line, |
84 driver.cmd_line = port._overriding_cmd_line(driver.cmd_line, | 88 self.__delegate._path_to_dri ver(), |
85 port.__delegate._path_to_dri ver(), | |
86 sys.executable, | 89 sys.executable, |
87 path_to_this_file, | 90 path_to_this_file, |
88 port.__delegate.name()) | 91 self.__delegate.name()) |
89 return driver | 92 return driver |
90 | 93 |
91 @staticmethod | 94 @staticmethod |
92 def _overriding_cmd_line(original_cmd_line, driver_path, python_exe, this_fi le, port_name): | 95 def _overriding_cmd_line(original_cmd_line, driver_path, python_exe, this_fi le, port_name): |
93 def new_cmd_line(pixel_tests, per_test_args): | 96 def new_cmd_line(pixel_tests, per_test_args): |
94 cmd_line = original_cmd_line(pixel_tests, per_test_args) | 97 cmd_line = original_cmd_line(pixel_tests, per_test_args) |
95 index = cmd_line.index(driver_path) | 98 index = cmd_line.index(driver_path) |
96 cmd_line[index:index + 1] = [python_exe, this_file, '--platform', po rt_name] | 99 cmd_line[index:index + 1] = [python_exe, this_file, '--platform', po rt_name] |
97 return cmd_line | 100 return cmd_line |
98 | 101 |
(...skipping 16 matching lines...) Expand all Loading... | |
115 | 118 |
116 def stop_http_server(self): | 119 def stop_http_server(self): |
117 pass | 120 pass |
118 | 121 |
119 def stop_websocket_server(self): | 122 def stop_websocket_server(self): |
120 pass | 123 pass |
121 | 124 |
122 def release_http_lock(self): | 125 def release_http_lock(self): |
123 pass | 126 pass |
124 | 127 |
125 def show_results_html_file(self, results_filename): | |
126 pass | |
127 | |
128 def _make_wdiff_available(self): | 128 def _make_wdiff_available(self): |
129 self.__delegate._wdiff_available = True | 129 self.__delegate._wdiff_available = True |
130 | 130 |
131 def setup_environ_for_server(self, server_name): | |
132 env = self.__delegate.setup_environ_for_server() | |
133 # We need to propagate PATH down so the python code can find the checkou t. | |
134 env['PATH'] = os.environ['PATH'] | |
135 return env | |
136 | |
137 def lookup_virtual_test_args(self, test_name): | |
138 suite = self.__delegate.lookup_virtual_suite(test_name) | |
139 return suite.args + ['--virtual-test-suite-name', suite.name, '--virtual -test-suite-base', suite.base] | |
131 | 140 |
132 def main(argv, host, stdin, stdout, stderr): | 141 def main(argv, host, stdin, stdout, stderr): |
133 """Run the tests.""" | 142 """Run the tests.""" |
134 | 143 |
135 options, args = parse_options(argv) | 144 options, args = parse_options(argv) |
136 if options.test_shell: | 145 drt = MockDRT(options, args, host, stdin, stdout, stderr) |
137 drt = MockTestShell(options, args, host, stdin, stdout, stderr) | |
138 else: | |
139 drt = MockDRT(options, args, host, stdin, stdout, stderr) | |
140 return drt.run() | 146 return drt.run() |
141 | 147 |
142 | 148 |
143 def parse_options(argv): | 149 def parse_options(argv): |
144 # FIXME: We have to do custom arg parsing instead of using the optparse | 150 # We do custom arg parsing instead of using the optparse module |
145 # module. First, Chromium and non-Chromium DRTs have a different argument | 151 # because we don't want to have to list every command line flag DRT |
146 # syntax. Chromium uses --pixel-tests=<path>, and non-Chromium uses | 152 # accepts, and optparse complains about unrecognized flags. |
147 # --pixel-tests as a boolean flag. Second, we don't want to have to list | |
148 # every command line flag DRT accepts, but optparse complains about | |
149 # unrecognized flags. At some point it might be good to share a common | |
150 # DRT options class between this file and webkit.py and chromium.py | |
151 # just to get better type checking. | |
152 platform_index = argv.index('--platform') | |
153 platform = argv[platform_index + 1] | |
154 | 153 |
155 pixel_tests = False | 154 def get_arg(arg_name): |
156 pixel_path = None | 155 if arg_name in argv: |
157 test_shell = '--test-shell' in argv | 156 index = argv.index(arg_name) |
158 if test_shell: | 157 return argv[index + 1] |
159 for arg in argv: | 158 return None |
160 if arg.startswith('--pixel-tests'): | 159 |
161 pixel_tests = True | 160 platform = get_arg('--platform') |
162 pixel_path = arg[len('--pixel-tests='):] | 161 actual_directory = get_arg('--actual_directory') |
163 else: | 162 virtual_test_suite_name = get_arg('--virtual-test-suite-name') |
164 pixel_tests = '--pixel-tests' in argv | 163 virtual_test_suite_base = get_arg('--virtual-test-suite-base') |
165 options = optparse.Values({'test_shell': test_shell, 'platform': platform, ' pixel_tests': pixel_tests, 'pixel_path': pixel_path}) | 164 options = optparse.Values({'actual_directory': actual_directory, |
bungeman-chromium
2013/09/20 22:35:17
Arg, my OCD! Any reason these are in a different o
Dirk Pranke
2013/09/20 22:41:00
No good reason. Will fix.
| |
165 'platform': platform, | |
166 'virtual_test_suite_base': virtual_test_suite_bas e, | |
167 'virtual_test_suite_name': virtual_test_suite_nam e}) | |
166 return (options, argv) | 168 return (options, argv) |
167 | 169 |
168 | 170 |
169 class MockDRT(object): | 171 class MockDRT(object): |
170 def __init__(self, options, args, host, stdin, stdout, stderr): | 172 def __init__(self, options, args, host, stdin, stdout, stderr): |
171 self._options = options | 173 self._options = options |
172 self._args = args | 174 self._args = args |
173 self._host = host | 175 self._host = host |
174 self._stdout = stdout | 176 self._stdout = stdout |
175 self._stdin = stdin | 177 self._stdin = stdin |
(...skipping 12 matching lines...) Expand all Loading... | |
188 return 0 | 190 return 0 |
189 driver_input = self.input_from_line(line) | 191 driver_input = self.input_from_line(line) |
190 dirname, basename = self._port.split_test(driver_input.test_name) | 192 dirname, basename = self._port.split_test(driver_input.test_name) |
191 is_reftest = (self._port.reference_files(driver_input.test_name) or | 193 is_reftest = (self._port.reference_files(driver_input.test_name) or |
192 self._port.is_reference_html_file(self._port._filesyst em, dirname, basename)) | 194 self._port.is_reference_html_file(self._port._filesyst em, dirname, basename)) |
193 output = self.output_for_test(driver_input, is_reftest) | 195 output = self.output_for_test(driver_input, is_reftest) |
194 self.write_test_output(driver_input, output, is_reftest) | 196 self.write_test_output(driver_input, output, is_reftest) |
195 | 197 |
196 def input_from_line(self, line): | 198 def input_from_line(self, line): |
197 vals = line.strip().split("'") | 199 vals = line.strip().split("'") |
198 if len(vals) == 1: | 200 uri = vals[0] |
199 uri = vals[0] | 201 checksum = None |
200 checksum = None | 202 should_run_pixel_tests = False |
201 else: | 203 if len(vals) == 2 and vals[1] == '--pixel-test': |
202 uri = vals[0] | 204 should_run_pixel_tests = True |
203 checksum = vals[1] | 205 elif len(vals) == 3 and vals[1] == '--pixel-test': |
206 should_run_pixel_tests = True | |
207 checksum = vals[2] | |
208 elif len(vals) != 1: | |
209 raise NotImplementedError | |
210 | |
204 if uri.startswith('http://') or uri.startswith('https://'): | 211 if uri.startswith('http://') or uri.startswith('https://'): |
205 test_name = self._driver.uri_to_test(uri) | 212 test_name = self._driver.uri_to_test(uri) |
206 else: | 213 else: |
207 test_name = self._port.relative_test_filename(uri) | 214 test_name = self._port.relative_test_filename(uri) |
208 | 215 |
209 return DriverInput(test_name, 0, checksum, self._options.pixel_tests) | 216 return DriverInput(test_name, 0, checksum, should_run_pixel_tests) |
210 | 217 |
211 def output_for_test(self, test_input, is_reftest): | 218 def output_for_test(self, test_input, is_reftest): |
212 port = self._port | 219 port = self._port |
220 if self._options.virtual_test_suite_name: | |
221 test_input.test_name = test_input.test_name.replace(self._options.vi rtual_test_suite_base, self._options.virtual_test_suite_name) | |
213 actual_text = port.expected_text(test_input.test_name) | 222 actual_text = port.expected_text(test_input.test_name) |
214 actual_audio = port.expected_audio(test_input.test_name) | 223 actual_audio = port.expected_audio(test_input.test_name) |
215 actual_image = None | 224 actual_image = None |
216 actual_checksum = None | 225 actual_checksum = None |
217 if is_reftest: | 226 if is_reftest: |
218 # Make up some output for reftests. | 227 # Make up some output for reftests. |
219 actual_text = 'reference text\n' | 228 actual_text = 'reference text\n' |
220 actual_checksum = 'mock-checksum' | 229 actual_checksum = 'mock-checksum' |
221 actual_image = 'blank' | 230 actual_image = 'blank' |
222 if test_input.test_name.endswith('-mismatch.html'): | 231 if test_input.test_name.endswith('-mismatch.html'): |
223 actual_text = 'not reference text\n' | 232 actual_text = 'not reference text\n' |
224 actual_checksum = 'not-mock-checksum' | 233 actual_checksum = 'not-mock-checksum' |
225 actual_image = 'not blank' | 234 actual_image = 'not blank' |
226 elif self._options.pixel_tests and test_input.image_hash: | 235 elif test_input.should_run_pixel_test and test_input.image_hash: |
227 actual_checksum = port.expected_checksum(test_input.test_name) | 236 actual_checksum = port.expected_checksum(test_input.test_name) |
228 actual_image = port.expected_image(test_input.test_name) | 237 actual_image = port.expected_image(test_input.test_name) |
229 | 238 |
239 if self._options.actual_directory: | |
240 actual_path = port._filesystem.join(self._options.actual_directory, test_input.test_name) | |
241 root, _ = port._filesystem.splitext(actual_path) | |
242 text_path = root + '-actual.txt' | |
243 if port._filesystem.exists(text_path): | |
244 actual_text = port._filesystem.read_binary_file(text_path) | |
245 audio_path = root + '-actual.wav' | |
246 if port._filesystem.exists(audio_path): | |
247 actual_audio = port._filesystem.read_binary_file(audio_path) | |
248 image_path = root + '-actual.png' | |
249 if port._filesystem.exists(image_path): | |
250 actual_image = port._filesystem.read_binary_file(image_path) | |
251 with port._filesystem.open_binary_file_for_reading(image_path) a s filehandle: | |
252 actual_checksum = read_checksum_from_png.read_checksum(fileh andle) | |
253 | |
230 return DriverOutput(actual_text, actual_image, actual_checksum, actual_a udio) | 254 return DriverOutput(actual_text, actual_image, actual_checksum, actual_a udio) |
231 | 255 |
232 def write_test_output(self, test_input, output, is_reftest): | 256 def write_test_output(self, test_input, output, is_reftest): |
233 if output.audio: | 257 if output.audio: |
234 self._stdout.write('Content-Type: audio/wav\n') | 258 self._stdout.write('Content-Type: audio/wav\n') |
235 self._stdout.write('Content-Transfer-Encoding: base64\n') | 259 self._stdout.write('Content-Transfer-Encoding: base64\n') |
236 self._stdout.write(base64.b64encode(output.audio)) | 260 self._stdout.write(base64.b64encode(output.audio)) |
261 self._stdout.write('\n') | |
237 else: | 262 else: |
238 self._stdout.write('Content-Type: text/plain\n') | 263 self._stdout.write('Content-Type: text/plain\n') |
239 # FIXME: Note that we don't ensure there is a trailing newline! | 264 # FIXME: Note that we don't ensure there is a trailing newline! |
240 # This mirrors actual (Mac) DRT behavior but is a bug. | 265 # This mirrors actual (Mac) DRT behavior but is a bug. |
241 if output.text: | 266 if output.text: |
242 self._stdout.write(output.text) | 267 self._stdout.write(output.text) |
243 | 268 |
244 self._stdout.write('#EOF\n') | 269 self._stdout.write('#EOF\n') |
245 | 270 |
246 if self._options.pixel_tests and output.image_hash: | 271 if test_input.should_run_pixel_test and output.image_hash: |
bungeman-chromium
2013/09/20 22:35:17
I think I added ' or is_reftest' here in my origin
Dirk Pranke
2013/09/20 22:41:00
Yeah, you needed to add it to work around the call
| |
247 self._stdout.write('\n') | 272 self._stdout.write('\n') |
248 self._stdout.write('ActualHash: %s\n' % output.image_hash) | 273 self._stdout.write('ActualHash: %s\n' % output.image_hash) |
249 self._stdout.write('ExpectedHash: %s\n' % test_input.image_hash) | 274 self._stdout.write('ExpectedHash: %s\n' % test_input.image_hash) |
250 if output.image_hash != test_input.image_hash: | 275 if output.image_hash != test_input.image_hash: |
251 self._stdout.write('Content-Type: image/png\n') | 276 self._stdout.write('Content-Type: image/png\n') |
252 self._stdout.write('Content-Length: %s\n' % len(output.image)) | 277 self._stdout.write('Content-Length: %s\n' % len(output.image)) |
253 self._stdout.write(output.image) | 278 self._stdout.write(output.image) |
254 self._stdout.write('#EOF\n') | 279 self._stdout.write('#EOF\n') |
255 self._stdout.flush() | 280 self._stdout.flush() |
256 self._stderr.write('#EOF\n') | 281 self._stderr.write('#EOF\n') |
257 self._stderr.flush() | 282 self._stderr.flush() |
258 | 283 |
259 | 284 |
260 class MockTestShell(MockDRT): | |
261 def input_from_line(self, line): | |
262 vals = line.strip().split() | |
263 if len(vals) == 3: | |
264 uri, timeout, checksum = vals | |
265 else: | |
266 uri, timeout = vals | |
267 checksum = None | |
268 | |
269 test_name = self._driver.uri_to_test(uri) | |
270 return DriverInput(test_name, timeout, checksum, self._options.pixel_tes ts) | |
271 | |
272 def output_for_test(self, test_input, is_reftest): | |
273 # FIXME: This is a hack to make virtual tests work. Need something more general. | |
274 original_test_name = test_input.test_name | |
275 if '--enable-accelerated-2d-canvas' in self._args and 'canvas' in test_i nput.test_name: | |
276 test_input.test_name = 'platform/chromium/virtual/gpu/' + test_input .test_name | |
277 output = super(MockTestShell, self).output_for_test(test_input, is_refte st) | |
278 test_input.test_name = original_test_name | |
279 return output | |
280 | |
281 def write_test_output(self, test_input, output, is_reftest): | |
282 self._stdout.write("#URL:%s\n" % self._driver.test_to_uri(test_input.tes t_name)) | |
283 if self._options.pixel_tests and output.image_hash: | |
284 self._stdout.write("#MD5:%s\n" % output.image_hash) | |
285 if output.image: | |
286 self._host.filesystem.maybe_make_directory(self._host.filesystem .dirname(self._options.pixel_path)) | |
287 self._host.filesystem.write_binary_file(self._options.pixel_path , output.image) | |
288 if output.text: | |
289 self._stdout.write(output.text) | |
290 | |
291 if output.text and not output.text.endswith('\n'): | |
292 self._stdout.write('\n') | |
293 self._stdout.write('#EOF\n') | |
294 self._stdout.flush() | |
295 | |
296 | |
297 if __name__ == '__main__': | 285 if __name__ == '__main__': |
298 # Note that the Mock in MockDRT refers to the fact that it is emulating a | 286 # Note that the Mock in MockDRT refers to the fact that it is emulating a |
299 # real DRT, and as such, it needs access to a real SystemHost, not a MockSys temHost. | 287 # real DRT, and as such, it needs access to a real SystemHost, not a MockSys temHost. |
300 sys.exit(main(sys.argv[1:], SystemHost(), sys.stdin, sys.stdout, sys.stderr) ) | 288 sys.exit(main(sys.argv[1:], SystemHost(), sys.stdin, sys.stdout, sys.stderr) ) |
OLD | NEW |