OLD | NEW |
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 643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
654 raise ValueError(expectation) | 654 raise ValueError(expectation) |
655 | 655 |
656 def remove_expectation_line(self, test): | 656 def remove_expectation_line(self, test): |
657 if not self.has_test(test): | 657 if not self.has_test(test): |
658 return | 658 return |
659 self._clear_expectations_for_test(test) | 659 self._clear_expectations_for_test(test) |
660 del self._test_to_expectation_line[test] | 660 del self._test_to_expectation_line[test] |
661 | 661 |
662 def add_expectation_line(self, expectation_line, | 662 def add_expectation_line(self, expectation_line, |
663 model_all_expectations=False): | 663 model_all_expectations=False): |
664 """Returns a list of warnings encountered while matching specifiers.""" | |
665 | |
666 if expectation_line.is_invalid(): | 664 if expectation_line.is_invalid(): |
667 return | 665 return |
668 | 666 |
669 for test in expectation_line.matching_tests: | 667 for test in expectation_line.matching_tests: |
670 if self._already_seen_better_match(test, expectation_line): | 668 lines_involve_rebaseline = False |
671 continue | 669 prev_expectation_line = self.get_expectation_line(test) |
672 | 670 |
673 if model_all_expectations: | 671 if prev_expectation_line: |
674 expectation_line = TestExpectationLine.merge_expectation_lines(s
elf.get_expectation_line(test), expectation_line, model_all_expectations) | 672 # The previous path matched more of the test. |
| 673 if len(prev_expectation_line.path) > len(expectation_line.path): |
| 674 continue |
| 675 |
| 676 if self._lines_conflict(prev_expectation_line, expectation_line)
: |
| 677 continue |
| 678 |
| 679 lines_involve_rebaseline = self._expects_rebaseline(prev_expecta
tion_line) or self._expects_rebaseline(expectation_line) |
| 680 |
| 681 # Exact path matches that conflict should be merged, e.g. |
| 682 # [ Pass Timeout ] + [ NeedsRebaseline ] ==> [ Pass Timeout NeedsReb
aseline ]. |
| 683 if model_all_expectations or lines_involve_rebaseline: |
| 684 expectation_line = TestExpectationLine.merge_expectation_lines(p
rev_expectation_line, expectation_line, model_all_expectations) |
675 | 685 |
676 self._clear_expectations_for_test(test) | 686 self._clear_expectations_for_test(test) |
677 self._test_to_expectation_line[test] = expectation_line | 687 self._test_to_expectation_line[test] = expectation_line |
678 self._add_test(test, expectation_line) | 688 self._add_test(test, expectation_line) |
679 | 689 |
680 def _add_test(self, test, expectation_line): | 690 def _add_test(self, test, expectation_line): |
681 """Sets the expected state for a given test. | 691 """Sets the expected state for a given test. |
682 | 692 |
683 This routine assumes the test has not been added before. If it has, | 693 This routine assumes the test has not been added before. If it has, |
684 use _clear_expectations_for_test() to reset the state prior to | 694 use _clear_expectations_for_test() to reset the state prior to |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
718 def _remove_from_sets(self, test, dict_of_sets_of_tests): | 728 def _remove_from_sets(self, test, dict_of_sets_of_tests): |
719 """Removes the given test from the sets in the dictionary. | 729 """Removes the given test from the sets in the dictionary. |
720 | 730 |
721 Args: | 731 Args: |
722 test: test to look for | 732 test: test to look for |
723 dict: dict of sets of files""" | 733 dict: dict of sets of files""" |
724 for set_of_tests in dict_of_sets_of_tests.itervalues(): | 734 for set_of_tests in dict_of_sets_of_tests.itervalues(): |
725 if test in set_of_tests: | 735 if test in set_of_tests: |
726 set_of_tests.remove(test) | 736 set_of_tests.remove(test) |
727 | 737 |
728 def _already_seen_better_match(self, test, expectation_line): | 738 def _expects_rebaseline(self, expectation_line): |
729 """Returns whether we've seen a better match already in the file. | 739 expectations = expectation_line.parsed_expectations |
| 740 return REBASELINE in expectations or NEEDS_REBASELINE in expectations or
NEEDS_MANUAL_REBASELINE in expectations |
730 | 741 |
731 Returns True if we've already seen a expectation_line.name that matches
more of the test | 742 def _lines_conflict(self, prev_expectation_line, expectation_line): |
732 than this path does | 743 if prev_expectation_line.path != expectation_line.path: |
733 """ | |
734 # FIXME: See comment below about matching test configs and specificity. | |
735 if not self.has_test(test): | |
736 # We've never seen this test before. | |
737 return False | 744 return False |
738 | 745 |
739 prev_expectation_line = self._test_to_expectation_line[test] | 746 if PASS in expectation_line.parsed_expectations and self._expects_rebase
line(prev_expectation_line): |
740 | |
741 if prev_expectation_line.filename != expectation_line.filename: | |
742 # We've moved on to a new expectation file, which overrides older on
es. | |
743 return False | 747 return False |
744 | 748 |
745 if len(prev_expectation_line.path) > len(expectation_line.path): | 749 if PASS in prev_expectation_line.parsed_expectations and self._expects_r
ebaseline(expectation_line): |
746 # The previous path matched more of the test. | |
747 return True | |
748 | |
749 if len(prev_expectation_line.path) < len(expectation_line.path): | |
750 # This path matches more of the test. | |
751 return False | 750 return False |
752 | 751 |
753 # At this point we know we have seen a previous exact match on this | |
754 # base path, so we need to check the two sets of specifiers. | |
755 | |
756 # FIXME: This code was originally designed to allow lines that matched | |
757 # more specifiers to override lines that matched fewer specifiers. | |
758 # However, we currently view these as errors. | |
759 # | |
760 # To use the "more specifiers wins" policy, change the errors for overri
des | |
761 # to be warnings and return False". | |
762 | |
763 if prev_expectation_line.matching_configurations == expectation_line.mat
ching_configurations: | 752 if prev_expectation_line.matching_configurations == expectation_line.mat
ching_configurations: |
764 expectation_line.warnings.append('Duplicate or ambiguous entry lines
%s:%s and %s:%s.' % ( | 753 expectation_line.warnings.append('Duplicate or ambiguous entry lines
%s:%s and %s:%s.' % ( |
765 self._shorten_filename(prev_expectation_line.filename), prev_exp
ectation_line.line_numbers, | 754 self._shorten_filename(prev_expectation_line.filename), prev_exp
ectation_line.line_numbers, |
766 self._shorten_filename(expectation_line.filename), expectation_l
ine.line_numbers)) | 755 self._shorten_filename(expectation_line.filename), expectation_l
ine.line_numbers)) |
767 return True | 756 return True |
768 | 757 |
769 if prev_expectation_line.matching_configurations >= expectation_line.mat
ching_configurations: | 758 if prev_expectation_line.matching_configurations >= expectation_line.mat
ching_configurations: |
770 expectation_line.warnings.append('More specific entry for %s on line
%s:%s overrides line %s:%s.' % (expectation_line.name, | 759 expectation_line.warnings.append('More specific entry for %s on line
%s:%s overrides line %s:%s.' % (expectation_line.name, |
771 self._shorten_filename(prev_expectation_line.filename), prev_exp
ectation_line.line_numbers, | 760 self._shorten_filename(prev_expectation_line.filename), prev_exp
ectation_line.line_numbers, |
772 self._shorten_filename(expectation_line.filename), expectation_l
ine.line_numbers)) | 761 self._shorten_filename(expectation_line.filename), expectation_l
ine.line_numbers)) |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1137 # If reconstitute_only_these is an empty list, we want to return ori
ginal_string. | 1126 # If reconstitute_only_these is an empty list, we want to return ori
ginal_string. |
1138 # So we need to compare reconstitute_only_these to None, not just ch
eck if it's falsey. | 1127 # So we need to compare reconstitute_only_these to None, not just ch
eck if it's falsey. |
1139 if reconstitute_only_these is None or expectation_line in reconstitu
te_only_these: | 1128 if reconstitute_only_these is None or expectation_line in reconstitu
te_only_these: |
1140 return expectation_line.to_string(test_configuration_converter) | 1129 return expectation_line.to_string(test_configuration_converter) |
1141 return expectation_line.original_string | 1130 return expectation_line.original_string |
1142 | 1131 |
1143 def nones_out(expectation_line): | 1132 def nones_out(expectation_line): |
1144 return expectation_line is not None | 1133 return expectation_line is not None |
1145 | 1134 |
1146 return "\n".join(filter(nones_out, map(serialize, expectation_lines))) | 1135 return "\n".join(filter(nones_out, map(serialize, expectation_lines))) |
OLD | NEW |