Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(262)

Unified Diff: media/tools/layout_tests/test_expectations.py

Issue 10986008: Switch to using WebKit's test expecation parser. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use no-reply. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/tools/layout_tests/test_expectations.py
diff --git a/media/tools/layout_tests/test_expectations.py b/media/tools/layout_tests/test_expectations.py
index ce09101d309c5f453fe99c9ea56bf7067c616478..d8f5948552b8cc9603131b525f98912dddc5a081 100644
--- a/media/tools/layout_tests/test_expectations.py
+++ b/media/tools/layout_tests/test_expectations.py
@@ -4,9 +4,10 @@
"""A module to analyze test expectations for Webkit layout tests."""
-import re
import urllib2
+from webkitpy.layout_tests.models.test_expectations import *
+
# Default Webkit SVN location for chromium test expectation file.
# TODO(imasaki): support multiple test expectations files.
DEFAULT_TEST_EXPECTATION_LOCATION = (
@@ -14,8 +15,7 @@ DEFAULT_TEST_EXPECTATION_LOCATION = (
'LayoutTests/platform/chromium/TestExpectations')
# The following is from test expectation syntax. The detail can be found in
-# http://www.chromium.org/developers/testing/
-# webkit-layout-tests#TOC-Test-Expectations
+# http://www.chromium.org/developers/testing/webkit-layout-tests#TOC-Test-Expectations
# <decision> ::== [SKIP] [WONTFIX] [SLOW]
DECISION_NAMES = ['SKIP', 'WONTFIX', 'SLOW']
# <config> ::== RELEASE | DEBUG
@@ -28,36 +28,32 @@ KNOWN_TE_KEYWORDS = DECISION_NAMES + CONFIG_NAMES
class TestExpectations(object):
"""A class to model the content of test expectation file for analysis.
- The raw test expectation file can be found in
- |DEFAULT_TEST_EXPECTATION_LOCATION|.
- It is necessary to parse this file and store meaningful information for
- the analysis (joining with existing layout tests using a test name).
- Instance variable |all_test_expectation_info| is used.
- A test name such as 'media/video-source-type.html' is used for the key
- to store information. However, a test name can appear multiple times in
- the test expectation file. So, the map should keep all the occurrence
- information. For example, the current test expectation file has the following
- two entries:
- BUGWK58587 LINUX DEBUG GPU : media/video-zoom.html = IMAGE
- BUGCR86714 MAC GPU : media/video-zoom.html = CRASH IMAGE
- In this case, all_test_expectation_info['media/video-zoom.html'] will have
- a list with two elements, each of which is the map of the test expectation
- information.
+ This class retrieves the TestExpectations file via HTTP from WebKit and uses
+ the WebKit layout test processor to process each line.
+
+ The resulting dictionary is stored in |all_test_expectation_info| and looks
+ like:
+
+ {'<test name>': [{'<modifier0>': True, '<modifier1>': True, ...,
+ 'Platforms: ['<platform0>', ... ], 'Bugs': ['....']}]}
+
+ Duplicate keys are merged (though technically they shouldn't exist).
+
+ Example:
+ crbug.com/145590 [ Android ] \
+ platform/chromium/media/video-frame-size-change.html [ Timeout ]
+ webkit.org/b/84724 [ SnowLeopard ] \
+ platform/chromium/media/video-frame-size-change.html \
+ [ ImageOnlyFailure Pass ]
+
+ {'platform/chromium/media/video-frame-size-change.html': [{'IMAGE': True,
+ 'Bugs': ['BUGWK84724', 'BUGCR145590'], 'Comments': '',
+ 'Platforms': ['SNOWLEOPARD', 'ANDROID'], 'TIMEOUT': True, 'PASS': True}]}
"""
def __init__(self, url=DEFAULT_TEST_EXPECTATION_LOCATION):
"""Read the test expectation file from the specified URL and parse it.
- All parsed information is stored into instance variable
- |all_test_expectation_info|, which is a dictionary mapping a string test
- name to a list of dictionaries containing test expectation entry
- information. An example of such dictionary:
- {'media/video-zoom.html': [{'LINUX': True, 'DEBUG': True ....},
- {'MAC': True, 'GPU': True ....}]
- which is produced from the lines:
- BUGCR86714 MAC GPU : media/video-zoom.html = CRASH IMAGE
- BUGCR86714 LINUX DEBUG : media/video-zoom.html = IMAGE
-
Args:
url: A URL string for the test expectation file.
@@ -69,91 +65,57 @@ class TestExpectations(object):
if resp.code != 200:
raise NameError('Test expectation file does not exist in %s' % url)
# Start parsing each line.
- comments = ''
for line in resp.read().split('\n'):
- if line.startswith('//'):
- # Comments can be multiple lines.
- comments += line.replace('//', '')
- elif not line:
- comments = ''
+ line = line.strip()
+ # Skip comments.
+ if line.startswith('#'):
+ continue
+ testname, te_info = self.ParseLine(line)
+ if not testname or not te_info:
+ continue
+ if testname in self.all_test_expectation_info:
+ # Merge keys if entry already exists.
+ for k in te_info.keys():
+ if (isinstance(te_info[k], list) and
+ k in self.all_test_expectation_info[testname]):
+ self.all_test_expectation_info[testname][0][k] += te_info[k]
+ else:
+ self.all_test_expectation_info[testname][0][k] = te_info[k]
else:
- test_expectation_info = self.ParseLine(line, comments)
- testname = TestExpectations.ExtractTestOrDirectoryName(line)
- if not testname in self.all_test_expectation_info:
- self.all_test_expectation_info[testname] = []
- # This is a list for multiple entries.
- self.all_test_expectation_info[testname].append(test_expectation_info)
-
- @staticmethod
- def ExtractTestOrDirectoryName(line):
- """Extract either a test name or a directory name from each line.
-
- Please note the name in the test expectation entry can be test name or
- directory: Such examples are:
- BUGWK43668 SKIP : media/track/ = TIMEOUT
-
- Args:
- line: a line in the test expectation file.
-
- Returns:
- a test name or directory name string. Returns '' if no match.
-
- Raises:
- ValueError when there is no test name match.
- """
- # First try to find test name ending with .html.
- matches = re.search(r':\s+(\S+(.html|.svg))', line)
- # Next try to find directory name.
- if matches:
- return matches.group(1)
- matches = re.search(r':\s+(\S+)', line)
- if matches:
- return matches.group(1)
- else:
- raise ValueError('test or dictionary name cannot be found in the line')
+ self.all_test_expectation_info[testname] = [te_info]
@staticmethod
- def ParseLine(line, comment_prefix):
- """Parse each line in test expectation and update test expectation info.
-
- This function checks for each entry from |ALL_TE_KEYWORDS| in the current
- line and stores it in the test expectation info map if found. Comment
- and bug information is also stored in the map.
-
- Args:
- line: a line in the test expectation file. For example,
- "BUGCR86714 MAC GPU : media/video-zoom.html = CRASH IMAGE"
- comment_prefix: comments from the test expectation file occurring just
- before the current line being parsed.
+ def ParseLine(line):
+ """Parses the provided line using WebKit's TextExpecations parser.
Returns:
- a dictionary containing test expectation info, including comment and bug
- info.
+ Tuple of test name, test expectations dictionary. See class documentation
+ for the format of the dictionary
"""
test_expectation_info = {}
- # Store comments.
- inline_comments = ''
- if '//' in line:
- inline_comments = line[line.rindex('//') + 2:]
- # Remove the inline comments to avoid the case where keywords are in
- # inline comments.
- line = line[0:line.rindex('//')]
- for name in KNOWN_TE_KEYWORDS:
- if name in line:
- test_expectation_info[name] = True
- test_expectation_info['Comments'] = comment_prefix + inline_comments
- # Store bug informations.
- bugs = re.findall(r'BUG\w+', line)
- if bugs:
- test_expectation_info['Bugs'] = bugs
- # Platforms should be the first tags to the left of the " : " after the BUG
- # information and known keywords have been removed.
- test_expectation_info['Platforms'] = [
- x for x in line.split(' : ')[0].split(' ') if x and x not in bugs and
- x not in KNOWN_TE_KEYWORDS]
- # Test expectations should be all the keywords to the right of " = "
- test_expectation = [x for x in line.split(' = ')[-1].split(' ') if x]
- # Dump keywords into test expectations dictionary.
- for name in test_expectation_info['Platforms'] + test_expectation:
- test_expectation_info[name] = True
- return test_expectation_info
+ parsed = TestExpectationParser._tokenize_line('TestExpectations', line, 0)
+ if parsed.is_invalid():
+ return None, None
+
+ test_expectation_info['Comments'] = parsed.comment or ''
+
+ # Split the modifiers dictionary into the format we want.
+ remaining_modifiers = list(parsed.modifiers)
+ test_expectation_info['Bugs'] = []
+ for m in parsed.modifiers:
+ if m.startswith('BUG'):
+ test_expectation_info['Bugs'].append(m)
+ remaining_modifiers.remove(m)
+ elif m in KNOWN_TE_KEYWORDS:
+ test_expectation_info[m] = True
+ remaining_modifiers.remove(m)
+
+ # The modifiers left over should all be platform names.
+ test_expectation_info['Platforms'] = list(remaining_modifiers)
+
+ # Shovel the expectations and modifiers in as "<key>: True" entries. Ugly,
+ # but required by the rest of the pipeline for parsing.
+ for m in parsed.expectations + remaining_modifiers:
+ test_expectation_info[m] = True
+
+ return parsed.name, test_expectation_info
« no previous file with comments | « media/tools/layout_tests/layouttest_analyzer_helpers.py ('k') | media/tools/layout_tests/test_expectations_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698