Title: [120230] trunk/Tools
Revision
120230
Author
[email protected]
Date
2012-06-13 11:50:08 -0700 (Wed, 13 Jun 2012)

Log Message

nrwt: preliminary cleanup before supporting cascading expectations files
https://bugs.webkit.org/show_bug.cgi?id=88942

Reviewed by Ojan Vafai.

This change just prepares the TestExpectations parser to get filenames
along with the expectations, and improves the warning messages so that
they contain the filenames along with the line numbers.

There should be no functional changes in this patch.

* Scripts/webkitpy/layout_tests/controllers/test_expectations_editor_unittest.py:
(TestExpectationEditorTests.make_parsed_expectation_lines):
* Scripts/webkitpy/layout_tests/models/test_expectations.py:
(TestExpectationParser.parse):
(TestExpectationParser.expectation_for_skipped_test):
(TestExpectationParser._tokenize):
(TestExpectationParser._tokenize_list):
(TestExpectationLine):
(TestExpectationsModel.__init__):
(TestExpectationsModel._already_seen_better_match):
(TestExpectations.__init__):
(TestExpectations._shorten_filename):
(TestExpectations._report_warnings):
(TestExpectations._add_skipped_tests):
* Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py:
(TestExpectationParserTests._tokenize):
(TestExpectationParserTests.test_tokenize_blank):
(TestExpectationParserTests.test_tokenize_missing_colon):
(TestExpectationParserTests.test_tokenize_extra_colon):
(TestExpectationParserTests.test_tokenize_empty_comment):
(TestExpectationParserTests.test_tokenize_comment):
(TestExpectationParserTests.test_tokenize_missing_equal):
(TestExpectationParserTests.test_tokenize_extra_equal):
(TestExpectationParserTests.test_tokenize_valid):
(TestExpectationParserTests.test_tokenize_valid_with_comment):
(TestExpectationParserTests.test_tokenize_valid_with_multiple_modifiers):
(TestExpectationParserTests.test_parse_empty_string):
(TestExpectationSerializerTests._tokenize):
(TestExpectationSerializerTests.assert_round_trip):
(TestExpectationSerializerTests.assert_list_round_trip):
* Scripts/webkitpy/tool/servers/gardeningserver.py:
(GardeningExpectationsUpdater.update_expectations):

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (120229 => 120230)


--- trunk/Tools/ChangeLog	2012-06-13 18:45:43 UTC (rev 120229)
+++ trunk/Tools/ChangeLog	2012-06-13 18:50:08 UTC (rev 120230)
@@ -1,3 +1,49 @@
+2012-06-13  Dirk Pranke  <[email protected]>
+
+        nrwt: preliminary cleanup before supporting cascading expectations files
+        https://bugs.webkit.org/show_bug.cgi?id=88942
+
+        Reviewed by Ojan Vafai.
+
+        This change just prepares the TestExpectations parser to get filenames
+        along with the expectations, and improves the warning messages so that
+        they contain the filenames along with the line numbers.
+
+        There should be no functional changes in this patch.
+
+        * Scripts/webkitpy/layout_tests/controllers/test_expectations_editor_unittest.py:
+        (TestExpectationEditorTests.make_parsed_expectation_lines):
+        * Scripts/webkitpy/layout_tests/models/test_expectations.py:
+        (TestExpectationParser.parse):
+        (TestExpectationParser.expectation_for_skipped_test):
+        (TestExpectationParser._tokenize):
+        (TestExpectationParser._tokenize_list):
+        (TestExpectationLine):
+        (TestExpectationsModel.__init__):
+        (TestExpectationsModel._already_seen_better_match):
+        (TestExpectations.__init__):
+        (TestExpectations._shorten_filename):
+        (TestExpectations._report_warnings):
+        (TestExpectations._add_skipped_tests):
+        * Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py:
+        (TestExpectationParserTests._tokenize):
+        (TestExpectationParserTests.test_tokenize_blank):
+        (TestExpectationParserTests.test_tokenize_missing_colon):
+        (TestExpectationParserTests.test_tokenize_extra_colon):
+        (TestExpectationParserTests.test_tokenize_empty_comment):
+        (TestExpectationParserTests.test_tokenize_comment):
+        (TestExpectationParserTests.test_tokenize_missing_equal):
+        (TestExpectationParserTests.test_tokenize_extra_equal):
+        (TestExpectationParserTests.test_tokenize_valid):
+        (TestExpectationParserTests.test_tokenize_valid_with_comment):
+        (TestExpectationParserTests.test_tokenize_valid_with_multiple_modifiers):
+        (TestExpectationParserTests.test_parse_empty_string):
+        (TestExpectationSerializerTests._tokenize):
+        (TestExpectationSerializerTests.assert_round_trip):
+        (TestExpectationSerializerTests.assert_list_round_trip):
+        * Scripts/webkitpy/tool/servers/gardeningserver.py:
+        (GardeningExpectationsUpdater.update_expectations):
+
 2012-06-13  Zan Dobersek  <[email protected]>
 
         [Gtk] Enable link prefetch support in the developer builds

