Commit 5ad02862 authored by qyearsley's avatar qyearsley Committed by Commit bot

Move tokenize_line method from TestExpectationParser to TestExpectationLine.

In this CL:
 - Move tokenize_line class method to TestExpectationLine, as suggested by FIXME.
 - Make tokenize_line non-protected, since it's used in another class, and
   would be useful in other modules, e.g. update_w3c_test_expectations.
 - Move class attributes that tokenize_line depends on.
 - Other changes suggested by linter (e.g. shorten long variable name).

This is a preliminary refactoring CL which is intended to make it easier to re-use tokenize_line in update_w3c_test_expectations.py, in order to make it easier to fix http://crbug.com/647395.

BUG=647395

Review-Url: https://codereview.chromium.org/2341173002
Cr-Commit-Position: refs/heads/master@{#419013}
parent 1201616d
...@@ -105,7 +105,7 @@ class TestExpectationParser(object): ...@@ -105,7 +105,7 @@ class TestExpectationParser(object):
line_number = 0 line_number = 0
for line in expectations_string.split("\n"): for line in expectations_string.split("\n"):
line_number += 1 line_number += 1
test_expectation = self._tokenize_line(filename, line, line_number) test_expectation = TestExpectationLine.tokenize_line(filename, line, line_number)
self._parse_line(test_expectation) self._parse_line(test_expectation)
expectation_lines.append(test_expectation) expectation_lines.append(test_expectation)
return expectation_lines return expectation_lines
...@@ -128,7 +128,7 @@ class TestExpectationParser(object): ...@@ -128,7 +128,7 @@ class TestExpectationParser(object):
_log.warning('The following test %s from the Skipped list doesn\'t exist', test_name) _log.warning('The following test %s from the Skipped list doesn\'t exist', test_name)
expectation_line = self._create_expectation_line(test_name, [TestExpectationParser.PASS_EXPECTATION], '<Skipped file>') expectation_line = self._create_expectation_line(test_name, [TestExpectationParser.PASS_EXPECTATION], '<Skipped file>')
expectation_line.expectations = [TestExpectationParser.SKIP_MODIFIER, TestExpectationParser.WONTFIX_MODIFIER] expectation_line.expectations = [TestExpectationParser.SKIP_MODIFIER, TestExpectationParser.WONTFIX_MODIFIER]
expectation_line.is_skipped_outside_expectations_file = True expectation_line.is_extra_skipped_test = True
self._parse_line(expectation_line) self._parse_line(expectation_line)
return expectation_line return expectation_line
...@@ -221,6 +221,62 @@ class TestExpectationParser(object): ...@@ -221,6 +221,62 @@ class TestExpectationParser(object):
if expectation_line.path in self._all_tests: if expectation_line.path in self._all_tests:
expectation_line.matching_tests.append(expectation_line.path) expectation_line.matching_tests.append(expectation_line.path)
class TestExpectationLine(object):
"""Represents a line in test expectations file."""
def __init__(self):
"""Initializes a blank-line equivalent of an expectation."""
self.original_string = None
self.filename = None # this is the path to the expectations file for this line
self.line_numbers = "0"
self.name = None # this is the path in the line itself
self.path = None # this is the normpath of self.name
self.bugs = []
self.specifiers = []
self.parsed_specifiers = []
self.matching_configurations = set()
self.expectations = []
self.parsed_expectations = set()
self.comment = None
self.matching_tests = []
self.warnings = []
self.is_extra_skipped_test = False
def __str__(self):
return "TestExpectationLine{name=%s, matching_configurations=%s, original_string=%s}" % (
self.name, self.matching_configurations, self.original_string)
def __eq__(self, other):
return (self.original_string == other.original_string
and self.filename == other.filename
and self.line_numbers == other.line_numbers
and self.name == other.name
and self.path == other.path
and self.bugs == other.bugs
and self.specifiers == other.specifiers
and self.parsed_specifiers == other.parsed_specifiers
and self.matching_configurations == other.matching_configurations
and self.expectations == other.expectations
and self.parsed_expectations == other.parsed_expectations
and self.comment == other.comment
and self.matching_tests == other.matching_tests
and self.warnings == other.warnings
and self.is_extra_skipped_test == other.is_extra_skipped_test)
def is_invalid(self):
return bool(self.warnings and self.warnings != [TestExpectationParser.MISSING_BUG_WARNING])
def is_flaky(self):
return len(self.parsed_expectations) > 1
def is_comment(self):
return bool(re.match(r"^\s*#.*$", self.original_string))
def is_whitespace(self):
return not self.original_string.strip()
# FIXME: Update the original specifiers and remove this once the old syntax is gone. # FIXME: Update the original specifiers and remove this once the old syntax is gone.
_configuration_tokens_list = [ _configuration_tokens_list = [
'Mac', 'Mac10.9', 'Mac10.10', 'Mac10.11', 'Retina', 'Mac', 'Mac10.9', 'Mac10.10', 'Mac10.11', 'Retina',
...@@ -250,13 +306,12 @@ class TestExpectationParser(object): ...@@ -250,13 +306,12 @@ class TestExpectationParser(object):
'WontFix': 'WONTFIX', 'WontFix': 'WONTFIX',
} }
_inverted_expectation_tokens = dict( inverted_expectation_tokens = dict(
[(value, name) for name, value in _expectation_tokens.iteritems()] + [(value, name) for name, value in _expectation_tokens.iteritems()] +
[('TEXT', 'Failure'), ('IMAGE', 'Failure'), ('IMAGE+TEXT', 'Failure'), ('AUDIO', 'Failure')]) [('TEXT', 'Failure'), ('IMAGE', 'Failure'), ('IMAGE+TEXT', 'Failure'), ('AUDIO', 'Failure')])
# FIXME: Seems like these should be classmethods on TestExpectationLine instead of TestExpectationParser.
@classmethod @classmethod
def _tokenize_line(cls, filename, expectation_string, line_number): def tokenize_line(cls, filename, expectation_string, line_number):
"""Tokenizes a line from TestExpectations and returns an unparsed TestExpectationLine instance using the old format. """Tokenizes a line from TestExpectations and returns an unparsed TestExpectationLine instance using the old format.
The new format for a test expectation line is: The new format for a test expectation line is:
...@@ -387,66 +442,6 @@ class TestExpectationParser(object): ...@@ -387,66 +442,6 @@ class TestExpectationParser(object):
expectation_line.warnings = warnings expectation_line.warnings = warnings
return expectation_line return expectation_line
@classmethod
def _split_space_separated(cls, space_separated_string):
"""Splits a space-separated string into an array."""
return [part.strip() for part in space_separated_string.strip().split(' ')]
class TestExpectationLine(object):
"""Represents a line in test expectations file."""
def __init__(self):
"""Initializes a blank-line equivalent of an expectation."""
self.original_string = None
self.filename = None # this is the path to the expectations file for this line
self.line_numbers = "0"
self.name = None # this is the path in the line itself
self.path = None # this is the normpath of self.name
self.bugs = []
self.specifiers = []
self.parsed_specifiers = []
self.matching_configurations = set()
self.expectations = []
self.parsed_expectations = set()
self.comment = None
self.matching_tests = []
self.warnings = []
self.is_skipped_outside_expectations_file = False
def __str__(self):
return "TestExpectationLine{name=%s, matching_configurations=%s, original_string=%s}" % (
self.name, self.matching_configurations, self.original_string)
def __eq__(self, other):
return (self.original_string == other.original_string
and self.filename == other.filename
and self.line_numbers == other.line_numbers
and self.name == other.name
and self.path == other.path
and self.bugs == other.bugs
and self.specifiers == other.specifiers
and self.parsed_specifiers == other.parsed_specifiers
and self.matching_configurations == other.matching_configurations
and self.expectations == other.expectations
and self.parsed_expectations == other.parsed_expectations
and self.comment == other.comment
and self.matching_tests == other.matching_tests
and self.warnings == other.warnings
and self.is_skipped_outside_expectations_file == other.is_skipped_outside_expectations_file)
def is_invalid(self):
return bool(self.warnings and self.warnings != [TestExpectationParser.MISSING_BUG_WARNING])
def is_flaky(self):
return len(self.parsed_expectations) > 1
def is_comment(self):
return bool(re.match(r"^\s*#.*$", self.original_string))
def is_whitespace(self):
return not self.original_string.strip()
@staticmethod @staticmethod
def create_passing_expectation(test): def create_passing_expectation(test):
expectation_line = TestExpectationLine() expectation_line = TestExpectationLine()
...@@ -484,8 +479,7 @@ class TestExpectationLine(object): ...@@ -484,8 +479,7 @@ class TestExpectationLine(object):
result.matching_configurations = set(line1.matching_configurations) | set(line2.matching_configurations) result.matching_configurations = set(line1.matching_configurations) | set(line2.matching_configurations)
result.matching_tests = list(list(set(line1.matching_tests) | set(line2.matching_tests))) result.matching_tests = list(list(set(line1.matching_tests) | set(line2.matching_tests)))
result.warnings = list(set(line1.warnings) | set(line2.warnings)) result.warnings = list(set(line1.warnings) | set(line2.warnings))
result.is_skipped_outside_expectations_file = (line1.is_skipped_outside_expectations_file or result.is_extra_skipped_test = line1.is_extra_skipped_test or line2.is_extra_skipped_test
line2.is_skipped_outside_expectations_file)
return result return result
def to_string(self, test_configuration_converter=None, include_specifiers=True, def to_string(self, test_configuration_converter=None, include_specifiers=True,
...@@ -538,19 +532,19 @@ class TestExpectationLine(object): ...@@ -538,19 +532,19 @@ class TestExpectationLine(object):
return ['Slow'] return ['Slow']
return expectations return expectations
@staticmethod @classmethod
def _format_line(bugs, specifiers, name, expectations, comment, include_specifiers=True, def _format_line(cls, bugs, specifiers, name, expectations, comment, include_specifiers=True,
include_expectations=True, include_comment=True): include_expectations=True, include_comment=True):
new_specifiers = [] new_specifiers = []
new_expectations = [] new_expectations = []
for specifier in specifiers: for specifier in specifiers:
# FIXME: Make this all work with the mixed-cased specifiers (e.g. WontFix, Slow, etc). # FIXME: Make this all work with the mixed-cased specifiers (e.g. WontFix, Slow, etc).
specifier = specifier.upper() specifier = specifier.upper()
new_specifiers.append(TestExpectationParser._inverted_configuration_tokens.get(specifier, specifier)) new_specifiers.append(cls._inverted_configuration_tokens.get(specifier, specifier))
for expectation in expectations: for expectation in expectations:
expectation = expectation.upper() expectation = expectation.upper()
new_expectations.append(TestExpectationParser._inverted_expectation_tokens.get(expectation, expectation)) new_expectations.append(cls.inverted_expectation_tokens.get(expectation, expectation))
result = '' result = ''
if include_specifiers and (bugs or new_specifiers): if include_specifiers and (bugs or new_specifiers):
...@@ -671,7 +665,7 @@ class TestExpectationsModel(object): ...@@ -671,7 +665,7 @@ class TestExpectationsModel(object):
"""Returns the expectations for the given test as an uppercase string. """Returns the expectations for the given test as an uppercase string.
If there are no expectations for the test, then "PASS" is returned. If there are no expectations for the test, then "PASS" is returned.
""" """
if self.get_expectation_line(test).is_skipped_outside_expectations_file: if self.get_expectation_line(test).is_extra_skipped_test:
return 'NOTRUN' return 'NOTRUN'
expectations = self.get_expectations(test) expectations = self.get_expectations(test)
......
...@@ -463,7 +463,7 @@ class ExpectationSyntaxTests(Base): ...@@ -463,7 +463,7 @@ class ExpectationSyntaxTests(Base):
expectations = expectations or [] expectations = expectations or []
warnings = warnings or [] warnings = warnings or []
line_number = '1' line_number = '1'
expectation_line = TestExpectationParser._tokenize_line(filename, line, line_number) expectation_line = TestExpectationLine.tokenize_line(filename, line, line_number)
self.assertEqual(expectation_line.warnings, warnings) self.assertEqual(expectation_line.warnings, warnings)
self.assertEqual(expectation_line.name, name) self.assertEqual(expectation_line.name, name)
self.assertEqual(expectation_line.filename, filename) self.assertEqual(expectation_line.filename, filename)
...@@ -904,7 +904,7 @@ class TestExpectationSerializationTests(unittest.TestCase): ...@@ -904,7 +904,7 @@ class TestExpectationSerializationTests(unittest.TestCase):
unittest.TestCase.__init__(self, testFunc) unittest.TestCase.__init__(self, testFunc)
def _tokenize(self, line): def _tokenize(self, line):
return TestExpectationParser._tokenize_line('path', line, 0) return TestExpectationLine.tokenize_line('path', line, 0)
def assert_round_trip(self, in_string, expected_string=None): def assert_round_trip(self, in_string, expected_string=None):
expectation = self._tokenize(in_string) expectation = self._tokenize(in_string)
......
...@@ -28,14 +28,11 @@ ...@@ -28,14 +28,11 @@
from webkitpy.layout_tests.models import test_expectations from webkitpy.layout_tests.models import test_expectations
from webkitpy.layout_tests.models.test_expectations import TestExpectations, TestExpectationLine
from webkitpy.common.net.layouttestresults import LayoutTestResults from webkitpy.common.net.layouttestresults import LayoutTestResults
TestExpectations = test_expectations.TestExpectations
TestExpectationParser = test_expectations.TestExpectationParser
class BuildBotPrinter(object): class BuildBotPrinter(object):
# This output is parsed by buildbots and must only be changed in coordination with buildbot scripts (see webkit.org's # This output is parsed by buildbots and must only be changed in coordination with buildbot scripts (see webkit.org's
# Tools/BuildSlaveSupport/build.webkit.org-config/master.cfg: RunWebKitTests._parseNewRunWebKitTestsOutput # Tools/BuildSlaveSupport/build.webkit.org-config/master.cfg: RunWebKitTests._parseNewRunWebKitTestsOutput
...@@ -145,7 +142,7 @@ class BuildBotPrinter(object): ...@@ -145,7 +142,7 @@ class BuildBotPrinter(object):
actual = result.actual_results().split(" ") actual = result.actual_results().split(" ")
expected = result.expected_results().split(" ") expected = result.expected_results().split(" ")
# FIXME: clean this up once the old syntax is gone # FIXME: clean this up once the old syntax is gone
new_expectations_list = [TestExpectationParser._inverted_expectation_tokens[exp] new_expectations_list = [TestExpectationLine.inverted_expectation_tokens[exp]
for exp in list(set(actual) | set(expected))] for exp in list(set(actual) | set(expected))]
self._print(" %s [ %s ]" % (test, " ".join(new_expectations_list))) self._print(" %s [ %s ]" % (test, " ".join(new_expectations_list)))
self._print("") self._print("")
...@@ -161,7 +158,7 @@ class BuildBotPrinter(object): ...@@ -161,7 +158,7 @@ class BuildBotPrinter(object):
result = test_results.result_for_test(test) result = test_results.result_for_test(test)
actual = result.actual_results().split(" ") actual = result.actual_results().split(" ")
expected = result.expected_results().split(" ") expected = result.expected_results().split(" ")
new_expectations_list = [TestExpectationParser._inverted_expectation_tokens[exp] for exp in actual] new_expectations_list = [TestExpectationLine.inverted_expectation_tokens[exp] for exp in actual]
self._print(" %s [ %s ]" % (test, " ".join(new_expectations_list))) self._print(" %s [ %s ]" % (test, " ".join(new_expectations_list)))
self._print("") self._print("")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment