| OLD | NEW |
| 1 # Copyright (C) 2011 Google Inc. All rights reserved. | 1 # Copyright (C) 2011 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 | 47 |
| 48 def __init__(self, test_name, timeout, image_hash, should_run_pixel_test, ar
gs): | 48 def __init__(self, test_name, timeout, image_hash, should_run_pixel_test, ar
gs): |
| 49 self.test_name = test_name | 49 self.test_name = test_name |
| 50 self.timeout = timeout # in ms | 50 self.timeout = timeout # in ms |
| 51 self.image_hash = image_hash | 51 self.image_hash = image_hash |
| 52 self.should_run_pixel_test = should_run_pixel_test | 52 self.should_run_pixel_test = should_run_pixel_test |
| 53 self.args = args | 53 self.args = args |
| 54 | 54 |
| 55 | 55 |
| 56 class DriverOutput(object): | 56 class DriverOutput(object): |
| 57 |
| 57 """Groups information about a output from driver for easy passing | 58 """Groups information about a output from driver for easy passing |
| 58 and post-processing of data.""" | 59 and post-processing of data.""" |
| 59 | 60 |
| 60 def __init__(self, text, image, image_hash, audio, crash=False, | 61 def __init__(self, text, image, image_hash, audio, crash=False, |
| 61 test_time=0, measurements=None, timeout=False, error='', crashe
d_process_name='??', | 62 test_time=0, measurements=None, timeout=False, error='', crashe
d_process_name='??', |
| 62 crashed_pid=None, crash_log=None, leak=False, leak_log=None, pi
d=None): | 63 crashed_pid=None, crash_log=None, leak=False, leak_log=None, pi
d=None): |
| 63 # FIXME: Args could be renamed to better clarify what they do. | 64 # FIXME: Args could be renamed to better clarify what they do. |
| 64 self.text = text | 65 self.text = text |
| 65 self.image = image # May be empty-string if the test crashes. | 66 self.image = image # May be empty-string if the test crashes. |
| 66 self.image_hash = image_hash | 67 self.image_hash = image_hash |
| (...skipping 13 matching lines...) Expand all Loading... |
| 80 | 81 |
| 81 def has_stderr(self): | 82 def has_stderr(self): |
| 82 return bool(self.error) | 83 return bool(self.error) |
| 83 | 84 |
| 84 | 85 |
| 85 class DeviceFailure(Exception): | 86 class DeviceFailure(Exception): |
| 86 pass | 87 pass |
| 87 | 88 |
| 88 | 89 |
| 89 class Driver(object): | 90 class Driver(object): |
| 91 |
| 90 """object for running test(s) using content_shell or other driver.""" | 92 """object for running test(s) using content_shell or other driver.""" |
| 91 | 93 |
| 92 def __init__(self, port, worker_number, pixel_tests, no_timeout=False): | 94 def __init__(self, port, worker_number, pixel_tests, no_timeout=False): |
| 93 """Initialize a Driver to subsequently run tests. | 95 """Initialize a Driver to subsequently run tests. |
| 94 | 96 |
| 95 Typically this routine will spawn content_shell in a config | 97 Typically this routine will spawn content_shell in a config |
| 96 ready for subsequent input. | 98 ready for subsequent input. |
| 97 | 99 |
| 98 port - reference back to the port object. | 100 port - reference back to the port object. |
| 99 worker_number - identifier for a particular worker/driver instance | 101 worker_number - identifier for a particular worker/driver instance |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 | 405 |
| 404 def _check_for_leak(self, error_line): | 406 def _check_for_leak(self, error_line): |
| 405 if error_line.startswith("#LEAK - "): | 407 if error_line.startswith("#LEAK - "): |
| 406 self._leaked = True | 408 self._leaked = True |
| 407 match = re.match('#LEAK - (\S+) pid (\d+) (.+)\n', error_line) | 409 match = re.match('#LEAK - (\S+) pid (\d+) (.+)\n', error_line) |
| 408 self._leak_log = match.group(3) | 410 self._leak_log = match.group(3) |
| 409 return self._leaked | 411 return self._leaked |
| 410 | 412 |
| 411 def _command_from_driver_input(self, driver_input): | 413 def _command_from_driver_input(self, driver_input): |
| 412 # FIXME: performance tests pass in full URLs instead of test names. | 414 # FIXME: performance tests pass in full URLs instead of test names. |
| 413 if driver_input.test_name.startswith('http://') or driver_input.test_nam
e.startswith('https://') or driver_input.test_name == ('about:blank'): | 415 if driver_input.test_name.startswith( |
| 416 'http://') or driver_input.test_name.startswith('https://') or d
river_input.test_name == ('about:blank'): |
| 414 command = driver_input.test_name | 417 command = driver_input.test_name |
| 415 elif self.is_http_test(driver_input.test_name) or self._should_treat_as_
wpt_test(driver_input.test_name): | 418 elif self.is_http_test(driver_input.test_name) or self._should_treat_as_
wpt_test(driver_input.test_name): |
| 416 command = self.test_to_uri(driver_input.test_name) | 419 command = self.test_to_uri(driver_input.test_name) |
| 417 else: | 420 else: |
| 418 command = self._port.abspath_for_test(driver_input.test_name) | 421 command = self._port.abspath_for_test(driver_input.test_name) |
| 419 if sys.platform == 'cygwin': | 422 if sys.platform == 'cygwin': |
| 420 command = path.cygpath(command) | 423 command = path.cygpath(command) |
| 421 | 424 |
| 422 assert not driver_input.image_hash or driver_input.should_run_pixel_test | 425 assert not driver_input.image_hash or driver_input.should_run_pixel_test |
| 423 | 426 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 452 if line.startswith(header_text) and getattr(block, header_attr) is None: | 455 if line.startswith(header_text) and getattr(block, header_attr) is None: |
| 453 value = line.split()[1] | 456 value = line.split()[1] |
| 454 if header_filter: | 457 if header_filter: |
| 455 value = header_filter(value) | 458 value = header_filter(value) |
| 456 setattr(block, header_attr, value) | 459 setattr(block, header_attr, value) |
| 457 return True | 460 return True |
| 458 return False | 461 return False |
| 459 | 462 |
| 460 def _process_stdout_line(self, block, line): | 463 def _process_stdout_line(self, block, line): |
| 461 if (self._read_header(block, line, 'Content-Type: ', 'content_type') | 464 if (self._read_header(block, line, 'Content-Type: ', 'content_type') |
| 462 or self._read_header(block, line, 'Content-Transfer-Encoding: ', 'en
coding') | 465 or self._read_header(block, line, 'Content-Transfer-Encoding: ',
'encoding') |
| 463 or self._read_header(block, line, 'Content-Length: ', '_content_leng
th', int) | 466 or self._read_header(block, line, 'Content-Length: ', '_content_
length', int) |
| 464 or self._read_header(block, line, 'ActualHash: ', 'content_hash') | 467 or self._read_header(block, line, 'ActualHash: ', 'content_hash'
) |
| 465 or self._read_header(block, line, 'DumpMalloc: ', 'malloc') | 468 or self._read_header(block, line, 'DumpMalloc: ', 'malloc') |
| 466 or self._read_header(block, line, 'DumpJSHeap: ', 'js_heap') | 469 or self._read_header(block, line, 'DumpJSHeap: ', 'js_heap') |
| 467 or self._read_header(block, line, 'StdinPath', 'stdin_path')): | 470 or self._read_header(block, line, 'StdinPath', 'stdin_path')): |
| 468 return | 471 return |
| 469 # Note, we're not reading ExpectedHash: here, but we could. | 472 # Note, we're not reading ExpectedHash: here, but we could. |
| 470 # If the line wasn't a header, we just append it to the content. | 473 # If the line wasn't a header, we just append it to the content. |
| 471 block.content += line | 474 block.content += line |
| 472 | 475 |
| 473 def _strip_eof(self, line): | 476 def _strip_eof(self, line): |
| 474 if line and line.endswith("#EOF\n"): | 477 if line and line.endswith("#EOF\n"): |
| 475 return line[:-5], True | 478 return line[:-5], True |
| 476 if line and line.endswith("#EOF\r\n"): | 479 if line and line.endswith("#EOF\r\n"): |
| 477 _log.error("Got a CRLF-terminated #EOF - this is a driver bug.") | 480 _log.error("Got a CRLF-terminated #EOF - this is a driver bug.") |
| (...skipping 22 matching lines...) Expand all Loading... |
| 500 | 503 |
| 501 if out_line: | 504 if out_line: |
| 502 assert not out_seen_eof | 505 assert not out_seen_eof |
| 503 out_line, out_seen_eof = self._strip_eof(out_line) | 506 out_line, out_seen_eof = self._strip_eof(out_line) |
| 504 if err_line: | 507 if err_line: |
| 505 assert not self.err_seen_eof | 508 assert not self.err_seen_eof |
| 506 err_line, self.err_seen_eof = self._strip_eof(err_line) | 509 err_line, self.err_seen_eof = self._strip_eof(err_line) |
| 507 | 510 |
| 508 if out_line: | 511 if out_line: |
| 509 if out_line[-1] != "\n": | 512 if out_line[-1] != "\n": |
| 510 _log.error("Last character read from DRT stdout line was not
a newline! This indicates either a NRWT or DRT bug.") | 513 _log.error( |
| 514 "Last character read from DRT stdout line was not a newl
ine! This indicates either a NRWT or DRT bug.") |
| 511 content_length_before_header_check = block._content_length | 515 content_length_before_header_check = block._content_length |
| 512 self._process_stdout_line(block, out_line) | 516 self._process_stdout_line(block, out_line) |
| 513 # FIXME: Unlike HTTP, DRT dumps the content right after printing
a Content-Length header. | 517 # FIXME: Unlike HTTP, DRT dumps the content right after printing
a Content-Length header. |
| 514 # Don't wait until we're done with headers, just read the binary
blob right now. | 518 # Don't wait until we're done with headers, just read the binary
blob right now. |
| 515 if content_length_before_header_check != block._content_length: | 519 if content_length_before_header_check != block._content_length: |
| 516 if block._content_length > 0: | 520 if block._content_length > 0: |
| 517 block.content = self._server_process.read_stdout(deadlin
e, block._content_length) | 521 block.content = self._server_process.read_stdout(deadlin
e, block._content_length) |
| 518 else: | 522 else: |
| 519 _log.error("Received content of type %s with Content-Len
gth of 0! This indicates a bug in %s.", | 523 _log.error("Received content of type %s with Content-Len
gth of 0! This indicates a bug in %s.", |
| 520 block.content_type, self._server_process.name
()) | 524 block.content_type, self._server_process.name
()) |
| (...skipping 21 matching lines...) Expand all Loading... |
| 542 self.decoded_content = None | 546 self.decoded_content = None |
| 543 self.malloc = None | 547 self.malloc = None |
| 544 self.js_heap = None | 548 self.js_heap = None |
| 545 self.stdin_path = None | 549 self.stdin_path = None |
| 546 | 550 |
| 547 def decode_content(self): | 551 def decode_content(self): |
| 548 if self.encoding == 'base64' and self.content is not None: | 552 if self.encoding == 'base64' and self.content is not None: |
| 549 self.decoded_content = base64.b64decode(self.content) | 553 self.decoded_content = base64.b64decode(self.content) |
| 550 else: | 554 else: |
| 551 self.decoded_content = self.content | 555 self.decoded_content = self.content |
| OLD | NEW |