OLD | NEW |
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 from shutil import rmtree | 27 from shutil import rmtree |
| 28 import sys |
29 import tempfile | 29 import tempfile |
30 from webkitpy.common.checkout.scm.detection import detect_scm_system | 30 from webkitpy.common.checkout.scm.detection import detect_scm_system |
31 from webkitpy.common.system.executive import ScriptError | 31 from webkitpy.common.system.executive import ScriptError |
32 | 32 |
| 33 # Add Source path to PYTHONPATH to support function calls to bindings/scripts |
| 34 # for compute_dependencies and idl_compiler |
| 35 module_path = os.path.dirname(__file__) |
| 36 source_path = os.path.normpath(os.path.join(module_path, os.pardir, |
| 37 os.pardir, os.pardir, os.pardir, |
| 38 'Source')) |
| 39 sys.path.append(source_path) |
| 40 |
| 41 from bindings.scripts.compute_dependencies import compute |
| 42 from bindings.scripts.unstable.idl_compiler import compile_idl |
| 43 |
| 44 |
33 PASS_MESSAGE = 'All tests PASS!' | 45 PASS_MESSAGE = 'All tests PASS!' |
34 FAIL_MESSAGE = """Some tests FAIL! | 46 FAIL_MESSAGE = """Some tests FAIL! |
35 To update the reference files, execute: | 47 To update the reference files, execute: |
36 run-bindings-tests --reset-results | 48 run-bindings-tests --reset-results |
37 | 49 |
38 If the failures are not due to your changes, test results may be out of sync; | 50 If the failures are not due to your changes, test results may be out of sync; |
39 please rebaseline them in a separate CL, after checking that tests fail in ToT. | 51 please rebaseline them in a separate CL, after checking that tests fail in ToT. |
40 In CL, please set: | 52 In CL, please set: |
41 NOTRY=true | 53 NOTRY=true |
42 TBR=(someone in Source/bindings/OWNERS or WATCHLISTS:bindings) | 54 TBR=(someone in Source/bindings/OWNERS or WATCHLISTS:bindings) |
43 """ | 55 """ |
44 | 56 |
45 DEPENDENCY_IDL_FILES = set([ | 57 DEPENDENCY_IDL_FILES = set([ |
46 'SupportTestPartialInterface.idl', | 58 'SupportTestPartialInterface.idl', |
47 'TestImplements.idl', | 59 'TestImplements.idl', |
48 'TestImplements2.idl', | 60 'TestImplements2.idl', |
49 'TestImplements3.idl', | 61 'TestImplements3.idl', |
50 'TestPartialInterface.idl', | 62 'TestPartialInterface.idl', |
51 'TestPartialInterfacePython.idl', | 63 'TestPartialInterfacePython.idl', |
52 'TestPartialInterfacePython2.idl', | 64 'TestPartialInterfacePython2.idl', |
53 ]) | 65 ]) |
54 | 66 |
55 SKIP_PYTHON = 'TestSVG.idl' # Not implementing SVG-specific hacks in Python | 67 SKIP_PYTHON = 'TestSVG.idl' # Not implementing SVG-specific hacks in Python |
56 | 68 |
| 69 EXTENDED_ATTRIBUTES_FILE = 'bindings/IDLExtendedAttributes.txt' |
| 70 |
57 all_input_directory = '.' # Relative to Source/ | 71 all_input_directory = '.' # Relative to Source/ |
58 test_input_directory = os.path.join('bindings', 'tests', 'idls') | 72 test_input_directory = os.path.join('bindings', 'tests', 'idls') |
59 reference_directory = os.path.join('bindings', 'tests', 'results') | 73 reference_directory = os.path.join('bindings', 'tests', 'results') |
60 reference_event_names_filename = os.path.join(reference_directory, 'EventInterfa
ces.in') | 74 reference_event_names_filename = os.path.join(reference_directory, 'EventInterfa
ces.in') |
61 | 75 |
62 | 76 |
63 class ScopedTempFileProvider(object): | 77 class ScopedTempFileProvider(object): |
64 def __init__(self): | 78 def __init__(self): |
65 self.files = [] | 79 self.files = [] |
66 self.directories = [] | 80 self.directories = [] |
(...skipping 12 matching lines...) Expand all Loading... |
79 def newtempdir(self): | 93 def newtempdir(self): |
80 path = tempfile.mkdtemp() | 94 path = tempfile.mkdtemp() |
81 self.directories.append(path) | 95 self.directories.append(path) |
82 return path | 96 return path |
83 | 97 |
84 provider = ScopedTempFileProvider() | 98 provider = ScopedTempFileProvider() |
85 | 99 |
86 | 100 |
87 class BindingsTests(object): | 101 class BindingsTests(object): |
88 def __init__(self, reset_results, test_python, verbose, executive): | 102 def __init__(self, reset_results, test_python, verbose, executive): |
| 103 self.interfaces_info = {} # in-memory interfaces |
89 self.reset_results = reset_results | 104 self.reset_results = reset_results |
90 self.test_python = test_python | 105 self.test_python = test_python |
91 self.verbose = verbose | 106 self.verbose = verbose |
92 self.executive = executive | 107 self.executive = executive |
| 108 self.reader = None |
93 _, self.interface_dependencies_filename = provider.newtempfile() | 109 _, self.interface_dependencies_filename = provider.newtempfile() |
94 _, self.interfaces_info_filename = provider.newtempfile() | 110 _, self.interfaces_info_filename = provider.newtempfile() |
95 # Generate output into the reference directory if resetting results, or | 111 # Generate output into the reference directory if resetting results, or |
96 # a temp directory if not. | 112 # a temp directory if not. |
97 if reset_results: | 113 if reset_results: |
98 self.output_directory = reference_directory | 114 self.output_directory = reference_directory |
99 else: | 115 else: |
100 self.output_directory = provider.newtempdir() | 116 self.output_directory = provider.newtempdir() |
101 self.output_directory_py = provider.newtempdir() | 117 self.output_directory_py = provider.newtempdir() |
102 self.event_names_filename = os.path.join(self.output_directory, 'EventIn
terfaces.in') | 118 self.event_names_filename = os.path.join(self.output_directory, 'EventIn
terfaces.in') |
103 | 119 |
104 def run_command(self, cmd): | 120 def run_command(self, cmd): |
105 output = self.executive.run_command(cmd) | 121 output = self.executive.run_command(cmd) |
106 if output: | 122 if output: |
107 print output | 123 print output |
108 | 124 |
109 def generate_from_idl_pl(self, idl_file): | 125 def generate_from_idl_pl(self, idl_file): |
110 cmd = ['perl', '-w', | 126 cmd = ['perl', '-w', |
111 '-Ibindings/scripts', | 127 '-Ibindings/scripts', |
112 '-Ibuild/scripts', | 128 '-Ibuild/scripts', |
113 '-Icore/scripts', | 129 '-Icore/scripts', |
114 '-I../../JSON/out/lib/perl5', | 130 '-I../../JSON/out/lib/perl5', |
115 'bindings/scripts/generate_bindings.pl', | 131 'bindings/scripts/generate_bindings.pl', |
116 # idl include directories (path relative to generate-bindings.pl) | 132 # idl include directories (path relative to generate-bindings.pl) |
117 '--include', '.', | 133 '--include', '.', |
118 '--outputDir', self.output_directory, | 134 '--outputDir', self.output_directory, |
119 '--interfaceDependenciesFile', self.interface_dependencies_filena
me, | 135 '--interfaceDependenciesFile', self.interface_dependencies_filena
me, |
120 '--idlAttributesFile', 'bindings/IDLExtendedAttributes.txt', | 136 '--idlAttributesFile', EXTENDED_ATTRIBUTES_FILE, |
121 idl_file] | 137 idl_file] |
122 try: | 138 try: |
123 self.run_command(cmd) | 139 self.run_command(cmd) |
124 except ScriptError, e: | 140 except ScriptError, e: |
125 print 'ERROR: generate_bindings.pl: ' + os.path.basename(idl_file) | 141 print 'ERROR: generate_bindings.pl: ' + os.path.basename(idl_file) |
126 print e.output | 142 print e.output |
127 return e.exit_code | 143 return e.exit_code |
128 return 0 | 144 return 0 |
129 | 145 |
130 def generate_from_idl_py(self, idl_file): | 146 def generate_from_idl_py(self, idl_file): |
131 cmd = ['python', | |
132 'bindings/scripts/unstable/idl_compiler.py', | |
133 '--output-dir', self.output_directory_py, | |
134 '--idl-attributes-file', 'bindings/IDLExtendedAttributes.txt', | |
135 '--interfaces-info-file', self.interfaces_info_filename, | |
136 idl_file] | |
137 try: | 147 try: |
138 self.run_command(cmd) | 148 idl_file_fullpath = os.path.realpath(idl_file) |
| 149 self.reader = compile_idl(idl_file_fullpath, |
| 150 self.output_directory_py, |
| 151 EXTENDED_ATTRIBUTES_FILE, |
| 152 self.interfaces_info, self.reader) |
139 except ScriptError, e: | 153 except ScriptError, e: |
140 print 'ERROR: idl_compiler.py: ' + os.path.basename(idl_file) | 154 print 'ERROR: idl_compiler.py: ' + os.path.basename(idl_file) |
141 print e.output | 155 print e.output |
142 return e.exit_code | 156 return e.exit_code |
| 157 |
143 return 0 | 158 return 0 |
144 | 159 |
145 def generate_interface_dependencies(self): | 160 def generate_interface_dependencies(self): |
146 def idl_paths(directory): | 161 def idl_paths(directory): |
147 return [os.path.join(directory, input_file) | 162 return [os.path.join(directory, input_file) |
148 for input_file in os.listdir(directory) | 163 for input_file in os.listdir(directory) |
149 if input_file.endswith('.idl')] | 164 if input_file.endswith('.idl')] |
150 | 165 |
151 def idl_paths_recursive(directory): | 166 def idl_paths_recursive(directory): |
152 idl_paths = [] | 167 idl_paths = [] |
153 for dirpath, _, files in os.walk(directory): | 168 for dirpath, _, files in os.walk(directory): |
154 idl_paths.extend(os.path.join(dirpath, filename) | 169 idl_paths.extend(os.path.join(dirpath, filename) |
155 for filename in fnmatch.filter(files, '*.idl')) | 170 for filename in fnmatch.filter(files, '*.idl')) |
156 return idl_paths | 171 return idl_paths |
157 | 172 |
158 def write_list_file(idl_paths): | 173 def write_list_file(idl_paths): |
159 list_file, list_filename = provider.newtempfile() | 174 list_file, list_filename = provider.newtempfile() |
160 list_contents = ''.join(idl_path + '\n' | 175 list_contents = ''.join(idl_path + '\n' |
161 for idl_path in idl_paths) | 176 for idl_path in idl_paths) |
162 os.write(list_file, list_contents) | 177 os.write(list_file, list_contents) |
163 return list_filename | 178 return list_filename |
164 | 179 |
165 def compute_dependencies(idl_files_list_filename, | 180 # Faster in-memory file list. |
166 event_names_filename): | 181 def list_idl_file(idl_paths): |
| 182 idls = [] |
| 183 for idl_path in idl_paths: |
| 184 idls.append(idl_path) |
| 185 return idls |
| 186 |
| 187 def compute_dependencies(idl_files_list, event_names_filename, pickle_na
me): |
167 # Dummy files, required by compute_dependencies but not checked | 188 # Dummy files, required by compute_dependencies but not checked |
168 _, window_constructors_file = provider.newtempfile() | 189 _, window_constructors_file = provider.newtempfile() |
169 _, workerglobalscope_constructors_file = provider.newtempfile() | 190 _, workerglobalscope_constructors_file = provider.newtempfile() |
170 _, sharedworkerglobalscope_constructors_file = provider.newtempfile(
) | 191 _, sharedworkerglobalscope_constructors_file = provider.newtempfile(
) |
171 _, dedicatedworkerglobalscope_constructors_file = provider.newtempfi
le() | 192 _, dedicatedworkerglobalscope_constructors_file = provider.newtempfi
le() |
172 _, serviceworkersglobalscope_constructors_file = provider.newtempfil
e() | 193 _, serviceworkersglobalscope_constructors_file = provider.newtempfil
e() |
173 cmd = ['python', | |
174 'bindings/scripts/compute_dependencies.py', | |
175 '--idl-files-list', idl_files_list_filename, | |
176 '--interface-dependencies-file', self.interface_dependencies_
filename, | |
177 '--interfaces-info-file', self.interfaces_info_filename, | |
178 '--window-constructors-file', window_constructors_file, | |
179 '--workerglobalscope-constructors-file', workerglobalscope_co
nstructors_file, | |
180 '--sharedworkerglobalscope-constructors-file', sharedworkergl
obalscope_constructors_file, | |
181 '--dedicatedworkerglobalscope-constructors-file', dedicatedwo
rkerglobalscope_constructors_file, | |
182 '--serviceworkerglobalscope-constructors-file', serviceworker
sglobalscope_constructors_file, | |
183 '--event-names-file', event_names_filename, | |
184 '--write-file-only-if-changed', '0'] | |
185 self.run_command(cmd) | |
186 | 194 |
187 test_idl_files_list_filename = write_list_file(idl_paths(test_input_dire
ctory)) | 195 return compute(idl_files_list, |
188 all_idl_files_list_filename = write_list_file(idl_paths_recursive(all_in
put_directory)) | 196 self.interface_dependencies_filename, |
| 197 window_constructors_file, |
| 198 workerglobalscope_constructors_file, |
| 199 sharedworkerglobalscope_constructors_file, |
| 200 dedicatedworkerglobalscope_constructors_file, |
| 201 serviceworkersglobalscope_constructors_file, |
| 202 event_names_filename, False) |
| 203 |
| 204 test_idl_files_list = list_idl_file(idl_paths(test_input_directory)) |
| 205 all_idl_files_list = list_idl_file(idl_paths_recursive(all_input_directo
ry)) |
189 | 206 |
190 if self.reset_results and self.verbose: | 207 if self.reset_results and self.verbose: |
191 print 'Reset results: EventInterfaces.in' | 208 print 'Reset results: EventInterfaces.in' |
192 try: | 209 try: |
193 # We first compute dependencies for testing files only, | 210 # We first compute dependencies for testing files only, |
194 # so we can compare EventInterfaces.in. | 211 # so we can compare EventInterfaces.in. |
195 compute_dependencies(test_idl_files_list_filename, | 212 compute_dependencies(test_idl_files_list, self.event_names_filename, |
196 self.event_names_filename) | 213 self.interfaces_info_filename) |
197 | 214 |
198 # We then compute dependencies for all IDL files, as code generator | 215 # We then compute dependencies for all IDL files, as code generator |
199 # output depends on inheritance (both ancestor chain and inherited | 216 # output depends on inheritance (both ancestor chain and inherited |
200 # extended attributes), and some real interfaces are special-cased, | 217 # extended attributes), and some real interfaces are special-cased, |
201 # such as Node. | 218 # such as Node. |
202 # For example, when testing the behavior of interfaces that inherit | 219 # For example, when testing the behavior of interfaces that inherit |
203 # from Node, we also need to know that these inherit from | 220 # from Node, we also need to know that these inherit from |
204 # EventTarget, since this is also special-cased and Node inherits | 221 # EventTarget, since this is also special-cased and Node inherits |
205 # from EventTarget, but this inheritance information requires | 222 # from EventTarget, but this inheritance information requires |
206 # computing dependencies for the real Node.idl file. | 223 # computing dependencies for the real Node.idl file. |
207 # | 224 # |
208 # Don't overwrite the event names file generated for testing IDLs | 225 # Don't overwrite the event names file generated for testing IDLs |
209 _, dummy_event_names_filename = provider.newtempfile() | 226 _, dummy_event_names_filename = provider.newtempfile() |
210 compute_dependencies(all_idl_files_list_filename, | 227 self.interfaces_info = compute_dependencies(all_idl_files_list, |
211 dummy_event_names_filename) | 228 dummy_event_names_filena
me, |
| 229 self.interfaces_info_fil
ename) |
212 except ScriptError, e: | 230 except ScriptError, e: |
213 print 'ERROR: compute_dependencies.py' | 231 print 'ERROR: compute_dependencies.py' |
214 print e.output | 232 print e.output |
215 return e.exit_code | 233 return e.exit_code |
216 return 0 | 234 return 0 |
217 | 235 |
218 def identical_file(self, reference_filename, output_filename): | 236 def identical_file(self, reference_filename, output_filename): |
219 reference_basename = os.path.basename(reference_filename) | 237 reference_basename = os.path.basename(reference_filename) |
220 cmd = ['diff', | 238 cmd = ['diff', |
221 '-u', | 239 '-u', |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 | 321 |
304 all_tests_passed = self.run_tests() | 322 all_tests_passed = self.run_tests() |
305 if all_tests_passed: | 323 if all_tests_passed: |
306 if self.verbose: | 324 if self.verbose: |
307 print | 325 print |
308 print PASS_MESSAGE | 326 print PASS_MESSAGE |
309 return 0 | 327 return 0 |
310 print | 328 print |
311 print FAIL_MESSAGE | 329 print FAIL_MESSAGE |
312 return -1 | 330 return -1 |
OLD | NEW |