Changeset 92147 in webkit


Ignore:
Timestamp:
Aug 1, 2011 3:22:27 PM (13 years ago)
Author:
Dimitri Glazkov
Message:

Teach TestExpectationSerializer about parsed expectations.
https://bugs.webkit.org/show_bug.cgi?id=65444

This is a bit largish in size, but the essentials are:

  • TestExpectationSerializer, given a parsed TestExpectationLine, can now spit out a pretty string.
  • We now store original content of the expectation line on TestExpectationLine.
  • Lots of tests.

Reviewed by Adam Barth.

  • Scripts/webkitpy/layout_tests/models/test_configuration.py: Fixed an issue where we didn't

populate macros correctly, also fixed an issue where we incorrectly returned an empty list
for all configurations.

  • Scripts/webkitpy/layout_tests/models/test_configuration_unittest.py: Added tests for those.
  • Scripts/webkitpy/layout_tests/models/test_expectations.py: Removed vestiges of code long gone,

refactored TestExpectationsSerializer to recognize and correctly serialize parsed TestExpectationLine instances,
changed to store and use TestExpectationLine.original_string.

  • Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py: Added tests.
Location:
trunk/Tools
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Tools/ChangeLog

    r92137 r92147  
     12011-08-01  Dimitri Glazkov  <dglazkov@chromium.org>
     2
     3        Teach TestExpectationSerializer about parsed expectations.
     4        https://bugs.webkit.org/show_bug.cgi?id=65444
     5
     6        This is a bit largish in size, but the essentials are:
     7        * TestExpectationSerializer, given a parsed TestExpectationLine, can now spit out a pretty string.
     8        * We now store original content of the expectation line on TestExpectationLine.
     9        * Lots of tests.
     10
     11        Reviewed by Adam Barth.
     12
     13        * Scripts/webkitpy/layout_tests/models/test_configuration.py: Fixed an issue where we didn't
     14            populate macros correctly, also fixed an issue where we incorrectly returned an empty list
     15            for all configurations.
     16        * Scripts/webkitpy/layout_tests/models/test_configuration_unittest.py: Added tests for those.
     17        * Scripts/webkitpy/layout_tests/models/test_expectations.py: Removed vestiges of code long gone,
     18            refactored TestExpectationsSerializer to recognize and correctly serialize parsed TestExpectationLine instances,
     19            changed to store and use TestExpectationLine.original_string.
     20        * Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py: Added tests.
     21
    1222011-08-01  Adam Barth  <abarth@webkit.org>
    223
  • trunk/Tools/Scripts/webkitpy/layout_tests/models/test_configuration.py

    r92136 r92147  
    7575                self.add_specifier(category, specifier)
    7676
     77        self.add_macros(macros)
     78
     79    def add_specifier(self, category, specifier):
     80        self._specifier_to_category[specifier] = category
     81
     82    def add_macros(self, macros):
    7783        if not macros:
    7884            return
     
    8086        for macro, specifier_list in macros.items():
    8187            self.add_specifier(self.category_for_specifier(specifier_list[0]), macro)
    82 
    83     def add_specifier(self, category, specifier):
    84         self._specifier_to_category[specifier] = category
    8588
    8689    @classmethod
     
    134137                    self._junk_specifier_combinations[specifier] = set_by_category
    135138
     139        self._specifier_sorter.add_macros(configuration_macros)
     140
     141    def specifier_sorter(self):
     142        return self._specifier_sorter
     143
    136144    def _expand_macros(self, specifier):
    137145        expanded_specifiers = self._configuration_macros.get(specifier)
     
    171179        # Easy out: if the set is all configurations, the modifier is empty.
    172180        if len(test_configuration_set) == len(self._all_test_configurations):
    173             return []
     181            return [[]]
    174182
    175183        # 1) Build a list of specifier sets, discarding specifiers that don't add value.
  • trunk/Tools/Scripts/webkitpy/layout_tests/models/test_configuration_unittest.py

    r92136 r92147  
    131131        self.assertEquals(sorter.category_for_specifier('renaissance'), 'architecture')
    132132
     133    def test_add_macros(self):
     134        sorter = SpecifierSorter(self._all_test_configurations)
     135        sorter.add_macros(MOCK_MACROS)
     136        self.assertEquals(sorter.category_for_specifier('mac'), 'version')
     137        self.assertEquals(sorter.category_for_specifier('win'), 'version')
     138        self.assertEquals(sorter.category_for_specifier('x86'), 'architecture')
     139
    133140    def test_category_priority(self):
    134141        sorter = SpecifierSorter(self._all_test_configurations)
     
    259266        converter = TestConfigurationConverter(self._all_test_configurations)
    260267
    261         self.assertEquals(converter.to_specifiers_list(set(self._all_test_configurations)), [])
     268        self.assertEquals(converter.to_specifiers_list(set(self._all_test_configurations)), [[]])
     269        self.assertEquals(converter.to_specifiers_list(set()), [])
    262270
    263271        configs_to_match = set([
     
    359367        ])
    360368        self.assertEquals(converter.to_specifiers_list(configs_to_match), [set(['win', 'mac', 'release', 'gpu'])])
     369
     370    def test_specifier_converter_access(self):
     371        specifier_sorter = TestConfigurationConverter(self._all_test_configurations, MOCK_MACROS).specifier_sorter()
     372        self.assertEquals(specifier_sorter.category_for_specifier('snowleopard'), 'version')
     373        self.assertEquals(specifier_sorter.category_for_specifier('mac'), 'version')
  • trunk/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py

    r92087 r92147  
    5353 SLOW, REBASELINE, MISSING, FLAKY, NOW, NONE) = range(16)
    5454
    55 # Test expectation file update action constants
    56 (NO_CHANGE, REMOVE_TEST, REMOVE_PLATFORM, ADD_PLATFORMS_EXCEPT_THIS) = range(4)
    57 
    5855
    5956def result_was_expected(result, expected_results, test_needs_rebaselining, test_is_skipped):
     
    125122class TestExpectationSerializer:
    126123    """Provides means of serializing TestExpectationLine instances."""
     124    def __init__(self, test_configuration_converter):
     125        self._test_configuration_converter = test_configuration_converter
     126        self._parsed_expectation_to_string = dict([[parsed_expectation, expectation_string] for expectation_string, parsed_expectation in TestExpectations.EXPECTATIONS.items()])
     127
     128    def to_string(self, expectation_line):
     129        if expectation_line.is_malformed():
     130            return expectation_line.original_string or ''
     131
     132        if expectation_line.name is None:
     133            return '' if expectation_line.comment is None else "//%s" % expectation_line.comment
     134
     135        if expectation_line.parsed_bug_modifier:
     136            specifiers_list = self._test_configuration_converter.to_specifiers_list(expectation_line.matching_configurations)
     137            result = []
     138            for specifiers in specifiers_list:
     139                modifiers = self._parsed_modifier_string(expectation_line, specifiers)
     140                expectations = self._parsed_expectations_string(expectation_line)
     141                result.append(self._format_result(modifiers, expectation_line.name, expectations, expectation_line.comment))
     142            return "\n".join(result)
     143
     144        return self._format_result(" ".join(expectation_line.modifiers), expectation_line.name, " ".join(expectation_line.expectations), expectation_line.comment)
     145
     146    def _parsed_expectations_string(self, expectation_line):
     147        result = []
     148        for index in TestExpectations.EXPECTATION_ORDER:
     149            if index in expectation_line.parsed_expectations:
     150                result.append(self._parsed_expectation_to_string[index])
     151        return ' '.join(result)
     152
     153    def _parsed_modifier_string(self, expectation_line, specifiers):
     154        result = []
     155        if expectation_line.parsed_bug_modifier:
     156            result.append(expectation_line.parsed_bug_modifier)
     157        result.extend(expectation_line.parsed_modifiers)
     158        result.extend(self._test_configuration_converter.specifier_sorter().sort_specifiers(specifiers))
     159        return ' '.join(result)
     160
    127161    @classmethod
    128     def to_string(cls, expectation):
    129         result = []
    130         if expectation.is_malformed():
    131             result.append(expectation.comment)
    132         else:
    133             if expectation.name is None:
    134                 if expectation.comment is not None:
    135                     result.append('//')
    136                     result.append(expectation.comment)
    137             else:
    138                 result.append("%s : %s = %s" % (" ".join(expectation.modifiers).upper(), expectation.name, " ".join(expectation.expectations).upper()))
    139                 if expectation.comment is not None:
    140                     result.append(" //%s" % (expectation.comment))
    141 
    142         return ''.join(result)
     162    def _format_result(cls, modifiers, name, expectations, comment):
     163        result = "%s : %s = %s" % (modifiers.upper(), name, expectations.upper())
     164        if comment is not None:
     165            result += " //%s" % comment
     166        return result
    143167
    144168    @classmethod
    145     def list_to_string(cls, expectations):
    146         return "\n".join([TestExpectationSerializer.to_string(expectation) for expectation in expectations])
     169    def list_to_string(cls, expectations, test_configuration_converter):
     170        serializer = cls(test_configuration_converter)
     171        return "\n".join([serializer.to_string(expectation) for expectation in expectations])
    147172
    148173
     
    265290        """
    266291        expectation_line = TestExpectationLine()
     292        expectation_line.original_string = expectation_string
    267293        expectation_line.line_number = line_number
    268294        comment_index = expectation_string.find("//")
     
    284310                expectation_line.errors.append("Missing expectations" if len(test_and_expectation) < 2 else "Extraneous '='")
    285311
    286         if expectation_line.is_malformed():
    287             expectation_line.comment = expectation_string
    288         else:
     312        if not expectation_line.is_malformed():
    289313            expectation_line.modifiers = cls._split_space_separated(parts[0])
    290314            expectation_line.name = test_and_expectation[0].strip()
     
    315339    def __init__(self):
    316340        """Initializes a blank-line equivalent of an expectation."""
     341        self.original_string = None
    317342        self.line_number = None
    318343        self.name = None
     
    655680        self._model = TestExpectationsModel()
    656681        self._parser = TestExpectationParser(port, tests, is_lint_mode)
     682        self._test_configuration_converter = TestConfigurationConverter(port.all_test_configurations(), port.configuration_specifier_macros())
    657683
    658684        self._expectations = TestExpectationParser.tokenize_list(expectations)
     
    737763        for expectation in self._expectations:
    738764            for error in expectation.errors:
    739                 errors.append("Line:%s %s %s" % (expectation.line_number, error, expectation.name if expectation.expectations else expectation.comment))
     765                errors.append("Line:%s %s %s" % (expectation.line_number, error, expectation.name if expectation.expectations else expectation.original_string))
    740766            for warning in expectation.warnings:
    741                 warnings.append("Line:%s %s %s" % (expectation.line_number, warning, expectation.name if expectation.expectations else expectation.comment))
     767                warnings.append("Line:%s %s %s" % (expectation.line_number, warning, expectation.name if expectation.expectations else expectation.original_string))
    742768
    743769        if len(errors) or len(warnings):
     
    770796            return not (not expectation.is_malformed() and expectation.name in tests and "rebaseline" in expectation.modifiers)
    771797
    772         return TestExpectationSerializer.list_to_string(filter(without_rebaseline_modifier, self._expectations))
     798        return TestExpectationSerializer.list_to_string(filter(without_rebaseline_modifier, self._expectations), self._test_configuration_converter)
    773799
    774800    def _add_expectations(self, expectation_list, overrides_allowed):
  • trunk/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py

    r91884 r92147  
    3232from webkitpy.layout_tests import port
    3333from webkitpy.layout_tests.port import base
     34from webkitpy.layout_tests.models.test_configuration import *
    3435from webkitpy.layout_tests.models.test_expectations import *
    3536
     
    389390        expectation = TestExpectationParser.tokenize('Qux.')
    390391        self.assertEqual(expectation.is_malformed(), True)
    391         self.assertEqual(expectation.comment, 'Qux.')
    392392        self.assertEqual(str(expectation.errors), '["Missing a \':\'"]')
    393393
     
    395395        expectation = TestExpectationParser.tokenize('FOO : : bar')
    396396        self.assertEqual(expectation.is_malformed(), True)
    397         self.assertEqual(expectation.comment, 'FOO : : bar')
    398397        self.assertEqual(str(expectation.errors), '["Extraneous \':\'"]')
    399398
     
    413412        expectation = TestExpectationParser.tokenize('FOO : bar')
    414413        self.assertEqual(expectation.is_malformed(), True)
    415         self.assertEqual(expectation.comment, 'FOO : bar')
    416414        self.assertEqual(str(expectation.errors), "['Missing expectations\']")
    417415
     
    419417        expectation = TestExpectationParser.tokenize('FOO : bar = BAZ = Qux.')
    420418        self.assertEqual(expectation.is_malformed(), True)
    421         self.assertEqual(expectation.comment, 'FOO : bar = BAZ = Qux.')
    422419        self.assertEqual(str(expectation.errors), '["Extraneous \'=\'"]')
    423420
     
    456453
    457454class TestExpectationSerializerTests(unittest.TestCase):
     455    def __init__(self, testFunc):
     456        test_port = port.get('test-win-xp', None)
     457        self._serializer = TestExpectationSerializer(TestConfigurationConverter(test_port.all_test_configurations(), test_port.configuration_specifier_macros()))
     458        unittest.TestCase.__init__(self, testFunc)
     459
    458460    def assert_round_trip(self, in_string, expected_string=None):
    459461        expectation = TestExpectationParser.tokenize(in_string)
    460462        if expected_string is None:
    461463            expected_string = in_string
    462         self.assertEqual(expected_string, TestExpectationSerializer.to_string(expectation))
     464        self.assertEqual(expected_string, self._serializer.to_string(expectation))
    463465
    464466    def assert_list_round_trip(self, in_string, expected_string=None):
     
    466468        if expected_string is None:
    467469            expected_string = in_string
    468         self.assertEqual(expected_string, TestExpectationSerializer.list_to_string(expectations))
    469 
    470     def assert_to_string(self, expectation, expected_string):
    471         self.assertEqual(TestExpectationSerializer.to_string(expectation), expected_string)
    472 
    473     def test_string_serializer(self):
     470        self.assertEqual(expected_string, TestExpectationSerializer.list_to_string(expectations, SpecifierSorter()))
     471
     472    def test_unparsed_to_string(self):
    474473        expectation = TestExpectationLine()
    475         self.assert_to_string(expectation, '')
     474
     475        self.assertEqual(self._serializer.to_string(expectation), '')
    476476        expectation.comment = 'Qux.'
    477         self.assert_to_string(expectation, '//Qux.')
     477        self.assertEqual(self._serializer.to_string(expectation), '//Qux.')
    478478        expectation.name = 'bar'
    479         self.assert_to_string(expectation, ' : bar =  //Qux.')
     479        self.assertEqual(self._serializer.to_string(expectation), ' : bar =  //Qux.')
    480480        expectation.modifiers = ['foo']
    481         self.assert_to_string(expectation, 'FOO : bar =  //Qux.')
     481        self.assertEqual(self._serializer.to_string(expectation), 'FOO : bar =  //Qux.')
    482482        expectation.expectations = ['bAz']
    483         self.assert_to_string(expectation, 'FOO : bar = BAZ //Qux.')
     483        self.assertEqual(self._serializer.to_string(expectation), 'FOO : bar = BAZ //Qux.')
    484484        expectation.expectations = ['bAz1', 'baZ2']
    485         self.assert_to_string(expectation, 'FOO : bar = BAZ1 BAZ2 //Qux.')
     485        self.assertEqual(self._serializer.to_string(expectation), 'FOO : bar = BAZ1 BAZ2 //Qux.')
    486486        expectation.modifiers = ['foo1', 'foO2']
    487         self.assert_to_string(expectation, 'FOO1 FOO2 : bar = BAZ1 BAZ2 //Qux.')
     487        self.assertEqual(self._serializer.to_string(expectation), 'FOO1 FOO2 : bar = BAZ1 BAZ2 //Qux.')
    488488        expectation.errors.append('Oh the horror.')
    489         self.assert_to_string(expectation, 'Qux.')
     489        self.assertEqual(self._serializer.to_string(expectation), '')
     490        expectation.original_string = 'Yes it is!'
     491        self.assertEqual(self._serializer.to_string(expectation), 'Yes it is!')
     492
     493    def test_parsed_to_string(self):
     494        expectation_line = TestExpectationLine()
     495        expectation_line.parsed_bug_modifier = 'BUGX'
     496        expectation_line.name = 'test/name/for/realz.html'
     497        expectation_line.parsed_expectations = set([IMAGE])
     498        self.assertEqual(self._serializer.to_string(expectation_line), '')
     499        expectation_line.matching_configurations = set([TestConfiguration(None, 'xp', 'x86', 'release', 'cpu')])
     500        self.assertEqual(self._serializer.to_string(expectation_line), 'BUGX XP RELEASE CPU : test/name/for/realz.html = IMAGE')
     501        expectation_line.matching_configurations = set([TestConfiguration(None, 'xp', 'x86', 'release', 'cpu'), TestConfiguration(None, 'xp', 'x86', 'release', 'gpu')])
     502        self.assertEqual(self._serializer.to_string(expectation_line), 'BUGX XP RELEASE : test/name/for/realz.html = IMAGE')
     503        expectation_line.matching_configurations = set([TestConfiguration(None, 'xp', 'x86', 'release', 'cpu'), TestConfiguration(None, 'xp', 'x86', 'debug', 'gpu')])
     504        self.assertEqual(self._serializer.to_string(expectation_line), 'BUGX XP RELEASE CPU : test/name/for/realz.html = IMAGE\nBUGX XP DEBUG GPU : test/name/for/realz.html = IMAGE')
     505
     506    def test_parsed_expectations_string(self):
     507        expectation_line = TestExpectationLine()
     508        expectation_line.parsed_expectations = set([])
     509        self.assertEqual(self._serializer._parsed_expectations_string(expectation_line), '')
     510        expectation_line.parsed_expectations = set([IMAGE_PLUS_TEXT])
     511        self.assertEqual(self._serializer._parsed_expectations_string(expectation_line), 'image+text')
     512        expectation_line.parsed_expectations = set([PASS, FAIL])
     513        self.assertEqual(self._serializer._parsed_expectations_string(expectation_line), 'pass fail')
     514        expectation_line.parsed_expectations = set([FAIL, PASS])
     515        self.assertEqual(self._serializer._parsed_expectations_string(expectation_line), 'pass fail')
     516
     517    def test_parsed_modifier_string(self):
     518        expectation_line = TestExpectationLine()
     519        expectation_line.parsed_bug_modifier = 'garden-o-matic'
     520        expectation_line.parsed_modifiers = ['for', 'the']
     521        self.assertEqual(self._serializer._parsed_modifier_string(expectation_line, []), 'garden-o-matic for the')
     522        self.assertEqual(self._serializer._parsed_modifier_string(expectation_line, ['win']), 'garden-o-matic for the win')
     523        expectation_line.parsed_bug_modifier = ''
     524        expectation_line.parsed_modifiers = []
     525        self.assertEqual(self._serializer._parsed_modifier_string(expectation_line, []), '')
     526        self.assertEqual(self._serializer._parsed_modifier_string(expectation_line, ['win']), 'win')
     527
     528    def test_format_result(self):
     529        self.assertEqual(TestExpectationSerializer._format_result('modifiers', 'name', 'expectations', 'comment'), 'MODIFIERS : name = EXPECTATIONS //comment')
     530        self.assertEqual(TestExpectationSerializer._format_result('modifiers', 'name', 'expectations', None), 'MODIFIERS : name = EXPECTATIONS')
    490531
    491532    def test_string_roundtrip(self):
Note: See TracChangeset for help on using the changeset viewer.