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