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

Side by Side Diff: third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py

Issue 2633933002: Directly use TestImporter in DepsUpdater instead of invoking script. (Closed)
Patch Set: imported -> external Created 3 years, 11 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 unified diff | Download patch
OLDNEW
1 # Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. 1 # Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
2 # 2 #
3 # Redistribution and use in source and binary forms, with or without 3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions 4 # modification, are permitted provided that the following conditions
5 # are met: 5 # are met:
6 # 6 #
7 # 1. Redistributions of source code must retain the above 7 # 1. Redistributions of source code must retain the above
8 # copyright notice, this list of conditions and the following 8 # copyright notice, this list of conditions and the following
9 # disclaimer. 9 # disclaimer.
10 # 2. Redistributions in binary form must reproduce the above 10 # 2. Redistributions in binary form must reproduce the above
11 # copyright notice, this list of conditions and the following 11 # copyright notice, this list of conditions and the following
12 # disclaimer in the documentation and/or other materials 12 # disclaimer in the documentation and/or other materials
13 # provided with the distribution. 13 # provided with the distribution.
14 # 14 #
15 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY 15 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
16 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE 18 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
19 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 19 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
20 # OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 # OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 23 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
24 # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 24 # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
25 # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 # SUCH DAMAGE. 26 # SUCH DAMAGE.
27 27
28 """This script imports a directory of W3C tests into Blink. 28 """Logic for converting and copying files from a W3C repo.
29 29
30 This script takes a source repository directory, which it searches for files, 30 This module is responsible for modifying and copying a subset of the tests from
31 then converts and copies files over to a destination directory. 31 a local W3C repository source directory into a destination directory.
32
33 Rules for importing:
34
35 * By default, only reference tests and JS tests are imported, (because pixel
36 tests take longer to run). This can be overridden with the --all flag.
37
38 * By default, if test files by the same name already exist in the destination
39 directory, they are overwritten. This is because this script is used to
40 refresh files periodically. This can be overridden with the --no-overwrite fl ag.
41
42 * All files are converted to work in Blink:
43 1. All CSS properties requiring the -webkit- vendor prefix are prefixed
44 (the list of what needs prefixes is read from Source/core/css/CSSPropert ies.in).
45 2. Each reftest has its own copy of its reference file following
46 the naming conventions new-run-webkit-tests expects.
47 3. If a reference files lives outside the directory of the test that
48 uses it, it is checked for paths to support files as it will be
49 imported into a different relative position to the test file
50 (in the same directory).
51 4. Any tags with the class "instructions" have style="display:none" added
52 to them. Some w3c tests contain instructions to manual testers which we
53 want to strip out (the test result parser only recognizes pure testharne ss.js
54 output and not those instructions).
55
56 * Upon completion, script outputs the total number tests imported,
57 broken down by test type.
58
59 * Also upon completion, if we are not importing the files in place, each
60 directory where files are imported will have a w3c-import.log file written wi th
61 a timestamp, the list of CSS properties used that require prefixes, the list
62 of imported files, and guidance for future test modification and maintenance.
63 On subsequent imports, this file is read to determine if files have been
64 removed in the newer changesets. The script removes these files accordingly.
65 """ 32 """
66 33
67 import logging 34 import logging
68 import mimetypes 35 import mimetypes
36 import os
69 import re 37 import re
70 import optparse
71 import os
72 import sys
73 38
74 from webkitpy.common.host import Host
75 from webkitpy.common.webkit_finder import WebKitFinder 39 from webkitpy.common.webkit_finder import WebKitFinder
76 from webkitpy.layout_tests.models.test_expectations import TestExpectationParser 40 from webkitpy.layout_tests.models.test_expectations import TestExpectationParser
77 from webkitpy.w3c.test_parser import TestParser 41 from webkitpy.w3c.test_parser import TestParser
78 from webkitpy.w3c.test_converter import convert_for_webkit 42 from webkitpy.w3c.test_converter import convert_for_webkit
79 43
80
81 # Maximum length of import path starting from top of source repository. 44 # Maximum length of import path starting from top of source repository.
82 # This limit is here because the Windows builders cannot create paths that are 45 # This limit is here because the Windows builders cannot create paths that are
83 # longer than the Windows max path length (260). See http://crbug.com/609871. 46 # longer than the Windows max path length (260). See http://crbug.com/609871.
84 MAX_PATH_LENGTH = 125 47 MAX_PATH_LENGTH = 125
85 48
86
87 _log = logging.getLogger(__name__) 49 _log = logging.getLogger(__name__)
88 50
89 51
90 def main(_argv, _stdout, _stderr):
91 options, args = parse_args()
92 host = Host()
93 source_repo_path = host.filesystem.normpath(os.path.abspath(args[0]))
94
95 if not host.filesystem.exists(source_repo_path):
96 sys.exit('Repository directory %s not found!' % source_repo_path)
97
98 configure_logging()
99 test_importer = TestImporter(host, source_repo_path, options)
100 test_importer.do_import()
101
102
103 def configure_logging():
104 class LogHandler(logging.StreamHandler):
105
106 def format(self, record):
107 if record.levelno > logging.INFO:
108 return "%s: %s" % (record.levelname, record.getMessage())
109 return record.getMessage()
110
111 logger = logging.getLogger()
112 logger.setLevel(logging.INFO)
113 handler = LogHandler()
114 handler.setLevel(logging.INFO)
115 logger.addHandler(handler)
116 return handler
117
118
119 def parse_args():
120 parser = optparse.OptionParser(usage='usage: %prog [options] source_repo_pat h')
121 parser.add_option('-n', '--no-overwrite', dest='overwrite', action='store_fa lse', default=True,
122 help=('Flag to prevent duplicate test files from overwriti ng existing tests. '
123 'By default, they will be overwritten.'))
124 parser.add_option('-a', '--all', action='store_true', default=False,
125 help=('Import all tests including reftests, JS tests, and manual/pixel tests. '
126 'By default, only reftests and JS tests are imported .'))
127 parser.add_option('-d', '--dest-dir', dest='destination', default='w3c',
128 help=('Import into a specified directory relative to the L ayoutTests root. '
129 'By default, files are imported under LayoutTests/w3 c.'))
130 parser.add_option('--ignore-expectations', action='store_true', default=Fals e,
131 help='Ignore the W3CImportExpectations file and import eve rything.')
132 parser.add_option('--dry-run', action='store_true', default=False,
133 help='Dry run only (don\'t actually write any results).')
134
135 options, args = parser.parse_args()
136 if len(args) != 1:
137 parser.error('Incorrect number of arguments; source repo path is require d.')
138 return options, args
139
140
141 class TestImporter(object): 52 class TestImporter(object):
142 53
143 def __init__(self, host, source_repo_path, options): 54 def __init__(self, host, source_repo_path, dest_dir_name='external'):
55 """Initializes variables to prepare for copying and converting files.
56
57 Args:
58 source_repo_path: Path to the local checkout of a WPT
59 """
144 self.host = host 60 self.host = host
61
62 assert self.host.filesystem.exists(source_repo_path)
145 self.source_repo_path = source_repo_path 63 self.source_repo_path = source_repo_path
146 self.options = options 64 self.dest_dir_name = dest_dir_name
147 65
148 self.filesystem = self.host.filesystem 66 self.filesystem = self.host.filesystem
149 self.webkit_finder = WebKitFinder(self.filesystem) 67 self.webkit_finder = WebKitFinder(self.filesystem)
150 self._webkit_root = self.webkit_finder.webkit_base() 68 self._webkit_root = self.webkit_finder.webkit_base()
151 self.layout_tests_dir = self.webkit_finder.path_from_webkit_base('Layout Tests') 69 self.layout_tests_dir = self.webkit_finder.path_from_webkit_base('Layout Tests')
152 self.destination_directory = self.filesystem.normpath( 70 self.destination_directory = self.filesystem.normpath(
153 self.filesystem.join( 71 self.filesystem.join(
154 self.layout_tests_dir, 72 self.layout_tests_dir,
155 options.destination, 73 dest_dir_name,
156 self.filesystem.basename(self.source_repo_path))) 74 self.filesystem.basename(self.source_repo_path)))
157 self.import_in_place = (self.source_repo_path == self.destination_direct ory) 75 self.import_in_place = (self.source_repo_path == self.destination_direct ory)
158 self.dir_above_repo = self.filesystem.dirname(self.source_repo_path) 76 self.dir_above_repo = self.filesystem.dirname(self.source_repo_path)
159 77
160 self.import_list = [] 78 self.import_list = []
161 79
162 # This is just a FYI list of CSS properties that still need to be prefix ed, 80 # This is just a FYI list of CSS properties that still need to be prefix ed,
163 # which may be output after importing. 81 # which may be output after importing.
164 self._prefixed_properties = {} 82 self._prefixed_properties = {}
165 83
(...skipping 24 matching lines...) Expand all
190 # We copy all files in 'support', including HTML without metadata. 108 # We copy all files in 'support', including HTML without metadata.
191 # See: http://testthewebforward.org/docs/test-format-guidelines.html #support-files 109 # See: http://testthewebforward.org/docs/test-format-guidelines.html #support-files
192 dirs_to_include = ('resources', 'support') 110 dirs_to_include = ('resources', 'support')
193 111
194 if dirs: 112 if dirs:
195 for name in dirs_to_skip: 113 for name in dirs_to_skip:
196 if name in dirs: 114 if name in dirs:
197 dirs.remove(name) 115 dirs.remove(name)
198 116
199 for path in paths_to_skip: 117 for path in paths_to_skip:
200 path_base = path.replace(self.options.destination + '/', '') 118 path_base = path.replace(self.dest_dir_name + '/', '')
201 path_base = path_base.replace(cur_dir, '') 119 path_base = path_base.replace(cur_dir, '')
202 path_full = self.filesystem.join(root, path_base) 120 path_full = self.filesystem.join(root, path_base)
203 if path_base in dirs: 121 if path_base in dirs:
204 dirs.remove(path_base) 122 dirs.remove(path_base)
205 if not self.options.dry_run and self.import_in_place: 123 if self.import_in_place:
206 _log.info(" pruning %s", path_base) 124 _log.info(" pruning %s", path_base)
207 self.filesystem.rmtree(path_full) 125 self.filesystem.rmtree(path_full)
208 else: 126 else:
209 _log.info(" skipping %s", path_base) 127 _log.info(" skipping %s", path_base)
210 128
211 copy_list = [] 129 copy_list = []
212 130
213 for filename in files: 131 for filename in files:
214 path_full = self.filesystem.join(root, filename) 132 path_full = self.filesystem.join(root, filename)
215 path_base = path_full.replace(self.source_repo_path + '/', '') 133 path_base = path_full.replace(self.source_repo_path + '/', '')
216 path_base = self.destination_directory.replace(self.layout_tests _dir + '/', '') + '/' + path_base 134 path_base = self.destination_directory.replace(self.layout_tests _dir + '/', '') + '/' + path_base
217 if path_base in paths_to_skip: 135 if path_base in paths_to_skip:
218 if not self.options.dry_run and self.import_in_place: 136 if self.import_in_place:
219 _log.info(" pruning %s", path_base) 137 _log.info(" pruning %s", path_base)
220 self.filesystem.remove(path_full) 138 self.filesystem.remove(path_full)
221 continue 139 continue
222 else: 140 else:
223 continue 141 continue
224 # FIXME: This block should really be a separate function, but th e early-continues make that difficult. 142 # FIXME: This block should really be a separate function, but th e early-continues make that difficult.
225 143
226 if filename.startswith('.') or filename.endswith('.pl'): 144 if filename.startswith('.') or filename.endswith('.pl'):
227 # The w3cs repos may contain perl scripts, which we don't ca re about. 145 # The w3cs repos may contain perl scripts, which we don't ca re about.
228 continue 146 continue
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 total_tests += 1 202 total_tests += 1
285 copy_list.append({'src': test_info['reference'], 'dest': ref _file, 203 copy_list.append({'src': test_info['reference'], 'dest': ref _file,
286 'reference_support_info': test_info['refer ence_support_info']}) 204 'reference_support_info': test_info['refer ence_support_info']})
287 copy_list.append({'src': test_info['test'], 'dest': filename }) 205 copy_list.append({'src': test_info['test'], 'dest': filename })
288 206
289 elif 'jstest' in test_info.keys(): 207 elif 'jstest' in test_info.keys():
290 jstests += 1 208 jstests += 1
291 total_tests += 1 209 total_tests += 1
292 copy_list.append({'src': fullpath, 'dest': filename, 'is_jst est': True}) 210 copy_list.append({'src': fullpath, 'dest': filename, 'is_jst est': True})
293 211
294 elif self.options.all:
295 total_tests += 1
296 copy_list.append({'src': fullpath, 'dest': filename})
297
298 if copy_list: 212 if copy_list:
299 # Only add this directory to the list if there's something to im port 213 # Only add this directory to the list if there's something to im port
300 self.import_list.append({'dirname': root, 'copy_list': copy_list , 214 self.import_list.append({'dirname': root, 'copy_list': copy_list ,
301 'reftests': reftests, 'jstests': jstest s, 'total_tests': total_tests}) 215 'reftests': reftests, 'jstests': jstest s, 'total_tests': total_tests})
302 216
303 def find_paths_to_skip(self): 217 def find_paths_to_skip(self):
304 if self.options.ignore_expectations:
305 return set()
306
307 paths_to_skip = set() 218 paths_to_skip = set()
308 port = self.host.port_factory.get() 219 port = self.host.port_factory.get()
309 w3c_import_expectations_path = self.webkit_finder.path_from_webkit_base( 'LayoutTests', 'W3CImportExpectations') 220 w3c_import_expectations_path = self.webkit_finder.path_from_webkit_base( 'LayoutTests', 'W3CImportExpectations')
310 w3c_import_expectations = self.filesystem.read_text_file(w3c_import_expe ctations_path) 221 w3c_import_expectations = self.filesystem.read_text_file(w3c_import_expe ctations_path)
311 parser = TestExpectationParser(port, all_tests=(), is_lint_mode=False) 222 parser = TestExpectationParser(port, all_tests=(), is_lint_mode=False)
312 expectation_lines = parser.parse(w3c_import_expectations_path, w3c_impor t_expectations) 223 expectation_lines = parser.parse(w3c_import_expectations_path, w3c_impor t_expectations)
313 for line in expectation_lines: 224 for line in expectation_lines:
314 if 'SKIP' in line.expectations: 225 if 'SKIP' in line.expectations:
315 if line.specifiers: 226 if line.specifiers:
316 _log.warning("W3CImportExpectations:%s should not have any s pecifiers", line.line_numbers) 227 _log.warning("W3CImportExpectations:%s should not have any s pecifiers", line.line_numbers)
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 dest_path = self.filesystem.join(dest_dir, file_to_copy['dest']) 291 dest_path = self.filesystem.join(dest_dir, file_to_copy['dest'])
381 292
382 if self.filesystem.isdir(source_path): 293 if self.filesystem.isdir(source_path):
383 _log.error('%s refers to a directory', source_path) 294 _log.error('%s refers to a directory', source_path)
384 return None 295 return None
385 296
386 if not self.filesystem.exists(source_path): 297 if not self.filesystem.exists(source_path):
387 _log.error('%s not found. Possible error in the test.', source_path) 298 _log.error('%s not found. Possible error in the test.', source_path)
388 return None 299 return None
389 300
390 if file_to_copy.get('reference_support_info'): 301 reference_support_info = file_to_copy.get('reference_support_info') or N one
391 reference_support_info = file_to_copy['reference_support_info']
392 else:
393 reference_support_info = None
394 302
395 if not self.filesystem.exists(self.filesystem.dirname(dest_path)): 303 if not self.filesystem.exists(self.filesystem.dirname(dest_path)):
396 if not self.import_in_place and not self.options.dry_run: 304 if not self.import_in_place:
397 self.filesystem.maybe_make_directory(self.filesystem.dirname(des t_path)) 305 self.filesystem.maybe_make_directory(self.filesystem.dirname(des t_path))
398 306
399 relpath = self.filesystem.relpath(dest_path, self.layout_tests_dir) 307 relpath = self.filesystem.relpath(dest_path, self.layout_tests_dir)
400 if not self.options.overwrite and self.filesystem.exists(dest_path): 308 # FIXME: Maybe doing a file diff is in order here for existing files?
401 _log.info(' skipping %s', relpath) 309 # In other words, there's no sense in overwriting identical files, but
402 else: 310 # there's no harm in copying the identical thing.
403 # FIXME: Maybe doing a file diff is in order here for existing files ? 311 _log.info(' %s', relpath)
404 # In other words, there's no sense in overwriting identical files, b ut
405 # there's no harm in copying the identical thing.
406 _log.info(' %s', relpath)
407 312
408 if self.should_try_to_convert(file_to_copy, source_path, dest_dir): 313 if self.should_try_to_convert(file_to_copy, source_path, dest_dir):
409 converted_file = convert_for_webkit( 314 converted_file = convert_for_webkit(
410 dest_dir, filename=source_path, 315 dest_dir, filename=source_path,
411 reference_support_info=reference_support_info, 316 reference_support_info=reference_support_info,
412 host=self.host) 317 host=self.host)
413 for prefixed_property in converted_file[0]: 318 for prefixed_property in converted_file[0]:
414 self._prefixed_properties.setdefault(prefixed_property, 0) 319 self._prefixed_properties.setdefault(prefixed_property, 0)
415 self._prefixed_properties[prefixed_property] += 1 320 self._prefixed_properties[prefixed_property] += 1
416 321
417 if not self.options.dry_run: 322 self.filesystem.write_text_file(dest_path, converted_file[1])
418 self.filesystem.write_text_file(dest_path, converted_file[1])
419 else: 323 else:
420 if not self.import_in_place and not self.options.dry_run: 324 if not self.import_in_place:
421 self.filesystem.copyfile(source_path, dest_path) 325 self.filesystem.copyfile(source_path, dest_path)
422 if self.filesystem.read_binary_file(source_path)[:2] == '#!': 326 if self.filesystem.read_binary_file(source_path)[:2] == '#!':
423 self.filesystem.make_executable(dest_path) 327 self.filesystem.make_executable(dest_path)
424 328
425 return dest_path.replace(self._webkit_root, '') 329 return dest_path.replace(self._webkit_root, '')
426 330
427 @staticmethod 331 @staticmethod
428 def should_try_to_convert(file_to_copy, source_path, dest_dir): 332 def should_try_to_convert(file_to_copy, source_path, dest_dir):
429 """Checks whether we should try to modify the file when importing.""" 333 """Checks whether we should try to modify the file when importing."""
430 if file_to_copy.get('is_jstest', False): 334 if file_to_copy.get('is_jstest', False):
(...skipping 12 matching lines...) Expand all
443 """Checks whether a source path is too long to import. 347 """Checks whether a source path is too long to import.
444 348
445 Args: 349 Args:
446 Absolute path of file to be imported. 350 Absolute path of file to be imported.
447 351
448 Returns: 352 Returns:
449 True if the path is too long to import, False if it's OK. 353 True if the path is too long to import, False if it's OK.
450 """ 354 """
451 path_from_repo_base = os.path.relpath(source_path, self.source_repo_path ) 355 path_from_repo_base = os.path.relpath(source_path, self.source_repo_path )
452 return len(path_from_repo_base) > MAX_PATH_LENGTH 356 return len(path_from_repo_base) > MAX_PATH_LENGTH
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698