OLD | NEW |
---|---|
1 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Layout tests module that is necessary for the layout analyzer. | 5 """Layout tests module that is necessary for the layout analyzer. |
6 | 6 |
7 Layout tests are stored in Webkit SVN and LayoutTestCaseManager collects these | 7 Layout tests are stored in Webkit SVN and LayoutTestCaseManager collects these |
8 layout test cases (including description). | 8 layout test cases (including description). |
9 """ | 9 """ |
10 | 10 |
11 import copy | 11 import copy |
12 import csv | 12 import csv |
13 import locale | 13 import locale |
14 import pysvn | |
15 import re | 14 import re |
16 import sys | 15 import sys |
17 import urllib2 | 16 import urllib2 |
18 | 17 import pysvn |
dennis_jeffrey
2012/02/29 17:50:32
nit: add a blank line above this, to separate the
imasaki1
2012/03/02 19:12:07
Done.
| |
19 | 18 |
20 # Webkit SVN root location. | 19 # Webkit SVN root location. |
21 DEFAULT_LAYOUTTEST_LOCATION = ( | 20 DEFAULT_LAYOUTTEST_LOCATION = ( |
22 'http://svn.webkit.org/repository/webkit/trunk/LayoutTests/') | 21 'http://svn.webkit.org/repository/webkit/trunk/LayoutTests/') |
23 | 22 |
24 # When parsing the test HTML file and finding the test description, | 23 # When parsing the test HTML file and finding the test description, |
25 # this script tries to find the test description using sentences | 24 # this script tries to find the test description using sentences |
26 # starting with these keywords. This is adhoc but it is the only way | 25 # starting with these keywords. This is adhoc but it is the only way |
27 # since there is no standard for writing test description. | 26 # since there is no standard for writing test description. |
28 KEYWORDS_FOR_TEST_DESCRIPTION = ['This test', 'Tests that', 'Test '] | 27 KEYWORDS_FOR_TEST_DESCRIPTION = ['This test', 'Tests that', 'Test '] |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
62 if layouttest_root_path.startswith('http://'): | 61 if layouttest_root_path.startswith('http://'): |
63 name_map = self.GetLayoutTestNamesFromSVN(parent_location_list, | 62 name_map = self.GetLayoutTestNamesFromSVN(parent_location_list, |
64 layouttest_root_path, | 63 layouttest_root_path, |
65 recursion) | 64 recursion) |
66 else: | 65 else: |
67 # TODO(imasaki): support other forms such as CSV for reading test names. | 66 # TODO(imasaki): support other forms such as CSV for reading test names. |
68 pass | 67 pass |
69 self.name_map = copy.copy(name_map) | 68 self.name_map = copy.copy(name_map) |
70 if filter_names: | 69 if filter_names: |
71 # Filter names. | 70 # Filter names. |
72 for lt_name in name_map.keys(): | 71 for lt_name in name_map.iterkeys(): |
73 match = False | 72 match = False |
74 for filter_name in filter_names: | 73 for filter_name in filter_names: |
75 if re.search(filter_name, lt_name): | 74 if re.search(filter_name, lt_name): |
76 match = True | 75 match = True |
77 break | 76 break |
78 if not match: | 77 if not match: |
79 del self.name_map[lt_name] | 78 del self.name_map[lt_name] |
80 # We get description only for the filtered names. | 79 # We get description only for the filtered names. |
81 for lt_name in self.name_map.keys(): | 80 for lt_name in self.name_map.iterkeys(): |
82 self.name_map[lt_name] = LayoutTests.GetTestDescriptionFromSVN(lt_name) | 81 self.name_map[lt_name] = LayoutTests.GetTestDescriptionFromSVN(lt_name) |
83 | 82 |
84 @staticmethod | 83 @staticmethod |
85 def ExtractTestDescription(txt): | 84 def ExtractTestDescription(txt): |
86 """Extract the description description from test code in HTML. | 85 """Extract the description description from test code in HTML. |
87 | 86 |
88 Currently, we have 4 rules described in the code below. | 87 Currently, we have 4 rules described in the code below. |
89 (This example falls into rule 1): | 88 (This example falls into rule 1): |
90 <p> | 89 <p> |
91 This tests the intrinsic size of a video element is the default | 90 This tests the intrinsic size of a video element is the default |
(...skipping 11 matching lines...) Expand all Loading... | |
103 test description is not found. | 102 test description is not found. |
104 """ | 103 """ |
105 # (1) Try to find test description that contains keywords such as | 104 # (1) Try to find test description that contains keywords such as |
106 # 'test that' and surrounded by p tag. | 105 # 'test that' and surrounded by p tag. |
107 # This is the most common case. | 106 # This is the most common case. |
108 for keyword in KEYWORDS_FOR_TEST_DESCRIPTION: | 107 for keyword in KEYWORDS_FOR_TEST_DESCRIPTION: |
109 # Try to find <p> and </p>. | 108 # Try to find <p> and </p>. |
110 pattern = r'<p>(.*' + keyword + '.*)</p>' | 109 pattern = r'<p>(.*' + keyword + '.*)</p>' |
111 matches = re.search(pattern, txt) | 110 matches = re.search(pattern, txt) |
112 if matches is not None: | 111 if matches is not None: |
113 return matches.group(1).strip() | 112 return matches.group(1).strip() |
114 | 113 |
115 # (2) Try to find it by using more generic keywords such as 'PASS' etc. | 114 # (2) Try to find it by using more generic keywords such as 'PASS' etc. |
116 for keyword in KEYWORD_FOR_TEST_DESCRIPTION_FAIL_SAFE: | 115 for keyword in KEYWORD_FOR_TEST_DESCRIPTION_FAIL_SAFE: |
117 # Try to find new lines. | 116 # Try to find new lines. |
118 pattern = r'\n(.*' + keyword + '.*)\n' | 117 pattern = r'\n(.*' + keyword + '.*)\n' |
119 matches = re.search(pattern, txt) | 118 matches = re.search(pattern, txt) |
120 if matches is not None: | 119 if matches is not None: |
121 # Remove 'p' tag. | 120 # Remove 'p' tag. |
122 text = matches.group(1).strip() | 121 text = matches.group(1).strip() |
123 return text.replace('<p>', '').replace('</p>', '') | 122 return text.replace('<p>', '').replace('</p>', '') |
124 | 123 |
125 # (3) Try to find it by using HTML tag such as title. | 124 # (3) Try to find it by using HTML tag such as title. |
126 for tag in TAGS_FOR_TEST_DESCRIPTION: | 125 for tag in TAGS_FOR_TEST_DESCRIPTION: |
127 pattern = r'<' + tag + '>(.*)</' + tag + '>' | 126 pattern = r'<' + tag + '>(.*)</' + tag + '>' |
128 matches = re.search(pattern, txt) | 127 matches = re.search(pattern, txt) |
129 if matches is not None: | 128 if matches is not None: |
130 return matches.group(1).strip() | 129 return matches.group(1).strip() |
131 | 130 |
132 # (4) Try to find it by using test description and remove 'p' tag. | 131 # (4) Try to find it by using test description and remove 'p' tag. |
133 for keyword in KEYWORDS_FOR_TEST_DESCRIPTION: | 132 for keyword in KEYWORDS_FOR_TEST_DESCRIPTION: |
134 # Try to find <p> and </p>. | 133 # Try to find <p> and </p>. |
135 pattern = r'\n(.*' + keyword + '.*)\n' | 134 pattern = r'\n(.*' + keyword + '.*)\n' |
136 matches = re.search(pattern, txt) | 135 matches = re.search(pattern, txt) |
137 if matches is not None: | 136 if matches is not None: |
138 # Remove 'p' tag. | 137 # Remove 'p' tag. |
139 text = matches.group(1).strip() | 138 text = matches.group(1).strip() |
140 return text.replace('<p>', '').replace('</p>', '') | 139 return text.replace('<p>', '').replace('</p>', '') |
141 | 140 |
142 # (5) cannot find test description using existing rules. | 141 # (5) cannot find test description using existing rules. |
143 return 'UNKNOWN' | 142 return 'UNKNOWN' |
144 | 143 |
145 @staticmethod | 144 @staticmethod |
146 def GetLayoutTestNamesFromSVN(parent_location_list, | 145 def GetLayoutTestNamesFromSVN(parent_location_list, |
147 layouttest_root_path, recursion): | 146 layouttest_root_path, recursion): |
148 """Get LayoutTest names from Webkit SVN. | 147 """Get LayoutTest names from Webkit SVN. |
149 | 148 |
150 Args: | 149 Args: |
(...skipping 26 matching lines...) Expand all Loading... | |
177 return name_map | 176 return name_map |
178 | 177 |
179 @staticmethod | 178 @staticmethod |
180 def GetLayoutTestNamesFromCSV(csv_file_path): | 179 def GetLayoutTestNamesFromCSV(csv_file_path): |
181 """Get layout test names from CSV file. | 180 """Get layout test names from CSV file. |
182 | 181 |
183 Args: | 182 Args: |
184 csv_file_path: the path for the CSV file containing test names (including | 183 csv_file_path: the path for the CSV file containing test names (including |
185 regular expression patterns). The CSV file content has one column and | 184 regular expression patterns). The CSV file content has one column and |
186 each row contains a test name. | 185 each row contains a test name. |
186 | |
187 Returns: | |
188 a list of test names in string. | |
187 """ | 189 """ |
188 file_object = file(csv_file_path, 'r') | 190 file_object = file(csv_file_path, 'r') |
189 reader = csv.reader(file_object) | 191 reader = csv.reader(file_object) |
190 names = [row[0] for row in reader] | 192 names = [row[0] for row in reader] |
191 file_object.close() | 193 file_object.close() |
192 return names | 194 return names |
193 | 195 |
194 @staticmethod | 196 @staticmethod |
195 def GetParentDirectoryList(names): | 197 def GetParentDirectoryList(names): |
196 """Get parent directory list from test names. | 198 """Get parent directory list from test names. |
197 | 199 |
198 Args: | 200 Args: |
199 names: a list of test names. The test names also have path information as | 201 names: a list of test names. The test names also have path information as |
200 well (e.g., media/video-zoom.html). | 202 well (e.g., media/video-zoom.html). |
203 | |
204 Returns: | |
205 a list of parent directory for given test names. | |
dennis_jeffrey
2012/02/29 17:50:32
directory --> directories
dennis_jeffrey
2012/02/29 17:50:32
for given --> for the given
imasaki1
2012/03/02 19:12:07
Done.
imasaki1
2012/03/02 19:12:07
Done.
| |
201 """ | 206 """ |
202 pd_map = {} | 207 pd_map = {} |
203 for name in names: | 208 for name in names: |
204 p_dir = name[0:name.rfind('/') + 1] | 209 p_dir = name[0:name.rfind('/') + 1] |
205 pd_map[p_dir] = True | 210 pd_map[p_dir] = True |
206 return list(pd_map.iterkeys()) | 211 return list(pd_map.iterkeys()) |
207 | 212 |
208 def JoinWithTestExpectation(self, test_expectations): | 213 def JoinWithTestExpectation(self, test_expectations): |
209 """Join layout tests with the test expectation file using test name as key. | 214 """Join layout tests with the test expectation file using test name as key. |
210 | 215 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
255 try: | 260 try: |
256 resp = urllib2.urlopen(url) | 261 resp = urllib2.urlopen(url) |
257 except urllib2.HTTPError: | 262 except urllib2.HTTPError: |
258 # Some files with different languages cause this exception. | 263 # Some files with different languages cause this exception. |
259 # Return an empty description in this case. | 264 # Return an empty description in this case. |
260 return '' | 265 return '' |
261 if resp.code == 200: | 266 if resp.code == 200: |
262 return LayoutTests.ExtractTestDescription(resp.read()) | 267 return LayoutTests.ExtractTestDescription(resp.read()) |
263 raise urllib2.URLError( | 268 raise urllib2.URLError( |
264 'Fail to get layout test HTML file from %s.' % url) | 269 'Fail to get layout test HTML file from %s.' % url) |
OLD | NEW |