Changeset 91103 in webkit


Ignore:
Timestamp:
Jul 15, 2011 1:41:18 PM (13 years ago)
Author:
Dimitri Glazkov
Message:

Clean up test_expectations.py after refactorings.
https://bugs.webkit.org/show_bug.cgi?id=64620

  • Renamed all variables holding TestExpectationLine to expectation_line to avoid confusion with its sub-part, the actual expectation.
  • Renamed all references to options to modifier to eliminate dual terminology.
  • Made a bunch of parser constants and changed all callsites to use them.
  • Various other minor clean-ups.

Reviewed by Adam Barth.

  • Scripts/webkitpy/layout_tests/models/test_expectations.py: Cleaned up stuff.
  • Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py: Changed callsites after cleanup.
  • Scripts/webkitpy/style/checkers/test_expectations_unittest.py: Ditto.
Location:
trunk/Tools
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Tools/ChangeLog

    r91092 r91103  
     12011-07-15  Dimitri Glazkov  <dglazkov@chromium.org>
     2
     3        Clean up test_expectations.py after refactorings.
     4        https://bugs.webkit.org/show_bug.cgi?id=64620
     5
     6        * Renamed all variables holding TestExpectationLine to expectation_line to avoid confusion with
     7          its sub-part, the actual expectation.
     8        * Renamed all references to options to modifier to eliminate dual terminology.
     9        * Made a bunch of parser constants and changed all callsites to use them.
     10        * Various other minor clean-ups.
     11
     12        Reviewed by Adam Barth.
     13
     14        * Scripts/webkitpy/layout_tests/models/test_expectations.py: Cleaned up stuff.
     15        * Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py: Changed callsites after cleanup.
     16        * Scripts/webkitpy/style/checkers/test_expectations_unittest.py: Ditto.
     17
    1182011-07-15  Dimitri Glazkov  <dglazkov@chromium.org>
    219
  • trunk/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py

    r91092 r91103  
    166166    """Provides parsing facilities for lines in the test_expectation.txt file."""
    167167
     168    BUG_MODIFIER_PREFIX = 'bug'
     169    BUG_MODIFIER_REGEX = 'bug\d+'
     170    REBASELINE_MODIFIER = 'rebaseline'
     171    SKIP_MODIFIER = 'skip'
     172    SLOW_MODIFIER = 'slow'
     173    WONTFIX_MODIFIER = 'wontfix'
     174
     175    TIMEOUT_EXPECTATION = 'timeout'
     176
    168177    def __init__(self, port, test_config, full_test_list, allow_rebaseline_modifier):
    169178        self._port = port
     
    172181        self._allow_rebaseline_modifier = allow_rebaseline_modifier
    173182
    174     def parse(self, expectation):
    175         expectation.num_matches = self._check_options(self._matcher, expectation)
    176         if expectation.num_matches == ModifierMatcher.NO_MATCH:
     183    def parse(self, expectation_line):
     184        self._matcher.match(expectation_line)
     185        self._check_semantics(expectation_line)
     186
     187        if expectation_line.num_matches == ModifierMatcher.NO_MATCH:
    177188            return
    178189
    179         self._check_options_against_expectations(expectation)
    180 
    181         if self._check_path_does_not_exist(expectation):
     190        self._check_modifiers_against_expectations(expectation_line)
     191
     192        if self._check_path_does_not_exist(expectation_line):
    182193            return
    183194
    184195        if not self._full_test_list:
    185             expectation.matching_tests = [expectation.name]
    186         else:
    187             expectation.matching_tests = self._collect_matching_tests(expectation.name)
    188 
    189         expectation.parsed_modifiers = [modifier for modifier in expectation.modifiers if modifier in TestExpectations.MODIFIERS]
    190         self._parse_expectations(expectation)
     196            expectation_line.matching_tests = [expectation_line.name]
     197        else:
     198            expectation_line.matching_tests = self._collect_matching_tests(expectation_line.name)
     199
     200        expectation_line.parsed_modifiers = [modifier for modifier in expectation_line.modifiers if modifier in TestExpectations.MODIFIERS]
     201        self._parse_expectations(expectation_line)
    191202
    192203    def _parse_expectations(self, expectation_line):
     
    200211        expectation_line.parsed_expectations = result
    201212
    202     def _check_options(self, matcher, expectation):
    203         match_result = matcher.match(expectation)
    204         self._check_semantics(expectation)
    205         return match_result.num_matches
    206 
    207     def _check_semantics(self, expectation):
    208         has_wontfix = 'wontfix' in expectation.modifiers
     213    def _check_semantics(self, expectation_line):
     214        has_wontfix = self.WONTFIX_MODIFIER in expectation_line.modifiers
    209215        has_bug = False
    210         for opt in expectation.modifiers:
    211             if opt.startswith('bug'):
     216        for modifier in expectation_line.modifiers:
     217            if modifier.startswith(self.BUG_MODIFIER_PREFIX):
    212218                has_bug = True
    213                 if re.match('bug\d+', opt):
    214                     expectation.errors.append('BUG\d+ is not allowed, must be one of BUGCR\d+, BUGWK\d+, BUGV8_\d+, or a non-numeric bug identifier.')
     219                if re.match(self.BUG_MODIFIER_REGEX, modifier):
     220                    expectation_line.errors.append('BUG\d+ is not allowed, must be one of BUGCR\d+, BUGWK\d+, BUGV8_\d+, or a non-numeric bug identifier.')
    215221
    216222        if not has_bug and not has_wontfix:
    217             expectation.warnings.append('Test lacks BUG modifier.')
    218 
    219         if self._allow_rebaseline_modifier and 'rebaseline' in expectation.modifiers:
    220             expectation.errors.append('REBASELINE should only be used for running rebaseline.py. Cannot be checked in.')
    221 
    222     def _check_options_against_expectations(self, expectation):
    223         if 'slow' in expectation.modifiers and 'timeout' in expectation.expectations:
    224             expectation.errors.append('A test can not be both SLOW and TIMEOUT. If it times out indefinitely, then it should be just TIMEOUT.')
    225 
    226     def _check_path_does_not_exist(self, expectation):
     223            expectation_line.warnings.append('Test lacks BUG modifier.')
     224
     225        if self._allow_rebaseline_modifier and self.REBASELINE_MODIFIER in expectation_line.modifiers:
     226            expectation_line.errors.append('REBASELINE should only be used for running rebaseline.py. Cannot be checked in.')
     227
     228    def _check_modifiers_against_expectations(self, expectation_line):
     229        if self.SLOW_MODIFIER in expectation_line.modifiers and self.TIMEOUT_EXPECTATION in expectation_line.expectations:
     230            expectation_line.errors.append('A test can not be both SLOW and TIMEOUT. If it times out indefinitely, then it should be just TIMEOUT.')
     231
     232    def _check_path_does_not_exist(self, expectation_line):
    227233        # WebKit's way of skipping tests is to add a -disabled suffix.
    228234        # So we should consider the path existing if the path or the
    229235        # -disabled version exists.
    230         if (not self._port.test_exists(expectation.name)
    231             and not self._port.test_exists(expectation.name + '-disabled')):
     236        if (not self._port.test_exists(expectation_line.name)
     237            and not self._port.test_exists(expectation_line.name + '-disabled')):
    232238            # Log a warning here since you hit this case any
    233239            # time you update test_expectations.txt without syncing
    234240            # the LayoutTests directory
    235             expectation.warnings.append('Path does not exist.')
     241            expectation_line.warnings.append('Path does not exist.')
    236242            return True
    237243        return False
     
    270276
    271277        """
    272         expectation = TestExpectationLine()
     278        expectation_line = TestExpectationLine()
    273279        comment_index = expectation_string.find("//")
    274280        if comment_index == -1:
    275281            comment_index = len(expectation_string)
    276282        else:
    277             expectation.comment = expectation_string[comment_index + 2:]
     283            expectation_line.comment = expectation_string[comment_index + 2:]
    278284
    279285        remaining_string = re.sub(r"\s+", " ", expectation_string[:comment_index].strip())
    280286        if len(remaining_string) == 0:
    281             return expectation
     287            return expectation_line
    282288
    283289        parts = remaining_string.split(':')
    284290        if len(parts) != 2:
    285             expectation.errors.append("Missing a ':'" if len(parts) < 2 else "Extraneous ':'")
     291            expectation_line.errors.append("Missing a ':'" if len(parts) < 2 else "Extraneous ':'")
    286292        else:
    287293            test_and_expectation = parts[1].split('=')
    288294            if len(test_and_expectation) != 2:
    289                 expectation.errors.append("Missing expectations" if len(test_and_expectation) < 2 else "Extraneous '='")
    290 
    291         if expectation.is_malformed():
    292             expectation.comment = expectation_string
    293         else:
    294             expectation.modifiers = cls._split_space_separated(parts[0])
    295             expectation.name = test_and_expectation[0].strip()
    296             expectation.expectations = cls._split_space_separated(test_and_expectation[1])
    297 
    298         return expectation
     295                expectation_line.errors.append("Missing expectations" if len(test_and_expectation) < 2 else "Extraneous '='")
     296
     297        if expectation_line.is_malformed():
     298            expectation_line.comment = expectation_string
     299        else:
     300            expectation_line.modifiers = cls._split_space_separated(parts[0])
     301            expectation_line.name = test_and_expectation[0].strip()
     302            expectation_line.expectations = cls._split_space_separated(test_and_expectation[1])
     303
     304        return expectation_line
    299305
    300306    @classmethod
    301307    def tokenize_list(cls, expectations_string):
    302308        """Returns a list of TestExpectationLines, one for each line in expectations_string."""
    303         expectations = []
     309        expectation_lines = []
    304310        for line in expectations_string.split("\n"):
    305             expectations.append(cls.tokenize(line))
    306         return expectations
     311            expectation_lines.append(cls.tokenize(line))
     312        return expectation_lines
    307313
    308314    @classmethod
     
    346352        self._test_to_expectations = {}
    347353
    348         # Maps a test to its list of options (string values)
    349         self._test_to_options = {}
    350 
    351         # Maps a test to its list of modifiers: the constants associated with
    352         # the options minus any bug or platform strings
     354        # Maps a test to list of its modifiers (string values)
    353355        self._test_to_modifiers = {}
    354356
     
    395397        return self._timeline_to_tests[timeline]
    396398
    397     def get_options(self, test):
    398         """This returns the entire set of options for the given test
    399         (the modifiers plus the BUGXXXX identifier). This is used by the
    400         LTTF dashboard."""
    401         return self._test_to_options[test]
     399    def get_modifiers(self, test):
     400        """This returns modifiers for the given test (the modifiers plus the BUGXXXX identifier). This is used by the LTTF dashboard."""
     401        return self._test_to_modifiers[test]
    402402
    403403    def has_modifier(self, test, modifier):
     
    410410        return self._test_to_expectations[test]
    411411
    412     def add_tests(self, lineno, expectation, overrides_allowed):
     412    def add_tests(self, lineno, expectation_line, overrides_allowed):
    413413        """Returns a list of errors, encountered while matching modifiers."""
    414414
    415         if expectation.is_invalid():
     415        if expectation_line.is_invalid():
    416416            return
    417417
    418         for test in expectation.matching_tests:
    419             if self._already_seen_better_match(test, expectation, lineno, overrides_allowed):
     418        for test in expectation_line.matching_tests:
     419            if self._already_seen_better_match(test, expectation_line, lineno, overrides_allowed):
    420420                continue
    421421
    422             self._clear_expectations_for_test(test, expectation.name)
    423             self._test_list_paths[test] = (self._port.normalize_test_name(expectation.name), expectation.num_matches, lineno)
    424             self.add_test(test, expectation, overrides_allowed)
     422            self._clear_expectations_for_test(test, expectation_line.name)
     423            self._test_list_paths[test] = (self._port.normalize_test_name(expectation_line.name), expectation_line.num_matches, lineno)
     424            self.add_test(test, expectation_line, overrides_allowed)
    425425
    426426    def add_test(self, test, expectation_line, overrides_allowed):
     
    440440            self._expectation_to_tests[expectation].add(test)
    441441
    442         self._test_to_options[test] = expectation_line.modifiers
    443         self._test_to_modifiers[test] = set()
     442        self._test_to_modifiers[test] = expectation_line.modifiers
    444443        for modifier in expectation_line.parsed_modifiers:
    445444            mod_value = TestExpectations.MODIFIERS[modifier]
    446445            self._modifier_to_tests[mod_value].add(test)
    447             self._test_to_modifiers[test].add(mod_value)
    448 
    449         if 'wontfix' in expectation_line.parsed_modifiers:
     446
     447        if TestExpectationParser.WONTFIX_MODIFIER in expectation_line.parsed_modifiers:
    450448            self._timeline_to_tests[WONTFIX].add(test)
    451449        else:
    452450            self._timeline_to_tests[NOW].add(test)
    453451
    454         if 'skip' in expectation_line.parsed_modifiers:
     452        if TestExpectationParser.SKIP_MODIFIER in expectation_line.parsed_modifiers:
    455453            self._result_type_to_tests[SKIP].add(test)
    456454        elif expectation_line.parsed_expectations == set([PASS]):
     
    488486                set_of_tests.remove(test)
    489487
    490     def _already_seen_better_match(self, test, expectation, lineno, overrides_allowed):
     488    def _already_seen_better_match(self, test, expectation_line, lineno, overrides_allowed):
    491489        """Returns whether we've seen a better match already in the file.
    492490
    493         Returns True if we've already seen a expectation.name that matches more of the test
     491        Returns True if we've already seen a expectation_line.name that matches more of the test
    494492            than this path does
    495493        """
     
    500498
    501499        prev_base_path, prev_num_matches, prev_lineno = self._test_list_paths[test]
    502         base_path = self._port.normalize_test_name(expectation.name)
     500        base_path = self._port.normalize_test_name(expectation_line.name)
    503501
    504502        if len(prev_base_path) > len(base_path):
     
    533531        # to be warnings and return False".
    534532
    535         if prev_num_matches == expectation.num_matches:
    536             expectation.errors.append('Duplicate or ambiguous %s.' % expectation_source)
     533        if prev_num_matches == expectation_line.num_matches:
     534            expectation_line.errors.append('Duplicate or ambiguous %s.' % expectation_source)
    537535            return True
    538536
    539         if prev_num_matches < expectation.num_matches:
    540             expectation.errors.append('More specific entry on line %d overrides line %d' % (lineno, prev_lineno))
     537        if prev_num_matches < expectation_line.num_matches:
     538            expectation_line.errors.append('More specific entry on line %d overrides line %d' % (lineno, prev_lineno))
    541539            # FIXME: return False if we want more specific to win.
    542540            return True
    543541
    544         expectation.errors.append('More specific entry on line %d overrides line %d' % (prev_lineno, lineno))
     542        expectation_line.errors.append('More specific entry on line %d overrides line %d' % (prev_lineno, lineno))
    545543        return True
    546544
     
    557555      ...
    558556
    559     To add other options:
     557    To add modifiers:
    560558      SKIP : LayoutTests/fast/js/no-good.js = TIMEOUT PASS
    561559      DEBUG : LayoutTests/fast/js/no-good.js = TIMEOUT PASS
     
    611609    BUILD_TYPES = ('debug', 'release')
    612610
    613     MODIFIERS = {'skip': SKIP,
    614                  'wontfix': WONTFIX,
    615                  'slow': SLOW,
    616                  'rebaseline': REBASELINE,
     611    MODIFIERS = {TestExpectationParser.SKIP_MODIFIER: SKIP,
     612                 TestExpectationParser.WONTFIX_MODIFIER: WONTFIX,
     613                 TestExpectationParser.SLOW_MODIFIER: SLOW,
     614                 TestExpectationParser.REBASELINE_MODIFIER: REBASELINE,
    617615                 'none': NONE}
    618616
    619     TIMELINES = {'wontfix': WONTFIX,
     617    TIMELINES = {TestExpectationParser.WONTFIX_MODIFIER: WONTFIX,
    620618                 'now': NOW}
    621619
     
    699697
    700698    # FIXME: Change the callsites to use TestExpectationsModel and remove.
    701     def get_options(self, test):
    702         return self._model.get_options(test)
     699    def get_modifiers(self, test):
     700        return self._model.get_modifiers(test)
    703701
    704702    # FIXME: Change the callsites to use TestExpectationsModel and remove.
     
    783781        return TestExpectationSerializer.list_to_string(filter(without_rebaseline_modifier, self._expectations))
    784782
    785     def _add_to_all_expectations(self, test, options, expectations):
     783    def _add_to_all_expectations(self, test, modifiers, expectations):
    786784        if not test in self._all_expectations:
    787785            self._all_expectations[test] = []
    788786        self._all_expectations[test].append(
    789             ModifiersAndExpectations(options, expectations))
     787            ModifiersAndExpectations(modifiers, expectations))
    790788
    791789    def _add_expectations(self, expectation_list, overrides_allowed):
     
    805803
    806804class ModifierMatchResult(object):
    807     def __init__(self, options):
     805    def __init__(self, modifiers):
    808806        self.num_matches = ModifierMatcher.NO_MATCH
    809         self.options = options
    810         self.modifiers = []
     807        self._modifiers = modifiers
     808        self._matched_modifiers = []
    811809        self._matched_regexes = set()
    812810        self._matched_macros = set()
     
    863861    DUPLICATE_REGEXES_ALLOWED = ['bug\w+']
    864862
    865     # Magic value returned when the options don't match.
     863    # Magic value returned when the modifiers don't match.
    866864    NO_MATCH = -1
    867865
     
    892890                self._all_modifiers.add(modifier)
    893891
    894     def match(self, expectation):
     892    def match(self, expectation_line):
    895893        """Checks a expectation.modifiers against the config set in the constructor.
    896894        Options may be either actual modifier strings, "macro" strings
    897895        that get expanded to a list of modifiers, or strings that are allowed
    898         to be ignored. All of the options must be passed in in lower case.
     896        to be ignored. All of the modifiers must be passed in in lower case.
    899897
    900898        Returns the number of matching categories, or NO_MATCH (-1) if it
    901899        doesn't match or there were errors found. Matches are prioritized
    902900        by the number of matching categories, because the more specific
    903         the options list, the more categories will match.
    904 
    905         The results of the most recent match are available in the 'options',
    906         'modifiers', 'num_matches', 'errors', and 'warnings' properties.
     901        the modifier list, the more categories will match.
    907902        """
    908         old_error_count = len(expectation.errors)
    909         result = ModifierMatchResult(expectation.modifiers)
    910         self._parse(expectation, result)
    911         if old_error_count != len(expectation.errors):
    912             return result
    913         self._count_matches(result)
    914         return result
    915 
    916     def _parse(self, expectation, result):
     903        old_error_count = len(expectation_line.errors)
     904        result = ModifierMatchResult(expectation_line.modifiers)
     905        self._parse(expectation_line, result)
     906        if old_error_count == len(expectation_line.errors):
     907            self._count_matches(result)
     908        expectation_line.num_matches = result.num_matches
     909
     910    def _parse(self, expectation_line, result):
    917911        # FIXME: Should we warn about lines having every value in a category?
    918         for option in result.options:
    919             self._parse_one(expectation, option, result)
    920 
    921     def _parse_one(self, expectation, option, result):
    922         if option in self._all_modifiers:
    923             self._add_modifier(expectation, option, result)
    924         elif option in self.macros:
    925             self._expand_macro(expectation, option, result)
    926         elif not self._matches_any_regex(expectation, option, result):
    927             expectation.errors.append("Unrecognized option '%s'" % option)
    928 
    929     def _add_modifier(self, expectation, option, result):
    930         if option in result.modifiers:
    931             expectation.errors.append("More than one '%s'" % option)
    932         else:
    933             result.modifiers.append(option)
    934 
    935     def _expand_macro(self, expectation, macro, result):
     912        for modifier in result._modifiers:
     913            self._parse_one(expectation_line, modifier, result)
     914
     915    def _parse_one(self, expectation_line, modifier, result):
     916        if modifier in self._all_modifiers:
     917            self._add_modifier(expectation_line, modifier, result)
     918        elif modifier in self.macros:
     919            self._expand_macro(expectation_line, modifier, result)
     920        elif not self._matches_any_regex(expectation_line, modifier, result):
     921            expectation_line.errors.append("Unrecognized modifier '%s'" % modifier)
     922
     923    def _add_modifier(self, expectation_line, modifier, result):
     924        if modifier in result._matched_modifiers:
     925            expectation_line.errors.append("More than one '%s'" % modifier)
     926        else:
     927            result._matched_modifiers.append(modifier)
     928
     929    def _expand_macro(self, expectation_line, macro, result):
    936930        if macro in result._matched_macros:
    937             expectation.errors.append("More than one '%s'" % macro)
     931            expectation_line.errors.append("More than one '%s'" % macro)
    938932            return
    939933
    940934        mods = []
    941935        for modifier in self.macros[macro]:
    942             if modifier in result.options:
    943                 expectation.errors.append("Can't specify both modifier '%s' and macro '%s'" % (modifier, macro))
     936            if modifier in result._modifiers:
     937                expectation_line.errors.append("Can't specify both modifier '%s' and macro '%s'" % (modifier, macro))
    944938            else:
    945939                mods.append(modifier)
    946940        result._matched_macros.add(macro)
    947         result.modifiers.extend(mods)
    948 
    949     def _matches_any_regex(self, expectation, option, result):
     941        result._matched_modifiers.extend(mods)
     942
     943    def _matches_any_regex(self, expectation_line, modifier, result):
    950944        for regex_str, pattern in self.regexes_to_ignore.iteritems():
    951             if pattern.match(option):
    952                 self._handle_regex_match(expectation, regex_str, result)
     945            if pattern.match(modifier):
     946                self._handle_regex_match(expectation_line, regex_str, result)
    953947                return True
    954948        return False
    955949
    956     def _handle_regex_match(self, expectation, regex_str, result):
     950    def _handle_regex_match(self, expectation_line, regex_str, result):
    957951        if (regex_str in result._matched_regexes and
    958952            regex_str not in self.DUPLICATE_REGEXES_ALLOWED):
    959             expectation.errors.append("More than one option matching '%s'" %
     953            expectation_line.errors.append("More than one modifier matching '%s'" %
    960954                                 regex_str)
    961955        else:
     
    964958    def _count_matches(self, result):
    965959        """Returns the number of modifiers that match the test config."""
    966         categorized_modifiers = self._group_by_category(result.modifiers)
     960        categorized_modifiers = self._group_by_category(result._matched_modifiers)
    967961        result.num_matches = 0
    968962        for category, modifier in self.test_config.items():
  • trunk/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py

    r91092 r91103  
    152152        self.assert_exp('failures/expected/crash.html', IMAGE)
    153153
    154     def test_get_options(self):
    155         self.parse_exp(self.get_basic_expectations())
    156         self.assertEqual(self._exp.get_options(
     154    def test_get_modifiers(self):
     155        self.parse_exp(self.get_basic_expectations())
     156        self.assertEqual(self._exp.get_modifiers(
    157157                         self.get_test('passes/text.html')), [])
    158158
     
    195195        except ParseError, e:
    196196            self.assertTrue(e.fatal)
    197             exp_errors = [u"Line:1 Unrecognized option 'foo' failures/expected/text.html",
     197            exp_errors = [u"Line:1 Unrecognized modifier 'foo' failures/expected/text.html",
    198198                          u"Line:2 Missing expectations SKIP : failures/expected/image.html"]
    199199            self.assertEqual(str(e), '\n'.join(map(str, exp_errors)))
     
    397397        expectation = TestExpectationLine()
    398398        expectation.modifiers = modifiers
    399         match_result = matcher.match(expectation)
     399        matcher.match(expectation)
    400400        self.assertEqual(len(expectation.warnings), 0)
    401401        self.assertEqual(len(expectation.errors), num_errors)
    402         self.assertEqual(match_result.num_matches, expected_num_matches,
     402        self.assertEqual(expectation.num_matches, expected_num_matches,
    403403             'match(%s, %s) returned -> %d, expected %d' %
    404404             (modifiers, str(self.config.values()),
    405               match_result.num_matches, expected_num_matches))
     405              expectation.num_matches, expected_num_matches))
    406406
    407407    def test_bad_match_modifier(self):
     
    449449        self.match(['rebaseline', 'rebaseline'], num_errors=1)
    450450
    451     def test_unknown_option(self):
     451    def test_unknown_modifier(self):
    452452        self.match(['vms'], num_errors=1)
    453453
  • trunk/Tools/Scripts/webkitpy/style/checkers/test_expectations_unittest.py

    r91071 r91103  
    113113        self.assert_lines_lint(
    114114            ["INVALID-MODIFIER : passes/text.html = PASS"],
    115             "Unrecognized option 'invalid-modifier' "
     115            "Unrecognized modifier 'invalid-modifier' "
    116116            "passes/text.html  [test/expectations] [5]")
    117117        self.assert_lines_lint(
Note: See TracChangeset for help on using the changeset viewer.