Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1201)

Side by Side Diff: third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py

Issue 2014063002: Run format-webkit on webkitpy code (without string conversion). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright (C) 2010 Google Inc. All rights reserved. 1 # Copyright (C) 2010 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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 self.warnings = warnings 67 self.warnings = warnings
68 68
69 def __str__(self): 69 def __str__(self):
70 return '\n'.join(map(str, self.warnings)) 70 return '\n'.join(map(str, self.warnings))
71 71
72 def __repr__(self): 72 def __repr__(self):
73 return 'ParseError(warnings=%s)' % self.warnings 73 return 'ParseError(warnings=%s)' % self.warnings
74 74
75 75
76 class TestExpectationParser(object): 76 class TestExpectationParser(object):
77
77 """Provides parsing facilities for lines in the test_expectation.txt file."" " 78 """Provides parsing facilities for lines in the test_expectation.txt file."" "
78 79
79 # FIXME: Rename these to *_KEYWORD as in MISSING_KEYWORD above, but make 80 # FIXME: Rename these to *_KEYWORD as in MISSING_KEYWORD above, but make
80 # the case studdly-caps to match the actual file contents. 81 # the case studdly-caps to match the actual file contents.
81 REBASELINE_MODIFIER = 'rebaseline' 82 REBASELINE_MODIFIER = 'rebaseline'
82 NEEDS_REBASELINE_MODIFIER = 'needsrebaseline' 83 NEEDS_REBASELINE_MODIFIER = 'needsrebaseline'
83 NEEDS_MANUAL_REBASELINE_MODIFIER = 'needsmanualrebaseline' 84 NEEDS_MANUAL_REBASELINE_MODIFIER = 'needsmanualrebaseline'
84 PASS_EXPECTATION = 'pass' 85 PASS_EXPECTATION = 'pass'
85 SKIP_MODIFIER = 'skip' 86 SKIP_MODIFIER = 'skip'
86 SLOW_MODIFIER = 'slow' 87 SLOW_MODIFIER = 'slow'
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 if not expectation_line.bugs and self.WONTFIX_MODIFIER not in expectatio ns: 169 if not expectation_line.bugs and self.WONTFIX_MODIFIER not in expectatio ns:
169 expectation_line.warnings.append(self.MISSING_BUG_WARNING) 170 expectation_line.warnings.append(self.MISSING_BUG_WARNING)
170 if self.REBASELINE_MODIFIER in expectations: 171 if self.REBASELINE_MODIFIER in expectations:
171 expectation_line.warnings.append('REBASELINE should only be used for running rebaseline.py. Cannot be checked in.') 172 expectation_line.warnings.append('REBASELINE should only be used for running rebaseline.py. Cannot be checked in.')
172 173
173 if self.NEEDS_REBASELINE_MODIFIER in expectations or self.NEEDS_MANUAL_R EBASELINE_MODIFIER in expectations: 174 if self.NEEDS_REBASELINE_MODIFIER in expectations or self.NEEDS_MANUAL_R EBASELINE_MODIFIER in expectations:
174 for test in expectation_line.matching_tests: 175 for test in expectation_line.matching_tests:
175 if self._port.reference_files(test): 176 if self._port.reference_files(test):
176 text_expected_filename = self._port.expected_filename(test, '.txt') 177 text_expected_filename = self._port.expected_filename(test, '.txt')
177 if not self._port.host.filesystem.exists(text_expected_filen ame): 178 if not self._port.host.filesystem.exists(text_expected_filen ame):
178 expectation_line.warnings.append('A reftest without text expectation cannot be marked as NeedsRebaseline/NeedsManualRebaseline') 179 expectation_line.warnings.append(
180 'A reftest without text expectation cannot be marked as NeedsRebaseline/NeedsManualRebaseline')
179 181
180 specifiers = [specifier.lower() for specifier in expectation_line.specif iers] 182 specifiers = [specifier.lower() for specifier in expectation_line.specif iers]
181 if (self.REBASELINE_MODIFIER in expectations or self.NEEDS_REBASELINE_MO DIFIER in expectations) and ('debug' in specifiers or 'release' in specifiers): 183 if (self.REBASELINE_MODIFIER in expectations or self.NEEDS_REBASELINE_MO DIFIER in expectations) and (
184 'debug' in specifiers or 'release' in specifiers):
182 expectation_line.warnings.append('A test cannot be rebaselined for D ebug/Release.') 185 expectation_line.warnings.append('A test cannot be rebaselined for D ebug/Release.')
183 186
184 def _parse_expectations(self, expectation_line): 187 def _parse_expectations(self, expectation_line):
185 result = set() 188 result = set()
186 for part in expectation_line.expectations: 189 for part in expectation_line.expectations:
187 expectation = TestExpectations.expectation_from_string(part) 190 expectation = TestExpectations.expectation_from_string(part)
188 if expectation is None: # Careful, PASS is currently 0. 191 if expectation is None: # Careful, PASS is currently 0.
189 expectation_line.warnings.append('Unsupported expectation: %s' % part) 192 expectation_line.warnings.append('Unsupported expectation: %s' % part)
190 continue 193 continue
191 result.add(expectation) 194 result.add(expectation)
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 specifiers = [] 291 specifiers = []
289 name = None 292 name = None
290 expectations = [] 293 expectations = []
291 warnings = [] 294 warnings = []
292 has_unrecognized_expectation = False 295 has_unrecognized_expectation = False
293 296
294 tokens = remaining_string.split() 297 tokens = remaining_string.split()
295 state = 'start' 298 state = 'start'
296 for token in tokens: 299 for token in tokens:
297 if (token.startswith(WEBKIT_BUG_PREFIX) or 300 if (token.startswith(WEBKIT_BUG_PREFIX) or
298 token.startswith(CHROMIUM_BUG_PREFIX) or 301 token.startswith(CHROMIUM_BUG_PREFIX) or
299 token.startswith(V8_BUG_PREFIX) or 302 token.startswith(V8_BUG_PREFIX) or
300 token.startswith(NAMED_BUG_PREFIX)): 303 token.startswith(NAMED_BUG_PREFIX)):
301 if state != 'start': 304 if state != 'start':
302 warnings.append('"%s" is not at the start of the line.' % to ken) 305 warnings.append('"%s" is not at the start of the line.' % to ken)
303 break 306 break
304 if token.startswith(WEBKIT_BUG_PREFIX): 307 if token.startswith(WEBKIT_BUG_PREFIX):
305 bugs.append(token) 308 bugs.append(token)
306 elif token.startswith(CHROMIUM_BUG_PREFIX): 309 elif token.startswith(CHROMIUM_BUG_PREFIX):
307 bugs.append(token) 310 bugs.append(token)
308 elif token.startswith(V8_BUG_PREFIX): 311 elif token.startswith(V8_BUG_PREFIX):
309 bugs.append(token) 312 bugs.append(token)
310 else: 313 else:
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 if 'WONTFIX' in expectations and 'SKIP' not in expectations: 360 if 'WONTFIX' in expectations and 'SKIP' not in expectations:
358 expectations.append('SKIP') 361 expectations.append('SKIP')
359 362
360 if ('SKIP' in expectations or 'WONTFIX' in expectations) and len(set(exp ectations) - set(['SKIP', 'WONTFIX'])): 363 if ('SKIP' in expectations or 'WONTFIX' in expectations) and len(set(exp ectations) - set(['SKIP', 'WONTFIX'])):
361 warnings.append('A test marked Skip or WontFix must not have other e xpectations.') 364 warnings.append('A test marked Skip or WontFix must not have other e xpectations.')
362 365
363 if 'SLOW' in expectations and 'SlowTests' not in filename: 366 if 'SLOW' in expectations and 'SlowTests' not in filename:
364 warnings.append('SLOW tests should ony be added to SlowTests and not to TestExpectations.') 367 warnings.append('SLOW tests should ony be added to SlowTests and not to TestExpectations.')
365 368
366 if 'WONTFIX' in expectations and ('NeverFixTests' not in filename and 'S taleTestExpectations' not in filename): 369 if 'WONTFIX' in expectations and ('NeverFixTests' not in filename and 'S taleTestExpectations' not in filename):
367 warnings.append('WONTFIX tests should ony be added to NeverFixTests or StaleTestExpectations and not to TestExpectations.') 370 warnings.append(
371 'WONTFIX tests should ony be added to NeverFixTests or StaleTest Expectations and not to TestExpectations.')
368 372
369 if 'NeverFixTests' in filename and expectations != ['WONTFIX', 'SKIP']: 373 if 'NeverFixTests' in filename and expectations != ['WONTFIX', 'SKIP']:
370 warnings.append('Only WONTFIX expectations are allowed in NeverFixTe sts') 374 warnings.append('Only WONTFIX expectations are allowed in NeverFixTe sts')
371 375
372 if 'SlowTests' in filename and expectations != ['SLOW']: 376 if 'SlowTests' in filename and expectations != ['SLOW']:
373 warnings.append('Only SLOW expectations are allowed in SlowTests') 377 warnings.append('Only SLOW expectations are allowed in SlowTests')
374 378
375 if not expectations and not has_unrecognized_expectation: 379 if not expectations and not has_unrecognized_expectation:
376 warnings.append('Missing expectations.') 380 warnings.append('Missing expectations.')
377 381
378 expectation_line.bugs = bugs 382 expectation_line.bugs = bugs
379 expectation_line.specifiers = specifiers 383 expectation_line.specifiers = specifiers
380 expectation_line.expectations = expectations 384 expectation_line.expectations = expectations
381 expectation_line.name = name 385 expectation_line.name = name
382 expectation_line.warnings = warnings 386 expectation_line.warnings = warnings
383 return expectation_line 387 return expectation_line
384 388
385 @classmethod 389 @classmethod
386 def _split_space_separated(cls, space_separated_string): 390 def _split_space_separated(cls, space_separated_string):
387 """Splits a space-separated string into an array.""" 391 """Splits a space-separated string into an array."""
388 return [part.strip() for part in space_separated_string.strip().split(' ')] 392 return [part.strip() for part in space_separated_string.strip().split(' ')]
389 393
390 394
391 class TestExpectationLine(object): 395 class TestExpectationLine(object):
396
392 """Represents a line in test expectations file.""" 397 """Represents a line in test expectations file."""
393 398
394 def __init__(self): 399 def __init__(self):
395 """Initializes a blank-line equivalent of an expectation.""" 400 """Initializes a blank-line equivalent of an expectation."""
396 self.original_string = None 401 self.original_string = None
397 self.filename = None # this is the path to the expectations file for th is line 402 self.filename = None # this is the path to the expectations file for th is line
398 self.line_numbers = "0" 403 self.line_numbers = "0"
399 self.name = None # this is the path in the line itself 404 self.name = None # this is the path in the line itself
400 self.path = None # this is the normpath of self.name 405 self.path = None # this is the normpath of self.name
401 self.bugs = [] 406 self.bugs = []
402 self.specifiers = [] 407 self.specifiers = []
403 self.parsed_specifiers = [] 408 self.parsed_specifiers = []
404 self.matching_configurations = set() 409 self.matching_configurations = set()
405 self.expectations = [] 410 self.expectations = []
406 self.parsed_expectations = set() 411 self.parsed_expectations = set()
407 self.comment = None 412 self.comment = None
408 self.matching_tests = [] 413 self.matching_tests = []
409 self.warnings = [] 414 self.warnings = []
410 self.is_skipped_outside_expectations_file = False 415 self.is_skipped_outside_expectations_file = False
411 416
412 def __str__(self): 417 def __str__(self):
413 return "TestExpectationLine{name=%s, matching_configurations=%s, origina l_string=%s}" % (self.name, self.matching_configurations, self.original_string) 418 return "TestExpectationLine{name=%s, matching_configurations=%s, origina l_string=%s}" % (
419 self.name, self.matching_configurations, self.original_string)
414 420
415 def __eq__(self, other): 421 def __eq__(self, other):
416 return (self.original_string == other.original_string 422 return (self.original_string == other.original_string
417 and self.filename == other.filename 423 and self.filename == other.filename
418 and self.line_numbers == other.line_numbers 424 and self.line_numbers == other.line_numbers
419 and self.name == other.name 425 and self.name == other.name
420 and self.path == other.path 426 and self.path == other.path
421 and self.bugs == other.bugs 427 and self.bugs == other.bugs
422 and self.specifiers == other.specifiers 428 and self.specifiers == other.specifiers
423 and self.parsed_specifiers == other.parsed_specifiers 429 and self.parsed_specifiers == other.parsed_specifiers
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 526
521 @staticmethod 527 @staticmethod
522 def _filter_redundant_expectations(expectations): 528 def _filter_redundant_expectations(expectations):
523 if set(expectations) == set(['Pass', 'Skip']): 529 if set(expectations) == set(['Pass', 'Skip']):
524 return ['Skip'] 530 return ['Skip']
525 if set(expectations) == set(['Pass', 'Slow']): 531 if set(expectations) == set(['Pass', 'Slow']):
526 return ['Slow'] 532 return ['Slow']
527 return expectations 533 return expectations
528 534
529 @staticmethod 535 @staticmethod
530 def _format_line(bugs, specifiers, name, expectations, comment, include_spec ifiers=True, include_expectations=True, include_comment=True): 536 def _format_line(bugs, specifiers, name, expectations, comment, include_spec ifiers=True,
537 include_expectations=True, include_comment=True):
531 new_specifiers = [] 538 new_specifiers = []
532 new_expectations = [] 539 new_expectations = []
533 for specifier in specifiers: 540 for specifier in specifiers:
534 # FIXME: Make this all work with the mixed-cased specifiers (e.g. Wo ntFix, Slow, etc). 541 # FIXME: Make this all work with the mixed-cased specifiers (e.g. Wo ntFix, Slow, etc).
535 specifier = specifier.upper() 542 specifier = specifier.upper()
536 new_specifiers.append(TestExpectationParser._inverted_configuration_ tokens.get(specifier, specifier)) 543 new_specifiers.append(TestExpectationParser._inverted_configuration_ tokens.get(specifier, specifier))
537 544
538 for expectation in expectations: 545 for expectation in expectations:
539 expectation = expectation.upper() 546 expectation = expectation.upper()
540 new_expectations.append(TestExpectationParser._inverted_expectation_ tokens.get(expectation, expectation)) 547 new_expectations.append(TestExpectationParser._inverted_expectation_ tokens.get(expectation, expectation))
541 548
542 result = '' 549 result = ''
543 if include_specifiers and (bugs or new_specifiers): 550 if include_specifiers and (bugs or new_specifiers):
544 if bugs: 551 if bugs:
545 result += ' '.join(bugs) + ' ' 552 result += ' '.join(bugs) + ' '
546 if new_specifiers: 553 if new_specifiers:
547 result += '[ %s ] ' % ' '.join(new_specifiers) 554 result += '[ %s ] ' % ' '.join(new_specifiers)
548 result += name 555 result += name
549 if include_expectations and new_expectations: 556 if include_expectations and new_expectations:
550 new_expectations = TestExpectationLine._filter_redundant_expectation s(new_expectations) 557 new_expectations = TestExpectationLine._filter_redundant_expectation s(new_expectations)
551 result += ' [ %s ]' % ' '.join(sorted(set(new_expectations))) 558 result += ' [ %s ]' % ' '.join(sorted(set(new_expectations)))
552 if include_comment and comment is not None: 559 if include_comment and comment is not None:
553 result += " #%s" % comment 560 result += " #%s" % comment
554 return result 561 return result
555 562
556 563
557 # FIXME: Refactor API to be a proper CRUD. 564 # FIXME: Refactor API to be a proper CRUD.
558 class TestExpectationsModel(object): 565 class TestExpectationsModel(object):
566
559 """Represents relational store of all expectations and provides CRUD semanti cs to manage it.""" 567 """Represents relational store of all expectations and provides CRUD semanti cs to manage it."""
560 568
561 def __init__(self, shorten_filename=None): 569 def __init__(self, shorten_filename=None):
562 # Maps a test to its list of expectations. 570 # Maps a test to its list of expectations.
563 self._test_to_expectations = {} 571 self._test_to_expectations = {}
564 572
565 # Maps a test to list of its specifiers (string values) 573 # Maps a test to list of its specifiers (string values)
566 self._test_to_specifiers = {} 574 self._test_to_specifiers = {}
567 575
568 # Maps a test to a TestExpectationLine instance. 576 # Maps a test to a TestExpectationLine instance.
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
812 self._shorten_filename( 820 self._shorten_filename(
813 prev_expectation_line.fi lename), prev_expectation_line.line_numbers, 821 prev_expectation_line.fi lename), prev_expectation_line.line_numbers,
814 self._shorten_filename(expec tation_line.filename), expectation_line.line_numbers)) 822 self._shorten_filename(expec tation_line.filename), expectation_line.line_numbers))
815 return True 823 return True
816 824
817 # Configuration sets are disjoint, then. 825 # Configuration sets are disjoint, then.
818 return False 826 return False
819 827
820 828
821 class TestExpectations(object): 829 class TestExpectations(object):
830
822 """Test expectations consist of lines with specifications of what 831 """Test expectations consist of lines with specifications of what
823 to expect from layout test cases. The test cases can be directories 832 to expect from layout test cases. The test cases can be directories
824 in which case the expectations apply to all test cases in that 833 in which case the expectations apply to all test cases in that
825 directory and any subdirectory. The format is along the lines of: 834 directory and any subdirectory. The format is along the lines of:
826 835
827 LayoutTests/fast/js/fixme.js [ Failure ] 836 LayoutTests/fast/js/fixme.js [ Failure ]
828 LayoutTests/fast/js/flaky.js [ Failure Pass ] 837 LayoutTests/fast/js/flaky.js [ Failure Pass ]
829 LayoutTests/fast/js/crash.js [ Crash Failure Pass Timeout ] 838 LayoutTests/fast/js/crash.js [ Crash Failure Pass Timeout ]
830 ... 839 ...
831 840
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 """Returns whether we got a result we were expecting. 912 """Returns whether we got a result we were expecting.
904 Args: 913 Args:
905 result: actual result of a test execution 914 result: actual result of a test execution
906 expected_results: set of results listed in test_expectations 915 expected_results: set of results listed in test_expectations
907 test_needs_rebaselining: whether test was marked as REBASELINE""" 916 test_needs_rebaselining: whether test was marked as REBASELINE"""
908 if not (set(expected_results) - (set(TestExpectations.NON_TEST_OUTCOME_E XPECTATIONS))): 917 if not (set(expected_results) - (set(TestExpectations.NON_TEST_OUTCOME_E XPECTATIONS))):
909 expected_results = set([PASS]) 918 expected_results = set([PASS])
910 919
911 if result in expected_results: 920 if result in expected_results:
912 return True 921 return True
913 if result in (PASS, TEXT, IMAGE, IMAGE_PLUS_TEXT, AUDIO, MISSING) and (N EEDS_REBASELINE in expected_results or NEEDS_MANUAL_REBASELINE in expected_resul ts): 922 if result in (PASS, TEXT, IMAGE, IMAGE_PLUS_TEXT, AUDIO, MISSING) and (
923 NEEDS_REBASELINE in expected_results or NEEDS_MANUAL_REBASELINE in expected_results):
914 return True 924 return True
915 if result in (TEXT, IMAGE, IMAGE_PLUS_TEXT, AUDIO) and (FAIL in expected _results): 925 if result in (TEXT, IMAGE, IMAGE_PLUS_TEXT, AUDIO) and (FAIL in expected _results):
916 return True 926 return True
917 if result == MISSING and test_needs_rebaselining: 927 if result == MISSING and test_needs_rebaselining:
918 return True 928 return True
919 if result == SKIP: 929 if result == SKIP:
920 return True 930 return True
921 return False 931 return False
922 932
923 @staticmethod 933 @staticmethod
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
969 suffixes.add('wav') 979 suffixes.add('wav')
970 if 'MISSING' in expectations: 980 if 'MISSING' in expectations:
971 suffixes.add('txt') 981 suffixes.add('txt')
972 suffixes.add('png') 982 suffixes.add('png')
973 suffixes.add('wav') 983 suffixes.add('wav')
974 return suffixes 984 return suffixes
975 985
976 # FIXME: This constructor does too much work. We should move the actual pars ing of 986 # FIXME: This constructor does too much work. We should move the actual pars ing of
977 # the expectations into separate routines so that linting and handling overr ides 987 # the expectations into separate routines so that linting and handling overr ides
978 # can be controlled separately, and the constructor can be more of a no-op. 988 # can be controlled separately, and the constructor can be more of a no-op.
979 def __init__(self, port, tests=None, include_overrides=True, expectations_di ct=None, model_all_expectations=False, is_lint_mode=False): 989 def __init__(self, port, tests=None, include_overrides=True, expectations_di ct=None,
990 model_all_expectations=False, is_lint_mode=False):
980 self._full_test_list = tests 991 self._full_test_list = tests
981 self._test_config = port.test_configuration() 992 self._test_config = port.test_configuration()
982 self._is_lint_mode = is_lint_mode 993 self._is_lint_mode = is_lint_mode
983 self._model_all_expectations = self._is_lint_mode or model_all_expectati ons 994 self._model_all_expectations = self._is_lint_mode or model_all_expectati ons
984 self._model = TestExpectationsModel(self._shorten_filename) 995 self._model = TestExpectationsModel(self._shorten_filename)
985 self._parser = TestExpectationParser(port, tests, self._is_lint_mode) 996 self._parser = TestExpectationParser(port, tests, self._is_lint_mode)
986 self._port = port 997 self._port = port
987 self._skipped_tests_warnings = [] 998 self._skipped_tests_warnings = []
988 self._expectations = [] 999 self._expectations = []
989 1000
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
1166 # If reconstitute_only_these is an empty list, we want to return ori ginal_string. 1177 # If reconstitute_only_these is an empty list, we want to return ori ginal_string.
1167 # So we need to compare reconstitute_only_these to None, not just ch eck if it's falsey. 1178 # So we need to compare reconstitute_only_these to None, not just ch eck if it's falsey.
1168 if reconstitute_only_these is None or expectation_line in reconstitu te_only_these: 1179 if reconstitute_only_these is None or expectation_line in reconstitu te_only_these:
1169 return expectation_line.to_string(test_configuration_converter) 1180 return expectation_line.to_string(test_configuration_converter)
1170 return expectation_line.original_string 1181 return expectation_line.original_string
1171 1182
1172 def nones_out(expectation_line): 1183 def nones_out(expectation_line):
1173 return expectation_line is not None 1184 return expectation_line is not None
1174 1185
1175 return "\n".join(filter(nones_out, map(serialize, expectation_lines))) 1186 return "\n".join(filter(nones_out, map(serialize, expectation_lines)))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698