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

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: removed obsolete method 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
Nils Barth (inactive) 2014/03/14 01:01:37 Here you can also import |interfaces_info| ...to a
terry 2014/03/14 16:12:54 Done. On 2014/03/14 01:01:37, Nils Barth wrote:
44 from bindings.scripts.idl_compiler import IdlCompilerV8
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 75
61 76
62 class ScopedTempFileProvider(object): 77 class ScopedTempFileProvider(object):
63 def __init__(self): 78 def __init__(self):
64 self.file_handles = [] 79 self.file_handles = []
65 self.file_paths = [] 80 self.file_paths = []
66 self.dir_paths = [] 81 self.dir_paths = []
(...skipping 22 matching lines...) Expand all
89 self.dir_paths.append(dir_path) 104 self.dir_paths.append(dir_path)
90 return dir_path 105 return dir_path
91 106
92 107
93 class BindingsTests(object): 108 class BindingsTests(object):
94 def __init__(self, reset_results, verbose, provider): 109 def __init__(self, reset_results, verbose, provider):
95 self.reset_results = reset_results 110 self.reset_results = reset_results
96 self.verbose = verbose 111 self.verbose = verbose
97 self.executive = executive.Executive() 112 self.executive = executive.Executive()
98 self.provider = provider 113 self.provider = provider
114 self.idl_compiler = None
99 _, self.interfaces_info_filename = provider.new_temp_file() 115 _, self.interfaces_info_filename = provider.new_temp_file()
100 # Generate output into the reference directory if resetting results, or 116 # Generate output into the reference directory if resetting results, or
101 # a temp directory if not. 117 # a temp directory if not.
102 if reset_results: 118 if reset_results:
103 self.output_directory = reference_directory 119 self.output_directory = reference_directory
104 else: 120 else:
105 self.output_directory = provider.new_temp_dir() 121 self.output_directory = provider.new_temp_dir()
106 122
107 def run_command(self, cmd): 123 def run_command(self, cmd):
108 output = self.executive.run_command(cmd) 124 output = self.executive.run_command(cmd)
109 if output: 125 if output:
110 print output 126 print output
111 127
112 def generate_from_idl(self, idl_file): 128 def generate_from_idl(self, idl_file):
113 cmd = ['python',
114 'bindings/scripts/idl_compiler.py',
115 '--output-dir', self.output_directory,
116 '--idl-attributes-file', 'bindings/IDLExtendedAttributes.txt',
117 '--interfaces-info-file', self.interfaces_info_filename,
118 idl_file]
119 try: 129 try:
120 self.run_command(cmd) 130 idl_file_fullpath = os.path.realpath(idl_file)
131 self.idl_compiler.compile_file(idl_file_fullpath)
121 except ScriptError, e: 132 except ScriptError, e:
122 print 'ERROR: idl_compiler.py: ' + os.path.basename(idl_file) 133 print 'ERROR: idl_compiler.py: ' + os.path.basename(idl_file)
123 print e.output 134 print e.output
124 return e.exit_code 135 return e.exit_code
136
125 return 0 137 return 0
126 138
127 def generate_interface_dependencies(self): 139 def generate_interface_dependencies(self):
128 def idl_paths(directory): 140 def idl_paths(directory):
129 return [os.path.join(directory, input_file) 141 return [os.path.join(directory, input_file)
130 for input_file in os.listdir(directory) 142 for input_file in os.listdir(directory)
131 if input_file.endswith('.idl')] 143 if input_file.endswith('.idl')]
132 144
133 def idl_paths_recursive(directory): 145 def idl_paths_recursive(directory):
134 idl_paths = [] 146 idl_paths = []
135 for dirpath, _, files in os.walk(directory): 147 for dirpath, _, files in os.walk(directory):
136 idl_paths.extend(os.path.join(dirpath, filename) 148 idl_paths.extend(os.path.join(dirpath, filename)
137 for filename in fnmatch.filter(files, '*.idl')) 149 for filename in fnmatch.filter(files, '*.idl'))
138 return idl_paths 150 return idl_paths
139 151
140 def write_list_file(idl_paths): 152 def write_list_file(idl_paths):
141 list_file, list_filename = self.provider.new_temp_file() 153 list_file, list_filename = self.provider.new_temp_file()
142 list_contents = ''.join(idl_path + '\n' 154 list_contents = ''.join(idl_path + '\n'
143 for idl_path in idl_paths) 155 for idl_path in idl_paths)
144 os.write(list_file, list_contents) 156 os.write(list_file, list_contents)
145 return list_filename 157 return list_filename
146 158
147 def compute_interfaces_info(idl_files_list_filename): 159 def compute_interfaces_info(idl_files_list_filename):
148 cmd = ['python', 160 compute(idl_files_list_filename, self.interfaces_info_filename, Fals e)
Nils Barth (inactive) 2014/03/14 01:01:37 Instead of using an intermediate file, we can just
terry 2014/03/14 16:12:54 Right, with the compiler taking interface_info I'l
149 'bindings/scripts/compute_interfaces_info.py',
150 '--idl-files-list', idl_files_list_filename,
151 '--interfaces-info-file', self.interfaces_info_filename,
152 '--write-file-only-if-changed', '0']
153 self.run_command(cmd)
154 161
155 # We compute interfaces info for *all* IDL files, not just test IDL 162 # We compute interfaces info for *all* IDL files, not just test IDL
156 # files, as code generator output depends on inheritance (both ancestor 163 # files, as code generator output depends on inheritance (both ancestor
157 # chain and inherited extended attributes), and some real interfaces 164 # chain and inherited extended attributes), and some real interfaces
158 # are special-cased, such as Node. 165 # are special-cased, such as Node.
159 # 166 #
160 # For example, when testing the behavior of interfaces that inherit 167 # For example, when testing the behavior of interfaces that inherit
161 # from Node, we also need to know that these inherit from EventTarget, 168 # from Node, we also need to know that these inherit from EventTarget,
162 # since this is also special-cased and Node inherits from EventTarget, 169 # since this is also special-cased and Node inherits from EventTarget,
163 # but this inheritance information requires computing dependencies for 170 # but this inheritance information requires computing dependencies for
164 # the real Node.idl file. 171 # the real Node.idl file.
165 all_idl_files_list_filename = write_list_file(idl_paths_recursive(all_in put_directory))
166 try: 172 try:
167 compute_interfaces_info(all_idl_files_list_filename) 173 compute_interfaces_info(idl_paths_recursive(all_input_directory))
168 except ScriptError, e: 174 except ScriptError, e:
169 print 'ERROR: compute_interfaces_info.py' 175 print 'ERROR: compute_interfaces_info.py'
170 print e.output 176 print e.output
171 return e.exit_code 177 return e.exit_code
178
172 return 0 179 return 0
173 180
174 def delete_cache_files(self): 181 def delete_cache_files(self):
175 # FIXME: Instead of deleting cache files, don't generate them. 182 # FIXME: Instead of deleting cache files, don't generate them.
176 cache_files = [os.path.join(self.output_directory, output_file) 183 cache_files = [os.path.join(self.output_directory, output_file)
177 for output_file in os.listdir(self.output_directory) 184 for output_file in os.listdir(self.output_directory)
178 if (output_file in ('lextab.py', # PLY lex 185 if (output_file in ('lextab.py', # PLY lex
179 'lextab.pyc', 186 'lextab.pyc',
180 'parsetab.pickle') or # PLY yacc 187 'parsetab.pickle') or # PLY yacc
181 output_file.endswith('.cache'))] # Jinja 188 output_file.endswith('.cache'))] # Jinja
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 '(probably cruft from renaming or deleting):\n' + 226 '(probably cruft from renaming or deleting):\n' +
220 '\n'.join(excess_files)) 227 '\n'.join(excess_files))
221 return False 228 return False
222 return True 229 return True
223 230
224 def run_tests(self): 231 def run_tests(self):
225 # Generate output, immediately dying on failure 232 # Generate output, immediately dying on failure
226 if self.generate_interface_dependencies(): 233 if self.generate_interface_dependencies():
227 return False 234 return False
228 235
236 self.idl_compiler = IdlCompilerV8(self.output_directory,
237 EXTENDED_ATTRIBUTES_FILE,
238 interfaces_info_filename=self.interfac es_info_filename,
Nils Barth (inactive) 2014/03/14 01:01:37 We can pass the dict in directly (no file needed!)
terry 2014/03/14 16:12:54 Good idea. I didn't noticed you had added that in
239 only_if_changed=True)
240
229 for input_filename in os.listdir(test_input_directory): 241 for input_filename in os.listdir(test_input_directory):
230 if not input_filename.endswith('.idl'): 242 if not input_filename.endswith('.idl'):
231 continue 243 continue
232 if input_filename in DEPENDENCY_IDL_FILES: 244 if input_filename in DEPENDENCY_IDL_FILES:
233 # Dependencies aren't built (they are used by the dependent) 245 # Dependencies aren't built (they are used by the dependent)
234 if self.verbose: 246 if self.verbose:
235 print 'DEPENDENCY: %s' % input_filename 247 print 'DEPENDENCY: %s' % input_filename
236 continue 248 continue
237 249
238 idl_path = os.path.join(test_input_directory, input_filename) 250 idl_path = os.path.join(test_input_directory, input_filename)
(...skipping 20 matching lines...) Expand all
259 print PASS_MESSAGE 271 print PASS_MESSAGE
260 return 0 272 return 0
261 print 273 print
262 print FAIL_MESSAGE 274 print FAIL_MESSAGE
263 return -1 275 return -1
264 276
265 277
266 def run_bindings_tests(reset_results, verbose): 278 def run_bindings_tests(reset_results, verbose):
267 with ScopedTempFileProvider() as provider: 279 with ScopedTempFileProvider() as provider:
268 return BindingsTests(reset_results, verbose, provider).main() 280 return BindingsTests(reset_results, verbose, provider).main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698