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

Side by Side Diff: Tools/Scripts/webkitpy/bindings/main.py

Issue 169743005: Faster run-bindings-tests (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Another merge Created 6 years, 9 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) 2011 Google Inc. All rights reserved. 1 # Copyright (C) 2011 Google Inc. 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 # 1. Redistributions of source code must retain the above copyright 6 # 1. Redistributions of source code must retain the above copyright
7 # notice, this list of conditions and the following disclaimer. 7 # notice, this list of conditions and the following disclaimer.
8 # 2. Redistributions in binary form must reproduce the above copyright 8 # 2. Redistributions in binary form must reproduce the above copyright
9 # notice, this list of conditions and the following disclaimer in the 9 # notice, this list of conditions and the following disclaimer in the
10 # documentation and/or other materials provided with the distribution. 10 # documentation and/or other materials provided with the distribution.
11 # 11 #
12 # THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 12 # THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
13 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 13 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 14 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
15 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 15 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
16 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
17 # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
18 # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
19 # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 19 # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
20 # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 21 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 # 23 #
24 24
25 import fnmatch 25 import fnmatch
26 import os 26 import os
27 import cPickle as pickle
28 import shutil 27 import shutil
28 import sys
29 import tempfile 29 import tempfile
30 30
31 from webkitpy.common.checkout.scm.detection import detect_scm_system 31 from webkitpy.common.checkout.scm.detection import detect_scm_system
32 from webkitpy.common.system import executive 32 from webkitpy.common.system import executive
33 from webkitpy.common.system.executive import ScriptError 33 from webkitpy.common.system.executive import ScriptError
34 34
35 # Add Source path to PYTHONPATH to support function calls to bindings/scripts
36 # for compute_dependencies and idl_compiler
37 module_path = os.path.dirname(__file__)
38 source_path = os.path.normpath(os.path.join(module_path, os.pardir,
39 os.pardir, os.pardir, os.pardir,
40 'Source'))
41 sys.path.append(source_path)
42
43 from bindings.scripts.compute_interfaces_info import compute
44 from bindings.scripts.idl_compiler import compile_idl
45
46
35 PASS_MESSAGE = 'All tests PASS!' 47 PASS_MESSAGE = 'All tests PASS!'
36 FAIL_MESSAGE = """Some tests FAIL! 48 FAIL_MESSAGE = """Some tests FAIL!
37 To update the reference files, execute: 49 To update the reference files, execute:
38 run-bindings-tests --reset-results 50 run-bindings-tests --reset-results
39 51
40 If the failures are not due to your changes, test results may be out of sync; 52 If the failures are not due to your changes, test results may be out of sync;
41 please rebaseline them in a separate CL, after checking that tests fail in ToT. 53 please rebaseline them in a separate CL, after checking that tests fail in ToT.
42 In CL, please set: 54 In CL, please set:
43 NOTRY=true 55 NOTRY=true
44 TBR=(someone in Source/bindings/OWNERS or WATCHLISTS:bindings) 56 TBR=(someone in Source/bindings/OWNERS or WATCHLISTS:bindings)
45 """ 57 """
46 58
47 DEPENDENCY_IDL_FILES = set([ 59 DEPENDENCY_IDL_FILES = set([
48 'SupportTestPartialInterface.idl', 60 'SupportTestPartialInterface.idl',
49 'TestImplements.idl', 61 'TestImplements.idl',
50 'TestImplements2.idl', 62 'TestImplements2.idl',
51 'TestImplements3.idl', 63 'TestImplements3.idl',
52 'TestPartialInterface.idl', 64 'TestPartialInterface.idl',
53 'TestPartialInterfacePython.idl', 65 'TestPartialInterfacePython.idl',
54 'TestPartialInterfacePython2.idl', 66 'TestPartialInterfacePython2.idl',
55 ]) 67 ])
56 68
69
70 EXTENDED_ATTRIBUTES_FILE = 'bindings/IDLExtendedAttributes.txt'
71
57 all_input_directory = '.' # Relative to Source/ 72 all_input_directory = '.' # Relative to Source/
58 test_input_directory = os.path.join('bindings', 'tests', 'idls') 73 test_input_directory = os.path.join('bindings', 'tests', 'idls')
59 reference_directory = os.path.join('bindings', 'tests', 'results') 74 reference_directory = os.path.join('bindings', 'tests', 'results')
60 reference_event_names_filename = os.path.join(reference_directory, 'EventInterfa ces.in') 75 reference_event_names_filename = os.path.join(reference_directory, 'EventInterfa ces.in')
61 76
62 77
63 class ScopedTempFileProvider(object): 78 class ScopedTempFileProvider(object):
64 def __init__(self): 79 def __init__(self):
65 self.file_handles = [] 80 self.file_handles = []
66 self.file_paths = [] 81 self.file_paths = []
(...skipping 23 matching lines...) Expand all
90 self.dir_paths.append(dir_path) 105 self.dir_paths.append(dir_path)
91 return dir_path 106 return dir_path
92 107
93 108
94 class BindingsTests(object): 109 class BindingsTests(object):
95 def __init__(self, reset_results, verbose, provider): 110 def __init__(self, reset_results, verbose, provider):
96 self.reset_results = reset_results 111 self.reset_results = reset_results
97 self.verbose = verbose 112 self.verbose = verbose
98 self.executive = executive.Executive() 113 self.executive = executive.Executive()
99 self.provider = provider 114 self.provider = provider
115 self.reader = None
Nils Barth (inactive) 2014/03/03 01:32:48 If we make the compiler an object, this becomes se
100 _, self.interface_dependencies_filename = provider.new_temp_file() 116 _, self.interface_dependencies_filename = provider.new_temp_file()
101 _, self.interfaces_info_filename = provider.new_temp_file() 117 _, self.interfaces_info_filename = provider.new_temp_file()
102 # Generate output into the reference directory if resetting results, or 118 # Generate output into the reference directory if resetting results, or
103 # a temp directory if not. 119 # a temp directory if not.
104 if reset_results: 120 if reset_results:
105 self.output_directory = reference_directory 121 self.output_directory = reference_directory
106 else: 122 else:
107 self.output_directory = provider.new_temp_dir() 123 self.output_directory = provider.new_temp_dir()
108 self.event_names_filename = os.path.join(self.output_directory, 'EventIn terfaces.in') 124 self.event_names_filename = os.path.join(self.output_directory, 'EventIn terfaces.in')
109 125
110 def run_command(self, cmd): 126 def run_command(self, cmd):
111 output = self.executive.run_command(cmd) 127 output = self.executive.run_command(cmd)
112 if output: 128 if output:
113 print output 129 print output
114 130
115 def generate_from_idl(self, idl_file): 131 def generate_from_idl(self, idl_file):
116 cmd = ['python',
117 'bindings/scripts/idl_compiler.py',
118 '--output-dir', self.output_directory,
119 '--idl-attributes-file', 'bindings/IDLExtendedAttributes.txt',
120 '--interfaces-info-file', self.interfaces_info_filename,
121 idl_file]
122 try: 132 try:
123 self.run_command(cmd) 133 idl_file_fullpath = os.path.realpath(idl_file)
134 self.reader = compile_idl(idl_file_fullpath,
135 self.output_directory,
136 EXTENDED_ATTRIBUTES_FILE,
137 self.interfaces_info_filename,
138 True, self.reader)
124 except ScriptError, e: 139 except ScriptError, e:
125 print 'ERROR: idl_compiler.py: ' + os.path.basename(idl_file) 140 print 'ERROR: idl_compiler.py: ' + os.path.basename(idl_file)
126 print e.output 141 print e.output
127 return e.exit_code 142 return e.exit_code
143
128 return 0 144 return 0
129 145
130 def generate_interface_dependencies(self): 146 def generate_interface_dependencies(self):
131 def idl_paths(directory): 147 def idl_paths(directory):
132 return [os.path.join(directory, input_file) 148 return [os.path.join(directory, input_file)
133 for input_file in os.listdir(directory) 149 for input_file in os.listdir(directory)
134 if input_file.endswith('.idl')] 150 if input_file.endswith('.idl')]
135 151
136 def idl_paths_recursive(directory): 152 def idl_paths_recursive(directory):
137 idl_paths = [] 153 idl_paths = []
138 for dirpath, _, files in os.walk(directory): 154 for dirpath, _, files in os.walk(directory):
139 idl_paths.extend(os.path.join(dirpath, filename) 155 idl_paths.extend(os.path.join(dirpath, filename)
140 for filename in fnmatch.filter(files, '*.idl')) 156 for filename in fnmatch.filter(files, '*.idl'))
141 return idl_paths 157 return idl_paths
142 158
143 def write_list_file(idl_paths): 159 def write_list_file(idl_paths):
144 list_file, list_filename = self.provider.new_temp_file() 160 list_file, list_filename = self.provider.new_temp_file()
145 list_contents = ''.join(idl_path + '\n' 161 list_contents = ''.join(idl_path + '\n'
146 for idl_path in idl_paths) 162 for idl_path in idl_paths)
147 os.write(list_file, list_contents) 163 os.write(list_file, list_contents)
148 return list_filename 164 return list_filename
149 165
166 # Faster in-memory file list.
167 def list_idl_file(idl_paths):
Nils Barth (inactive) 2014/03/03 01:32:48 This is unnecessary, right? (It's just copying a l
168 idls = []
169 for idl_path in idl_paths:
170 idls.append(idl_path)
171 return idls
172
150 def compute_interfaces_info(idl_files_list_filename, 173 def compute_interfaces_info(idl_files_list_filename,
Nils Barth (inactive) 2014/03/03 06:45:49 I'm simplifying this (remove EventInterfaces.in),
151 event_names_filename): 174 event_names_filename):
152 cmd = ['python', 175 compute(idl_files_list_filename, self.interfaces_info_filename,
153 'bindings/scripts/compute_interfaces_info.py', 176 self.interface_dependencies_filename,
154 '--idl-files-list', idl_files_list_filename, 177 event_names_filename, False)
155 '--interface-dependencies-file', self.interface_dependencies_ filename,
156 '--interfaces-info-file', self.interfaces_info_filename,
157 '--event-names-file', event_names_filename,
158 '--write-file-only-if-changed', '0']
159 self.run_command(cmd)
160 178
161 test_idl_files_list_filename = write_list_file(idl_paths(test_input_dire ctory)) 179 test_idl_files_list = list_idl_file(idl_paths(test_input_directory))
162 all_idl_files_list_filename = write_list_file(idl_paths_recursive(all_in put_directory)) 180 all_idl_files_list = list_idl_file(idl_paths_recursive(all_input_directo ry))
163 181
164 if self.reset_results and self.verbose: 182 if self.reset_results and self.verbose:
165 print 'Reset results: EventInterfaces.in' 183 print 'Reset results: EventInterfaces.in'
166 try: 184 try:
167 # We first compute interfaces info for testing files only, 185 # We first compute interfaces info for testing files only,
168 # so we can compare EventInterfaces.in. 186 # so we can compare EventInterfaces.in.
169 compute_interfaces_info(test_idl_files_list_filename, 187 compute_interfaces_info(test_idl_files_list, self.event_names_filena me)
170 self.event_names_filename)
171 188
172 # We then compute interfaces info for all IDL files, as code 189 # We then compute interfaces info for all IDL files, as code
173 # generator output depends on inheritance (both ancestor chain and 190 # generator output depends on inheritance (both ancestor chain and
174 # inherited extended attributes), and some real interfaces are 191 # inherited extended attributes), and some real interfaces are
175 # special-cased, such as Node. 192 # special-cased, such as Node.
176 # For example, when testing the behavior of interfaces that inherit 193 # For example, when testing the behavior of interfaces that inherit
177 # from Node, we also need to know that these inherit from 194 # from Node, we also need to know that these inherit from
178 # EventTarget, since this is also special-cased and Node inherits 195 # EventTarget, since this is also special-cased and Node inherits
179 # from EventTarget, but this inheritance information requires 196 # from EventTarget, but this inheritance information requires
180 # computing dependencies for the real Node.idl file. 197 # computing dependencies for the real Node.idl file.
181 # 198 #
182 # Don't overwrite the event names file generated for testing IDLs 199 # Don't overwrite the event names file generated for testing IDLs
183 _, dummy_event_names_filename = self.provider.new_temp_file() 200 _, dummy_event_names_filename = self.provider.new_temp_file()
184 compute_interfaces_info(all_idl_files_list_filename, 201 compute_interfaces_info(all_idl_files_list, dummy_event_names_filena me)
185 dummy_event_names_filename)
186 except ScriptError, e: 202 except ScriptError, e:
187 print 'ERROR: compute_interfaces_info.py' 203 print 'ERROR: compute_interfaces_info.py'
188 print e.output 204 print e.output
189 return e.exit_code 205 return e.exit_code
206
190 return 0 207 return 0
191 208
192 def identical_file(self, reference_filename, output_filename): 209 def identical_file(self, reference_filename, output_filename):
193 reference_basename = os.path.basename(reference_filename) 210 reference_basename = os.path.basename(reference_filename)
194 cmd = ['diff', 211 cmd = ['diff',
195 '-u', 212 '-u',
196 '-N', 213 '-N',
197 reference_filename, 214 reference_filename,
198 output_filename] 215 output_filename]
199 try: 216 try:
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 print 'DEPENDENCY: %s' % input_filename 263 print 'DEPENDENCY: %s' % input_filename
247 continue 264 continue
248 265
249 idl_path = os.path.join(test_input_directory, input_filename) 266 idl_path = os.path.join(test_input_directory, input_filename)
250 if self.generate_from_idl(idl_path): 267 if self.generate_from_idl(idl_path):
251 return False 268 return False
252 if self.reset_results and self.verbose: 269 if self.reset_results and self.verbose:
253 print 'Reset results: %s' % input_filename 270 print 'Reset results: %s' % input_filename
254 271
255 # Detect all changes 272 # Detect all changes
256 passed = self.identical_file(reference_event_names_filename, 273 passed = self.identical_file(reference_event_names_filename, self.event_ names_filename)
257 self.event_names_filename)
258 passed &= self.identical_output_files() 274 passed &= self.identical_output_files()
259 passed &= self.no_excess_files() 275 passed &= self.no_excess_files()
260 return passed 276 return passed
261 277
262 def main(self): 278 def main(self):
263 current_scm = detect_scm_system(os.curdir) 279 current_scm = detect_scm_system(os.curdir)
264 os.chdir(os.path.join(current_scm.checkout_root, 'Source')) 280 os.chdir(os.path.join(current_scm.checkout_root, 'Source'))
265 281
266 all_tests_passed = self.run_tests() 282 all_tests_passed = self.run_tests()
267 if all_tests_passed: 283 if all_tests_passed:
268 if self.verbose: 284 if self.verbose:
269 print 285 print
270 print PASS_MESSAGE 286 print PASS_MESSAGE
271 return 0 287 return 0
272 print 288 print
273 print FAIL_MESSAGE 289 print FAIL_MESSAGE
274 return -1 290 return -1
275 291
276 292
277 def run_bindings_tests(reset_results, verbose): 293 def run_bindings_tests(reset_results, verbose):
278 with ScopedTempFileProvider() as provider: 294 with ScopedTempFileProvider() as provider:
279 return BindingsTests(reset_results, verbose, provider).main() 295 return BindingsTests(reset_results, verbose, provider).main()
OLDNEW
« Source/bindings/scripts/idl_compiler.py ('K') | « Source/bindings/scripts/unstable/__init__.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698