Modified: trunk/Tools/Scripts/webkitpy/layout_tests/controllers/test_expectations_editor_unittest.py (120229 => 120230)


--- trunk/Tools/Scripts/webkitpy/layout_tests/controllers/test_expectations_editor_unittest.py	2012-06-13 18:45:43 UTC (rev 120229)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/controllers/test_expectations_editor_unittest.py	2012-06-13 18:50:08 UTC (rev 120230)
@@ -77,7 +77,7 @@
 
     def make_parsed_expectation_lines(self, in_string):
         parser = TestExpectationParser(self.test_port, self.full_test_list, allow_rebaseline_modifier=False)
-        expectation_lines = parser.parse(in_string)
+        expectation_lines = parser.parse('path', in_string)
         for expectation_line in expectation_lines:
             self.assertFalse(expectation_line.is_invalid())
         return expectation_lines

Modified: trunk/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py (120229 => 120230)


--- trunk/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py	2012-06-13 18:45:43 UTC (rev 120229)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py	2012-06-13 18:50:08 UTC (rev 120230)
@@ -225,8 +225,8 @@
         self._full_test_list = full_test_list
         self._allow_rebaseline_modifier = allow_rebaseline_modifier
 
-    def parse(self, expectations_string):
-        expectations = TestExpectationParser._tokenize_list(expectations_string)
+    def parse(self, filename, expectations_string):
+        expectations = TestExpectationParser._tokenize_list(filename, expectations_string)
         for expectation_line in expectations:
             self._parse_line(expectation_line)
         return expectations
@@ -236,6 +236,8 @@
         expectation_line.original_string = test_name
         expectation_line.modifiers = [TestExpectationParser.DUMMY_BUG_MODIFIER, TestExpectationParser.SKIP_MODIFIER]
         expectation_line.name = test_name
+        expectation_line.filename = '<Skipped file>'
+        expectation_line.line_number = 0
         expectation_line.expectations = [TestExpectationParser.PASS_EXPECTATION]
         self._parse_line(expectation_line)
         return expectation_line
@@ -337,7 +339,7 @@
             expectation_line.matching_tests.append(expectation_line.path)
 
     @classmethod
