Changeset 83475 in webkit
- Timestamp:
- Apr 11, 2011 12:17:57 PM (13 years ago)
- Location:
- trunk/Tools
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Tools/ChangeLog
r83466 r83475 1 2011-04-11 Dirk Pranke <dpranke@chromium.org> 2 3 Reviewed by Tony Chang. 4 5 new-run-webkit-tests: implement support for audio, take two 6 https://bugs.webkit.org/show_bug.cgi?id=58195 7 8 Attempt to re-land the fix for bug 58101 (which was initially 9 landed in r83330, but rolled out). This is the same patch but 10 fixes crashes in Port.diff_image() caused by the change for 11 empty image files being None instead of ''. 12 13 * Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py: 14 * Scripts/webkitpy/layout_tests/layout_package/single_test_runner.py: 15 * Scripts/webkitpy/layout_tests/layout_package/test_expectations.py: 16 * Scripts/webkitpy/layout_tests/layout_package/test_failures.py: 17 * Scripts/webkitpy/layout_tests/layout_package/test_result_writer.py: 18 * Scripts/webkitpy/layout_tests/port/base.py: 19 * Scripts/webkitpy/layout_tests/port/chromium.py: 20 * Scripts/webkitpy/layout_tests/port/dryrun.py: 21 * Scripts/webkitpy/layout_tests/port/mock_drt.py: 22 * Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py: 23 * Scripts/webkitpy/layout_tests/port/test.py: 24 * Scripts/webkitpy/layout_tests/port/webkit.py: 25 1 26 2011-04-11 Mario Sanchez Prada <msanchez@igalia.com> 2 27 -
trunk/Tools/Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py
r83361 r83475 51 51 test_expectations.TEXT: "F", 52 52 test_expectations.MISSING: "O", 53 test_expectations.AUDIO: "A", 53 54 test_expectations.IMAGE_PLUS_TEXT: "Z"} 54 55 -
trunk/Tools/Scripts/webkitpy/layout_tests/layout_package/single_test_runner.py
r83361 r83475 83 83 # 'foo-expected.txt', we should warn users. One test file must be used exclusively 84 84 # in either layout tests or reftests, but not in both. 85 for suffix in ['.txt', '.checksum', '.png']:85 for suffix in ('.txt', '.checksum', '.png', '.wav'): 86 86 expected_filename = self._port.expected_filename(self._filename, suffix) 87 87 if fs.exists(expected_filename): … … 92 92 return base.DriverOutput(self._port.expected_text(self._filename), 93 93 self._port.expected_image(self._filename), 94 self._port.expected_checksum(self._filename)) 94 self._port.expected_checksum(self._filename), 95 self._port.expected_audio(self._filename)) 95 96 96 97 def _should_fetch_expected_checksum(self): … … 143 144 self._save_baseline_data(driver_output.text, ".txt", 144 145 generate_new_baseline=self._options.new_baseline) 146 if driver_output.audio: 147 self._save_baseline_data(driver_output.audio, '.wav', 148 generate_new_baseline=self._options.new_baseline) 145 149 if self._options.pixel_tests and driver_output.image_hash: 146 150 self._save_baseline_data(driver_output.image, ".png", … … 217 221 218 222 failures.extend(self._compare_text(driver_output.text, expected_driver_output.text)) 223 failures.extend(self._compare_audio(driver_output.audio, expected_driver_output.audio)) 219 224 if self._options.pixel_tests: 220 225 failures.extend(self._compare_image(driver_output, expected_driver_output)) … … 223 228 def _compare_text(self, actual_text, expected_text): 224 229 failures = [] 225 if self._port.compare_text(self._get_normalized_output_text(actual_text), 226 # Assuming expected_text is already normalized. 227 expected_text): 228 if expected_text == '': 229 failures.append(test_failures.FailureMissingResult()) 230 else: 231 failures.append(test_failures.FailureTextMismatch()) 230 if (expected_text and actual_text and 231 # Assuming expected_text is already normalized. 232 self._port.compare_text(self._get_normalized_output_text(actual_text), expected_text)): 233 failures.append(test_failures.FailureTextMismatch()) 234 elif actual_text and not expected_text: 235 failures.append(test_failures.FailureMissingResult()) 236 return failures 237 238 def _compare_audio(self, actual_audio, expected_audio): 239 failures = [] 240 if (expected_audio and actual_audio and 241 self._port.compare_audio(actual_audio, expected_audio)): 242 failures.append(test_failures.FailureAudioMismatch()) 243 elif actual_audio and not expected_audio: 244 failures.append(test_failures.FailureMissingAudio()) 232 245 return failures 233 246 -
trunk/Tools/Scripts/webkitpy/layout_tests/layout_package/test_expectations.py
r83361 r83475 42 42 43 43 # Test expectation and modifier constants. 44 (PASS, FAIL, TEXT, IMAGE, IMAGE_PLUS_TEXT, TIMEOUT, CRASH, SKIP, WONTFIX,45 SLOW, REBASELINE, MISSING, FLAKY, NOW, NONE) = range(1 5)44 (PASS, FAIL, TEXT, IMAGE, IMAGE_PLUS_TEXT, AUDIO, TIMEOUT, CRASH, SKIP, WONTFIX, 45 SLOW, REBASELINE, MISSING, FLAKY, NOW, NONE) = range(16) 46 46 47 47 # Test expectation file update action constants … … 121 121 self._expected_failures.get_test_set(REBASELINE, TEXT) | 122 122 self._expected_failures.get_test_set(REBASELINE, 123 IMAGE_PLUS_TEXT)) 123 IMAGE_PLUS_TEXT) | 124 self._expected_failures.get_test_set(REBASELINE, AUDIO)) 124 125 125 126 def get_options(self, test): … … 245 246 Notes: 246 247 -A test cannot be both SLOW and TIMEOUT 247 -A test should only be one of IMAGE, TEXT, IMAGE+TEXT, or FAIL. FAIL is248 a migratory state that currently means either IMAGE, TEXT, or249 IMAGE+TEXT. Once we have finished migrating the expectations, we will250 change FAIL to have the meaning of IMAGE+TEXT and remove the IMAGE+TEXT251 identifier.248 -A test should only be one of IMAGE, TEXT, IMAGE+TEXT, AUDIO, or FAIL. 249 FAIL is a legacy value that currently means either IMAGE, 250 TEXT, or IMAGE+TEXT. Once we have finished migrating the expectations, 251 we should change FAIL to have the meaning of IMAGE+TEXT and remove the 252 IMAGE+TEXT identifier. 252 253 -A test can be included twice, but not via the same path. 253 254 -If a test is included twice, then the more precise path wins. … … 260 261 'image': IMAGE, 261 262 'image+text': IMAGE_PLUS_TEXT, 263 'audio': AUDIO, 262 264 'timeout': TIMEOUT, 263 265 'crash': CRASH, … … 272 274 IMAGE_PLUS_TEXT: ('image and text mismatch', 273 275 'image and text mismatch'), 276 AUDIO: ('audio mismatch', 'audio mismatch'), 274 277 CRASH: ('DumpRenderTree crash', 275 278 'DumpRenderTree crashes'), … … 279 282 280 283 EXPECTATION_ORDER = (PASS, CRASH, TIMEOUT, MISSING, IMAGE_PLUS_TEXT, 281 TEXT, IMAGE, FAIL, SKIP)284 TEXT, IMAGE, AUDIO, FAIL, SKIP) 282 285 283 286 BUILD_TYPES = ('debug', 'release') -
trunk/Tools/Scripts/webkitpy/layout_tests/layout_package/test_failures.py
r83361 r83475 55 55 elif (FailureMissingResult in failure_types or 56 56 FailureMissingImage in failure_types or 57 FailureMissingImageHash in failure_types): 57 FailureMissingImageHash in failure_types or 58 FailureMissingAudio in failure_types): 58 59 return test_expectations.MISSING 59 60 else: … … 63 64 is_reftest_failure = (FailureReftestMismatch in failure_types or 64 65 FailureReftestMismatchDidNotOccur in failure_types) 66 is_audio_failure = (FailureAudioMismatch in failure_types) 65 67 if is_text_failure and is_image_failure: 66 68 return test_expectations.IMAGE_PLUS_TEXT … … 69 71 elif is_image_failure or is_reftest_failure: 70 72 return test_expectations.IMAGE 73 elif is_audio_failure: 74 return test_expectations.AUDIO 71 75 else: 72 76 raise ValueError("unclassifiable set of failures: " … … 332 336 333 337 338 class FailureMissingAudio(ComparisonTestFailure): 339 """Actual result image was missing.""" 340 OUT_FILENAMES = ("-actual.wav",) 341 342 @staticmethod 343 def message(): 344 return "No expected audio found" 345 346 def result_html_output(self, filename): 347 return ("<strong>%s</strong>" % self.message() + 348 self.output_links(filename, self.OUT_FILENAMES)) 349 350 351 class FailureAudioMismatch(ComparisonTestFailure): 352 """Audio files didn't match.""" 353 OUT_FILENAMES = ("-actual.wav", "-expected.wav") 354 355 @staticmethod 356 def message(): 357 return "Audio mismatch" 358 359 334 360 # Convenient collection of all failure classes for anything that might 335 361 # need to enumerate over them all. -
trunk/Tools/Scripts/webkitpy/layout_tests/layout_package/test_result_writer.py
r83361 r83475 64 64 checksums_mismatch_but_images_are_same = True 65 65 imagehash_mismatch_failure = failure 66 elif isinstance(failure, (test_failures.FailureAudioMismatch, 67 test_failures.FailureMissingAudio)): 68 writer.write_audio_files(driver_output.audio, expected_driver_output.audio) 66 69 elif isinstance(failure, test_failures.FailureCrash): 67 70 if failure.reference_filename: … … 188 191 fs.write_binary_file(pretty_patch_filename, pretty_patch) 189 192 193 def write_audio_files(self, actual_audio, expected_audio): 194 self.write_output_files('.wav', actual_audio, expected_audio) 195 190 196 def write_image_files(self, actual_image, expected_image): 191 197 self.write_output_files('.png', actual_image, expected_image) -
trunk/Tools/Scripts/webkitpy/layout_tests/port/base.py
r83361 r83475 207 207 return expected_text != actual_text 208 208 209 def compare_audio(self, expected_audio, actual_audio): 210 """Return whether the two audio files are *not* equal.""" 211 return expected_audio != actual_audio 212 209 213 def diff_image(self, expected_contents, actual_contents, 210 214 diff_filename=None, tolerance=0): … … 352 356 return self._filesystem.read_binary_file(path) 353 357 358 def expected_audio(self, test): 359 path = self.expected_filename(test, '.wav') 360 if not self.path_exists(path): 361 return None 362 return self._filesystem.read_binary_file(path) 363 354 364 def expected_text(self, test): 355 """Returns the text output we expect the test to produce. 365 """Returns the text output we expect the test to produce, or None 366 if we don't expect there to be any text output. 356 367 End-of-line characters are normalized to '\n'.""" 357 368 # FIXME: DRT output is actually utf-8, but since we don't decode the … … 360 371 path = self.expected_filename(test, '.txt') 361 372 if not self.path_exists(path): 362 return ''373 return None 363 374 text = self._filesystem.read_binary_file(path) 364 375 return text.replace("\r\n", "\n") … … 868 879 """Groups information about a output from driver for easy passing of data.""" 869 880 870 def __init__(self, text, image, image_hash, 871 crash=False, test_time= None, timeout=False, error=''):881 def __init__(self, text, image, image_hash, audio, 882 crash=False, test_time=0, timeout=False, error=''): 872 883 """Initializes a TestOutput object. 873 884 … … 876 887 image: an image output 877 888 image_hash: a string containing the checksum of the image 889 audio: contents of an audio stream, if any (in WAV format) 878 890 crash: a boolean indicating whether the driver crashed on the test 879 test_time: a time which the test has taken891 test_time: the time the test took to execute 880 892 timeout: a boolean indicating whehter the test timed out 881 893 error: any unexpected or additional (or error) text output … … 884 896 self.image = image 885 897 self.image_hash = image_hash 898 self.audio = audio 886 899 self.crash = crash 887 900 self.test_time = test_time -
trunk/Tools/Scripts/webkitpy/layout_tests/port/chromium.py
r83398 r83475 137 137 def diff_image(self, expected_contents, actual_contents, 138 138 diff_filename=None): 139 executable = self._path_to_image_diff() 139 # FIXME: need unit tests for this. 140 if not actual_contents and not expected_contents: 141 return False 142 if not actual_contents or not expected_contents: 143 return True 140 144 141 145 tempdir = self._filesystem.mkdtemp() … … 145 149 self._filesystem.write_binary_file(actual_filename, actual_contents) 146 150 151 executable = self._path_to_image_diff() 147 152 if diff_filename: 148 153 cmd = [executable, '--diff', expected_filename, … … 427 432 return self._port._filesystem.read_binary_file(png_path) 428 433 else: 429 return ''434 return None 430 435 431 436 def _output_image_with_retry(self): … … 502 507 (line, crash) = self._write_command_and_read_line(input=None) 503 508 509 # FIXME: Add support for audio when we're ready. 510 504 511 run_time = time.time() - start_time 505 512 output_image = self._output_image_with_retry() 506 assert output_image is not None 507 return base.DriverOutput(''.join(output), output_image, actual_checksum, 508 crash, run_time, timeout, ''.join(error)) 513 text = ''.join(output) 514 if not text: 515 text = None 516 517 return base.DriverOutput(text, output_image, actual_checksum, audio=None, 518 crash=crash, test_time=run_time, timeout=timeout, error=''.join(error)) 509 519 510 520 def stop(self): -
trunk/Tools/Scripts/webkitpy/layout_tests/port/dryrun.py
r83361 r83475 120 120 start_time = time.time() 121 121 fs = self._port._filesystem 122 if fs.exists(self._port.reftest_expected_filename(driver_input.filename)) or \ 123 fs.exists(self._port.reftest_expected_mismatch_filename(driver_input.filename)): 124 text_output = 'test-text' 122 if (fs.exists(self._port.reftest_expected_filename(driver_input.filename)) or 123 fs.exists(self._port.reftest_expected_mismatch_filename(driver_input.filename)) or 124 driver_input.filename.endswith('-expected.html')): 125 text = 'test-text' 125 126 image = 'test-image' 126 hash = 'test-checksum' 127 elif driver_input.filename.endswith('-expected.html'): 128 text_output = 'test-text' 129 image = 'test-image' 130 hash = 'test-checksum' 127 checksum = 'test-checksum' 128 audio = None 131 129 elif driver_input.filename.endswith('-expected-mismatch.html'): 132 text _output= 'test-text-mismatch'130 text = 'test-text-mismatch' 133 131 image = 'test-image-mismatch' 134 hash = 'test-checksum-mismatch' 135 elif driver_input.image_hash is not None: 136 text_output = self._port.expected_text(driver_input.filename) 132 checksum = 'test-checksum-mismatch' 133 audio = None 134 else: 135 text = self._port.expected_text(driver_input.filename) 137 136 image = self._port.expected_image(driver_input.filename) 138 hash = self._port.expected_checksum(driver_input.filename) 139 else: 140 text_output = self._port.expected_text(driver_input.filename) 141 image = None 142 hash = None 143 return base.DriverOutput(text_output, image, hash, False, 144 time.time() - start_time, False, '') 137 checksum = self._port.expected_checksum(driver_input.filename) 138 audio = self._port.expected_audio(driver_input.filename) 139 return base.DriverOutput(text, image, checksum, audio, crash=False, 140 test_time=time.time() - start_time, timeout=False, error='') 145 141 146 142 def start(self): -
trunk/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py
r83361 r83475 33 33 """ 34 34 35 import base64 35 36 import logging 36 37 import optparse … … 207 208 208 209 actual_text = port.expected_text(test_path) 210 actual_audio = port.expected_audio(test_path) 209 211 if self._options.pixel_tests and test_input.checksum: 210 212 actual_checksum = port.expected_checksum(test_path) 211 213 actual_image = port.expected_image(test_path) 212 214 213 self._stdout.write('Content-Type: text/plain\n') 214 215 # FIXME: Note that we don't ensure there is a trailing newline! 216 # This mirrors actual (Mac) DRT behavior but is a bug. 217 self._stdout.write(actual_text) 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 218 227 self._stdout.write('#EOF\n') 219 228 … … 224 233 if actual_checksum != test_input.checksum: 225 234 self._stdout.write('Content-Type: image/png\n') 226 self._stdout.write('Content-Length: %s\n \n' % len(actual_image))235 self._stdout.write('Content-Length: %s\n' % len(actual_image)) 227 236 self._stdout.write(actual_image) 228 237 self._stdout.write('#EOF\n') -
trunk/Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py
r83361 r83475 201 201 'ExpectedHash: wrong-checksum\n', 202 202 'Content-Type: image/png\n', 203 'Content-Length: 13\n \n',203 'Content-Length: 13\n', 204 204 'checksum\x8a-png', 205 205 '#EOF\n']) -
trunk/Tools/Scripts/webkitpy/layout_tests/port/test.py
r83361 r83475 31 31 from __future__ import with_statement 32 32 33 import base64 33 34 import time 34 35 … … 67 68 self.expected_image = self.actual_image 68 69 70 self.actual_audio = None 71 self.expected_audio = None 69 72 70 73 # This is an in-memory list of tests, what we want them to produce, and … … 112 115 actual_checksum='image_checksum_fail-checksum', 113 116 actual_image='image_checksum_fail-png') 117 tests.add('failures/expected/audio.html', 118 actual_audio=base64.b64encode('audio_fail-wav'), expected_audio='audio-wav', 119 actual_text=None, expected_text=None, 120 actual_image=None, expected_image=None, 121 actual_checksum=None, expected_checksum=None) 114 122 tests.add('failures/expected/keyboard.html', keyboard=True) 115 123 tests.add('failures/expected/missing_check.html', … … 117 125 expected_image=None) 118 126 tests.add('failures/expected/missing_image.html', expected_image=None) 127 tests.add('failures/expected/missing_audio.html', expected_audio=None, 128 actual_text=None, expected_text=None, 129 actual_image=None, expected_image=None, 130 actual_checksum=None, expected_checksum=None) 119 131 tests.add('failures/expected/missing_text.html', expected_text=None) 120 132 tests.add('failures/expected/newlines_leading.html', … … 135 147 tests.add('passes/error.html', error='stuff going to stderr') 136 148 tests.add('passes/image.html') 149 tests.add('passes/audio.html', 150 actual_audio=base64.b64encode('audio-wav'), expected_audio='audio-wav', 151 actual_text=None, expected_text=None, 152 actual_image=None, expected_image=None, 153 actual_checksum=None, expected_checksum=None) 137 154 tests.add('passes/platform_image.html') 138 155 tests.add('passes/checksum_in_image.html', … … 185 202 if test.is_reftest: 186 203 continue 204 if test.actual_audio: 205 add_file(files, test, '-expected.wav', test.expected_audio) 206 continue 207 187 208 add_file(files, test, '-expected.txt', test.expected_text) 188 209 add_file(files, test, '-expected.checksum', test.expected_checksum) 189 210 add_file(files, test, '-expected.png', test.expected_image) 211 190 212 191 213 # Add the test_expectations file. … … 195 217 // This one actually passes because the checksums will match. 196 218 WONTFIX : failures/expected/image.html = PASS 219 WONTFIX : failures/expected/audio.html = AUDIO 197 220 WONTFIX : failures/expected/image_checksum.html = IMAGE 198 221 WONTFIX : failures/expected/mismatch.html = IMAGE 199 222 WONTFIX : failures/expected/missing_check.html = MISSING PASS 200 223 WONTFIX : failures/expected/missing_image.html = MISSING PASS 224 WONTFIX : failures/expected/missing_audio.html = MISSING PASS 201 225 WONTFIX : failures/expected/missing_text.html = MISSING PASS 202 226 WONTFIX : failures/expected/newlines_leading.html = TEXT … … 413 437 if test.hang: 414 438 time.sleep((float(test_input.timeout) * 4) / 1000.0) 439 440 audio = None 441 if test.actual_audio: 442 audio = base64.b64decode(test.actual_audio) 415 443 return base.DriverOutput(test.actual_text, test.actual_image, 416 test.actual_checksum, test.crash, 417 time.time() - start_time, test.timeout, 418 test.error) 444 test.actual_checksum, audio, crash=test.crash, 445 test_time=time.time() - start_time, timeout=test.timeout, error=test.error) 419 446 420 447 def start(self): -
trunk/Tools/Scripts/webkitpy/layout_tests/port/webkit.py
r83361 r83475 31 31 """WebKit implementations of the Port interface.""" 32 32 33 33 import base64 34 34 import logging 35 35 import operator … … 110 110 111 111 # Handle the case where the test didn't actually generate an image. 112 if not actual_contents: 112 # FIXME: need unit tests for this. 113 if not actual_contents and not expected_contents: 114 return False 115 if not actual_contents or not expected_contents: 113 116 return True 114 117 … … 407 410 self._server_process.write(command) 408 411 409 have_seen_content_type = False 412 text = None 413 image = None 410 414 actual_image_hash = None 411 output = str() # Use a byte array for output, even though it should be UTF-8. 412 image = str() 413 414 timeout = int(driver_input.timeout) / 1000.0 415 deadline = time.time() + timeout 416 line = self._server_process.read_line(timeout) 417 while (not self._server_process.timed_out 418 and not self._server_process.crashed 419 and line.rstrip() != "#EOF"): 420 if (line.startswith('Content-Type:') and not 421 have_seen_content_type): 422 have_seen_content_type = True 423 else: 424 # Note: Text output from DumpRenderTree is always UTF-8. 425 # However, some tests (e.g. webarchives) spit out binary 426 # data instead of text. So to make things simple, we 427 # always treat the output as binary. 428 output += line 429 line = self._server_process.read_line(timeout) 430 timeout = deadline - time.time() 431 432 # Now read a second block of text for the optional image data 433 remaining_length = -1 434 HASH_HEADER = 'ActualHash: ' 435 LENGTH_HEADER = 'Content-Length: ' 436 line = self._server_process.read_line(timeout) 437 while (not self._server_process.timed_out 438 and not self._server_process.crashed 439 and line.rstrip() != "#EOF"): 440 if line.startswith(HASH_HEADER): 441 actual_image_hash = line[len(HASH_HEADER):].strip() 442 elif line.startswith('Content-Type:'): 443 pass 444 elif line.startswith(LENGTH_HEADER): 445 timeout = deadline - time.time() 446 content_length = int(line[len(LENGTH_HEADER):]) 447 image = self._server_process.read(timeout, content_length) 448 timeout = deadline - time.time() 449 line = self._server_process.read_line(timeout) 415 audio = None 416 deadline = time.time() + int(driver_input.timeout) / 1000.0 417 418 # First block is either text or audio 419 block = self._read_block(deadline) 420 if block.content_type == 'audio/wav': 421 audio = block.decoded_content 422 else: 423 text = block.decoded_content 424 425 # Now read an optional second block of image data 426 block = self._read_block(deadline) 427 if block.content and block.content_type == 'image/png': 428 image = block.decoded_content 429 actual_image_hash = block.content_hash 450 430 451 431 error_lines = self._server_process.error.splitlines() … … 459 439 # this reset in. 460 440 self._server_process.error = "" 461 return base.DriverOutput(output, image, actual_image_hash, 462 self._server_process.crashed, 463 time.time() - start_time, 464 self._server_process.timed_out, 465 error) 441 return base.DriverOutput(text, image, actual_image_hash, audio, 442 crash=self._server_process.crashed, test_time=time.time() - start_time, 443 timeout=self._server_process.timed_out, error=error) 444 445 def _read_block(self, deadline): 446 LENGTH_HEADER = 'Content-Length: ' 447 HASH_HEADER = 'ActualHash: ' 448 TYPE_HEADER = 'Content-Type: ' 449 ENCODING_HEADER = 'Content-Transfer-Encoding: ' 450 content_type = None 451 encoding = None 452 content_hash = None 453 content_length = None 454 455 # Content is treated as binary data even though the text output 456 # is usually UTF-8. 457 content = '' 458 timeout = deadline - time.time() 459 line = self._server_process.read_line(timeout) 460 while (not self._server_process.timed_out 461 and not self._server_process.crashed 462 and line.rstrip() != "#EOF"): 463 if line.startswith(TYPE_HEADER) and content_type is None: 464 content_type = line.split()[1] 465 elif line.startswith(ENCODING_HEADER) and encoding is None: 466 encoding = line.split()[1] 467 elif line.startswith(LENGTH_HEADER) and content_length is None: 468 timeout = deadline - time.time() 469 content_length = int(line[len(LENGTH_HEADER):]) 470 # FIXME: Technically there should probably be another blank 471 # line here, but DRT doesn't write one. 472 content = self._server_process.read(timeout, content_length) 473 elif line.startswith(HASH_HEADER): 474 content_hash = line.split()[1] 475 else: 476 content += line 477 line = self._server_process.read_line(timeout) 478 timeout = deadline - time.time() 479 return ContentBlock(content_type, encoding, content_hash, content) 466 480 467 481 def stop(self): … … 469 483 self._server_process.stop() 470 484 self._server_process = None 485 486 487 class ContentBlock(object): 488 def __init__(self, content_type, encoding, content_hash, content): 489 self.content_type = content_type 490 self.encoding = encoding 491 self.content_hash = content_hash 492 self.content = content 493 if self.encoding == 'base64': 494 self.decoded_content = base64.b64decode(content) 495 else: 496 self.decoded_content = content
Note: See TracChangeset
for help on using the changeset viewer.