| OLD | NEW |
| 1 # Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """A helper class for reading in and dealing with tests expectations | 5 """A helper class for reading in and dealing with tests expectations |
| 6 for layout tests. | 6 for layout tests. |
| 7 """ | 7 """ |
| 8 | 8 |
| 9 import logging | 9 import logging |
| 10 import os | 10 import os |
| 11 import re | 11 import re |
| 12 import sys | 12 import sys |
| 13 import path_utils | 13 import path_utils |
| 14 import compare_failures | 14 import compare_failures |
| 15 | 15 |
| 16 | 16 |
| 17 # Test expectation and modifier constants. | 17 # Test expectation and modifier constants. |
| 18 (PASS, FAIL, TIMEOUT, CRASH, SKIP, WONTFIX, DEFER, NONE) = range(8) | 18 (PASS, FAIL, TIMEOUT, CRASH, SKIP, WONTFIX, DEFER, SLOW, NONE) = range(9) |
| 19 | 19 |
| 20 class TestExpectations: | 20 class TestExpectations: |
| 21 TEST_LIST = "test_expectations.txt" | 21 TEST_LIST = "test_expectations.txt" |
| 22 | 22 |
| 23 def __init__(self, tests, directory, platform, is_debug_mode): | 23 def __init__(self, tests, directory, platform, is_debug_mode): |
| 24 """Reads the test expectations files from the given directory.""" | 24 """Reads the test expectations files from the given directory.""" |
| 25 path = os.path.join(directory, self.TEST_LIST) | 25 path = os.path.join(directory, self.TEST_LIST) |
| 26 self._expected_failures = TestExpectationsFile(path, tests, platform, | 26 self._expected_failures = TestExpectationsFile(path, tests, platform, |
| 27 is_debug_mode) | 27 is_debug_mode) |
| 28 | 28 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 | 105 |
| 106 def IsDeferred(self, test): | 106 def IsDeferred(self, test): |
| 107 return self._expected_failures.HasModifier(test, DEFER) | 107 return self._expected_failures.HasModifier(test, DEFER) |
| 108 | 108 |
| 109 def IsFixable(self, test): | 109 def IsFixable(self, test): |
| 110 return self._expected_failures.HasModifier(test, NONE) | 110 return self._expected_failures.HasModifier(test, NONE) |
| 111 | 111 |
| 112 def IsIgnored(self, test): | 112 def IsIgnored(self, test): |
| 113 return self._expected_failures.HasModifier(test, WONTFIX) | 113 return self._expected_failures.HasModifier(test, WONTFIX) |
| 114 | 114 |
| 115 def HasModifier(self, test, modifier): |
| 116 return self._expected_failures.HasModifier(test, modifier) |
| 117 |
| 115 def StripComments(line): | 118 def StripComments(line): |
| 116 """Strips comments from a line and return None if the line is empty | 119 """Strips comments from a line and return None if the line is empty |
| 117 or else the contents of line with leading and trailing spaces removed | 120 or else the contents of line with leading and trailing spaces removed |
| 118 and all other whitespace collapsed""" | 121 and all other whitespace collapsed""" |
| 119 | 122 |
| 120 commentIndex = line.find('//') | 123 commentIndex = line.find('//') |
| 121 if commentIndex is -1: | 124 if commentIndex is -1: |
| 122 commentIndex = len(line) | 125 commentIndex = len(line) |
| 123 | 126 |
| 124 line = re.sub(r'\s+', ' ', line[:commentIndex].strip()) | 127 line = re.sub(r'\s+', ' ', line[:commentIndex].strip()) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 138 ... | 141 ... |
| 139 | 142 |
| 140 To add other options: | 143 To add other options: |
| 141 SKIP : LayoutTests/fast/js/no-good.js = TIMEOUT PASS | 144 SKIP : LayoutTests/fast/js/no-good.js = TIMEOUT PASS |
| 142 DEBUG : LayoutTests/fast/js/no-good.js = TIMEOUT PASS | 145 DEBUG : LayoutTests/fast/js/no-good.js = TIMEOUT PASS |
| 143 DEBUG SKIP : LayoutTests/fast/js/no-good.js = TIMEOUT PASS | 146 DEBUG SKIP : LayoutTests/fast/js/no-good.js = TIMEOUT PASS |
| 144 LINUX DEBUG SKIP : LayoutTests/fast/js/no-good.js = TIMEOUT PASS | 147 LINUX DEBUG SKIP : LayoutTests/fast/js/no-good.js = TIMEOUT PASS |
| 145 DEFER LINUX WIN : LayoutTests/fast/js/no-good.js = TIMEOUT PASS | 148 DEFER LINUX WIN : LayoutTests/fast/js/no-good.js = TIMEOUT PASS |
| 146 | 149 |
| 147 SKIP: Doesn't run the test. | 150 SKIP: Doesn't run the test. |
| 151 SLOW: The test takes a long time to run, but does not timeout indefinitely. |
| 148 WONTFIX: For tests that we never intend to pass on a given platform. | 152 WONTFIX: For tests that we never intend to pass on a given platform. |
| 149 DEFER: Test does not count in our statistics for the current release. | 153 DEFER: Test does not count in our statistics for the current release. |
| 150 DEBUG: Expectations apply only to the debug build. | 154 DEBUG: Expectations apply only to the debug build. |
| 151 RELEASE: Expectations apply only to release build. | 155 RELEASE: Expectations apply only to release build. |
| 152 LINUX/WIN/MAC: Expectations apply only to these platforms. | 156 LINUX/WIN/MAC: Expectations apply only to these platforms. |
| 153 | 157 |
| 154 A test can be included twice, but not via the same path. If a test is included | 158 Notes: |
| 155 twice, then the more precise path wins. | 159 -A test cannot be both SLOW and TIMEOUT |
| 160 -A test cannot be both DEFER and WONTFIX |
| 161 -A test can be included twice, but not via the same path. |
| 162 -If a test is included twice, then the more precise path wins. |
| 163 -CRASH tests cannot be DEFER or WONTFIX |
| 156 """ | 164 """ |
| 157 | 165 |
| 158 EXPECTATIONS = { 'pass': PASS, | 166 EXPECTATIONS = { 'pass': PASS, |
| 159 'fail': FAIL, | 167 'fail': FAIL, |
| 160 'timeout': TIMEOUT, | 168 'timeout': TIMEOUT, |
| 161 'crash': CRASH } | 169 'crash': CRASH } |
| 162 | 170 |
| 163 PLATFORMS = [ 'mac', 'linux', 'win' ] | 171 PLATFORMS = [ 'mac', 'linux', 'win' ] |
| 164 | 172 |
| 165 BUILD_TYPES = [ 'debug', 'release' ] | 173 BUILD_TYPES = [ 'debug', 'release' ] |
| 166 | 174 |
| 167 MODIFIERS = { 'skip': SKIP, | 175 MODIFIERS = { 'skip': SKIP, |
| 168 'wontfix': WONTFIX, | 176 'wontfix': WONTFIX, |
| 169 'defer': DEFER, | 177 'defer': DEFER, |
| 178 'slow': SLOW, |
| 170 'none': NONE } | 179 'none': NONE } |
| 171 | 180 |
| 172 def __init__(self, path, full_test_list, platform, is_debug_mode): | 181 def __init__(self, path, full_test_list, platform, is_debug_mode): |
| 173 """ | 182 """ |
| 174 path: The path to the expectation file. An error is thrown if a test is | 183 path: The path to the expectation file. An error is thrown if a test is |
| 175 listed more than once. | 184 listed more than once. |
| 176 full_test_list: The list of all tests to be run pending processing of the | 185 full_test_list: The list of all tests to be run pending processing of the |
| 177 expections for those tests. | 186 expections for those tests. |
| 178 platform: Which platform from self.PLATFORMS to filter tests for. | 187 platform: Which platform from self.PLATFORMS to filter tests for. |
| 179 is_debug_mode: Whether we testing a test_shell built debug mode. | 188 is_debug_mode: Whether we testing a test_shell built debug mode. |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 | 300 |
| 292 tests_and_expecation_parts = test_and_expectations.split('=') | 301 tests_and_expecation_parts = test_and_expectations.split('=') |
| 293 if (len(tests_and_expecation_parts) is not 2): | 302 if (len(tests_and_expecation_parts) is not 2): |
| 294 self._AddError(lineno, 'Missing expectations.', test_and_expectations) | 303 self._AddError(lineno, 'Missing expectations.', test_and_expectations) |
| 295 continue | 304 continue |
| 296 | 305 |
| 297 test_list_path = tests_and_expecation_parts[0].strip() | 306 test_list_path = tests_and_expecation_parts[0].strip() |
| 298 expectations = self._ParseExpectations(tests_and_expecation_parts[1], | 307 expectations = self._ParseExpectations(tests_and_expecation_parts[1], |
| 299 lineno, test_list_path) | 308 lineno, test_list_path) |
| 300 | 309 |
| 310 if 'slow' in options and TIMEOUT in expectations: |
| 311 self._AddError(lineno, 'A test cannot be both slow and timeout. If the ' |
| 312 'test times out indefinitely, the it should be listed as timeout.', |
| 313 test_and_expectations) |
| 314 |
| 301 full_path = os.path.join(path_utils.LayoutDataDir(), test_list_path) | 315 full_path = os.path.join(path_utils.LayoutDataDir(), test_list_path) |
| 302 full_path = os.path.normpath(full_path) | 316 full_path = os.path.normpath(full_path) |
| 303 # WebKit's way of skipping tests is to add a -disabled suffix. | 317 # WebKit's way of skipping tests is to add a -disabled suffix. |
| 304 # So we should consider the path existing if the path or the -disabled | 318 # So we should consider the path existing if the path or the -disabled |
| 305 # version exists. | 319 # version exists. |
| 306 if not os.path.exists(full_path) and not \ | 320 if not os.path.exists(full_path) and not \ |
| 307 os.path.exists(full_path + '-disabled'): | 321 os.path.exists(full_path + '-disabled'): |
| 308 # Log a non fatal error here since you hit this case any time you | 322 # Log a non fatal error here since you hit this case any time you |
| 309 # update test_expectations.txt without syncing the LayoutTests | 323 # update test_expectations.txt without syncing the LayoutTests |
| 310 # directory | 324 # directory |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 def _AddError(self, lineno, msg, path): | 426 def _AddError(self, lineno, msg, path): |
| 413 """Reports an error that will prevent running the tests. Does not | 427 """Reports an error that will prevent running the tests. Does not |
| 414 immediately raise an exception because we'd like to aggregate all the | 428 immediately raise an exception because we'd like to aggregate all the |
| 415 errors so they can all be printed out.""" | 429 errors so they can all be printed out.""" |
| 416 self._errors.append('\nLine:%s %s %s' % (lineno, msg, path)) | 430 self._errors.append('\nLine:%s %s %s' % (lineno, msg, path)) |
| 417 | 431 |
| 418 def _LogNonFatalError(self, lineno, msg, path): | 432 def _LogNonFatalError(self, lineno, msg, path): |
| 419 """Reports an error that will not prevent running the tests. These are | 433 """Reports an error that will not prevent running the tests. These are |
| 420 still errors, but not bad enough to warrant breaking test running.""" | 434 still errors, but not bad enough to warrant breaking test running.""" |
| 421 self._non_fatal_errors.append('Line:%s %s %s' % (lineno, msg, path)) | 435 self._non_fatal_errors.append('Line:%s %s %s' % (lineno, msg, path)) |
| OLD | NEW |