-    def _tokenize(cls, expectation_string, line_number=None):
+    def _tokenize(cls, filename, expectation_string, line_number):
         """Tokenizes a line from TestExpectations and returns an unparsed TestExpectationLine instance.
 
         The format of a test expectation line is:
@@ -350,6 +352,7 @@
         expectation_line = TestExpectationLine()
         expectation_line.original_string = expectation_string
         expectation_line.line_number = line_number
+        expectation_line.filename = filename
         comment_index = expectation_string.find("//")
         if comment_index == -1:
             comment_index = len(expectation_string)
@@ -376,13 +379,13 @@
         return expectation_line
 
     @classmethod
-    def _tokenize_list(cls, expectations_string):
+    def _tokenize_list(cls, filename, expectations_string):
         """Returns a list of TestExpectationLines, one for each line in expectations_string."""
         expectation_lines = []
         line_number = 0
         for line in expectations_string.split("\n"):
             line_number += 1
-            expectation_lines.append(cls._tokenize(line, line_number))
+            expectation_lines.append(cls._tokenize(filename, line, line_number))
         return expectation_lines
 
     @classmethod
@@ -392,7 +395,7 @@
         return [part.strip().lower() for part in space_separated_string.strip().split(' ')]
 
 
-class TestExpectationLine:
+class TestExpectationLine(object):
     """Represents a line in test expectations file."""
 
     def __init__(self):
@@ -432,7 +435,7 @@
 class TestExpectationsModel(object):
     """Represents relational store of all expectations and provides CRUD semantics to manage it."""
 
-    def __init__(self):
+    def __init__(self, shorten_filename=None):
         # Maps a test to its list of expectations.
         self._test_to_expectations = {}
 
@@ -454,6 +457,8 @@
         self._timeline_to_tests = self._dict_of_sets(TestExpectations.TIMELINES)
         self._result_type_to_tests = self._dict_of_sets(TestExpectations.RESULT_TYPES)
 
+        self._shorten_filename = shorten_filename or (lambda x: x)
+
     def _dict_of_sets(self, strings_to_constants):
         """Takes a dict of strings->constants and returns a dict mapping
         each constant to an empty set."""
@@ -634,20 +639,28 @@
         # to be warnings and return False".
 
         if prev_expectation_line.matching_configurations == expectation_line.matching_configurations:
-            expectation_line.warnings.append('Duplicate or ambiguous %s.' % expectation_source)
+            expectation_line.warnings.append('Duplicate or ambiguous entry for %s on lines %s:%d and %s:%d.' % (expectation_line.name,
+                self._shorten_filename(prev_expectation_line.filename), prev_expectation_line.line_number,
+                self._shorten_filename(expectation_line.filename), expectation_line.line_number))
             return True
 
         if prev_expectation_line.matching_configurations >= expectation_line.matching_configurations:
-            expectation_line.warnings.append('More specific entry on line %d overrides line %d' % (expectation_line.line_number, prev_expectation_line.line_number))
+            expectation_line.warnings.append('More specific entry for %s on line %s:%d overrides line %s:%d.' % (expectation_line.name,
+                self._shorten_filename(prev_expectation_line.filename), prev_expectation_line.line_number,
+                self._shorten_filename(expectation_line.filename), expectation_line.line_number))
             # FIXME: return False if we want more specific to win.
             return True
 
         if prev_expectation_line.matching_configurations <= expectation_line.matching_configurations:
-            expectation_line.warnings.append('More specific entry on line %d overrides line %d' % (prev_expectation_line.line_number, expectation_line.line_number))
+            expectation_line.warnings.append('More specific entry for %s on line %s:%d overrides line %s:%d.' % (expectation_line.name,
+                self._shorten_filename(expectation_line.filename), expectation_line.line_number,
+                self._shorten_filename(prev_expectation_line.filename), prev_expectation_line.line_number))
             return True
 
         if prev_expectation_line.matching_configurations & expectation_line.matching_configurations:
-            expectation_line.warnings.append('Entries on line %d and line %d match overlapping sets of configurations' % (prev_expectation_line.line_number, expectation_line.line_number))
+            expectation_line.warnings.append('Entries for %s on lines %s:%d and %s:%d match overlapping sets of configurations.' % (expectation_line.name,
+                self._shorten_filename(prev_expectation_line.filename), prev_expectation_line.line_number,
+                self._shorten_filename(expectation_line.filename), expectation_line.line_number))
             return True
 
         # Configuration sets are disjoint, then.
@@ -739,17 +752,17 @@
         self._full_test_list = tests
         self._test_config = port.test_configuration()
         self._is_lint_mode = is_lint_mode
-        self._model = TestExpectationsModel()
+        self._model = TestExpectationsModel(self._shorten_filename)
         self._parser = TestExpectationParser(port, tests, is_lint_mode)
         self._port = port
         self._skipped_tests_warnings = []
 
-        self._expectations = self._parser.parse(port.test_expectations())
+        self._expectations = self._parser.parse(port.path_to_test_expectations_file(), port.test_expectations())
         self._add_expectations(self._expectations, in_overrides=False)
 
         overrides = port.test_expectations_overrides()
         if overrides and include_overrides:
-            overrides_expectations = self._parser.parse(overrides)
+            overrides_expectations = self._parser.parse('overrides', overrides)
             self._add_expectations(overrides_expectations, in_overrides=True)
             self._expectations += overrides_expectations
 
@@ -826,18 +839,17 @@
     def is_rebaselining(self, test):
         return self._model.has_modifier(test, REBASELINE)
 
+    def _shorten_filename(self, filename):
+        if filename.startswith(self._port.path_from_webkit_base()):
+            return self._port.host.filesystem.relpath(filename, self._port.path_from_webkit_base())
+        return filename
+
     def _report_warnings(self):
         warnings = []
-        test_expectation_path = self._port.path_to_test_expectations_file()
-        if test_expectation_path.startswith(self._port.path_from_webkit_base()):
-            test_expectation_path = self._port.host.filesystem.relpath(test_expectation_path, self._port.path_from_webkit_base())
         for expectation in self._expectations:
             for warning in expectation.warnings:
-                warnings.append('%s:%d %s %s' % (test_expectation_path, expectation.line_number, warning, expectation.name if expectation.expectations else expectation.original_string))
+                warnings.append('%s:%d %s %s' % (self._shorten_filename(expectation.filename), expectation.line_number, warning, expectation.name if expectation.expectations else expectation.original_string))
 
-        for warning in self._skipped_tests_warnings:
-            warnings.append('%s%s' % (test_expectation_path, warning))
-
         if warnings:
             self._has_warnings = True
             if self._is_lint_mode:
@@ -893,9 +905,9 @@
     def _add_skipped_tests(self, tests_to_skip):
         if not tests_to_skip:
             return
-        for index, test in enumerate(self._expectations, start=1):
+        for test in self._expectations:
             if test.name and test.name in tests_to_skip:
-                self._skipped_tests_warnings.append(':%d %s is also in a Skipped file.' % (index, test.name))
+                test.warnings.append('%s:%d %s is also in a Skipped file.' % (test.filename, test.line_number, test.name))
 
         for test_name in tests_to_skip:
             expectation_line = self._parser.expectation_for_skipped_test(test_name)

Modified: trunk/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py (120229 => 120230)


--- trunk/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py	2012-06-13 18:45:43 UTC (rev 120229)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py	2012-06-13 18:50:08 UTC (rev 120230)
@@ -468,51 +468,54 @@
 
 
 class TestExpectationParserTests(unittest.TestCase):
+    def _tokenize(self, line):
+        return TestExpectationParser._tokenize('path', line, 0)
+
     def test_tokenize_blank(self):
-        expectation = TestExpectationParser._tokenize('')
+        expectation = self._tokenize('')
         self.assertEqual(expectation.comment, None)
         self.assertEqual(len(expectation.warnings), 0)
 
     def test_tokenize_missing_colon(self):
-        expectation = TestExpectationParser._tokenize('Qux.')
+        expectation = self._tokenize('Qux.')
         self.assertEqual(str(expectation.warnings), '["Missing a \':\'"]')
 
     def test_tokenize_extra_colon(self):
-        expectation = TestExpectationParser._tokenize('FOO : : bar')
+        expectation = self._tokenize('FOO : : bar')
         self.assertEqual(str(expectation.warnings), '["Extraneous \':\'"]')
 
     def test_tokenize_empty_comment(self):
-        expectation = TestExpectationParser._tokenize('//')
+        expectation = self._tokenize('//')
         self.assertEqual(expectation.comment, '')
         self.assertEqual(len(expectation.warnings), 0)
 
     def test_tokenize_comment(self):
-        expectation = TestExpectationParser._tokenize('//Qux.')
+        expectation = self._tokenize('//Qux.')
         self.assertEqual(expectation.comment, 'Qux.')
         self.assertEqual(len(expectation.warnings), 0)
 
     def test_tokenize_missing_equal(self):
-        expectation = TestExpectationParser._tokenize('FOO : bar')
+        expectation = self._tokenize('FOO : bar')
         self.assertEqual(str(expectation.warnings), "['Missing expectations\']")
 
     def test_tokenize_extra_equal(self):
-        expectation = TestExpectationParser._tokenize('FOO : bar = BAZ = Qux.')
+        expectation = self._tokenize('FOO : bar = BAZ = Qux.')
         self.assertEqual(str(expectation.warnings), '["Extraneous \'=\'"]')
 
     def test_tokenize_valid(self):
-        expectation = TestExpectationParser._tokenize('FOO : bar = BAZ')
+        expectation = self._tokenize('FOO : bar = BAZ')
         self.assertEqual(expectation.comment, None)
         self.assertEqual(len(expectation.warnings), 0)
 
     def test_tokenize_valid_with_comment(self):
-        expectation = TestExpectationParser._tokenize('FOO : bar = BAZ //Qux.')
+        expectation = self._tokenize('FOO : bar = BAZ //Qux.')
         self.assertEqual(expectation.comment, 'Qux.')
         self.assertEqual(str(expectation.modifiers), '[\'foo\']')
         self.assertEqual(str(expectation.expectations), '[\'baz\']')
         self.assertEqual(len(expectation.warnings), 0)
 
     def test_tokenize_valid_with_multiple_modifiers(self):
-        expectation = TestExpectationParser._tokenize('FOO1 FOO2 : bar = BAZ //Qux.')
+        expectation = self._tokenize('FOO1 FOO2 : bar = BAZ //Qux.')
         self.assertEqual(expectation.comment, 'Qux.')
         self.assertEqual(str(expectation.modifiers), '[\'foo1\', \'foo2\']')
         self.assertEqual(str(expectation.expectations), '[\'baz\']')
@@ -524,7 +527,7 @@
         test_port.test_exists = lambda test: True
         test_config = test_port.test_configuration()
         full_test_list = []
-        expectation_line = TestExpectationParser._tokenize('')
+        expectation_line = self._tokenize('')
         parser = TestExpectationParser(test_port, full_test_list, allow_rebaseline_modifier=False)
         parser._parse_line(expectation_line)
         self.assertFalse(expectation_line.is_invalid())
@@ -538,14 +541,17 @@
         self._serializer = TestExpectationSerializer(self._converter)
         unittest.TestCase.__init__(self, testFunc)
 
+    def _tokenize(self, line):
+        return TestExpectationParser._tokenize('path', line, 0)
+
     def assert_round_trip(self, in_string, expected_string=None):
-        expectation = TestExpectationParser._tokenize(in_string)
+        expectation = self._tokenize(in_string)
         if expected_string is None:
             expected_string = in_string
         self.assertEqual(expected_string, self._serializer.to_string(expectation))
 
     def assert_list_round_trip(self, in_string, expected_string=None):
-        expectations = TestExpectationParser._tokenize_list(in_string)
+        expectations = TestExpectationParser._tokenize_list('path', in_string)
         if expected_string is None:
             expected_string = in_string
         self.assertEqual(expected_string, TestExpectationSerializer.list_to_string(expectations, self._converter))

Modified: trunk/Tools/Scripts/webkitpy/tool/servers/gardeningserver.py (120229 => 120230)


--- trunk/Tools/Scripts/webkitpy/tool/servers/gardeningserver.py	2012-06-13 18:45:43 UTC (rev 120229)
+++ trunk/Tools/Scripts/webkitpy/tool/servers/gardeningserver.py	2012-06-13 18:50:08 UTC (rev 120230)
@@ -69,7 +69,7 @@
         return "BUG_NEW"
 
     def update_expectations(self, failure_info_list):
-        expectation_lines = self._parser.parse(self._tool.filesystem.read_text_file(self._path_to_test_expectations_file))
+        expectation_lines = self._parser.parse(self._path_to_test_expectations_file, self._tool.filesystem.read_text_file(self._path_to_test_expectations_file))
         editor = TestExpectationsEditor(expectation_lines, self)
         updated_expectation_lines = []
         # FIXME: Group failures by testName+failureTypeList.
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to