run-bindings-tests is not Win32-compatible
[WebKit-https.git] / Tools / Scripts / webkitpy / bindings / main.py
1 # Copyright (C) 2011 Google Inc.  All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions
5 # are met:
6 # 1. Redistributions of source code must retain the above copyright
7 #    notice, this list of conditions and the following disclaimer.
8 # 2. Redistributions in binary form must reproduce the above copyright
9 #    notice, this list of conditions and the following disclaimer in the
10 #    documentation and/or other materials provided with the distribution.
11 #
12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
13 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
15 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
16 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
17 # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
18 # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
19 # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
20 # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
23 #
24
25 import fnmatch
26 import json
27 import os
28 import os.path
29 import shutil
30 import subprocess
31 import sys
32 import tempfile
33 from webkitpy.common.checkout.scm.detection import detect_scm_system
34 from webkitpy.common.system.executive import ScriptError
35
36
37 class BindingsTests:
38
39     def __init__(self, reset_results, generators, executive, verbose, patterns, json_file_name):
40         self.reset_results = reset_results
41         self.generators = generators
42         self.executive = executive
43         self.verbose = verbose
44         self.patterns = patterns
45         self.json_file_name = json_file_name
46
47         if self.json_file_name:
48             self.failures = []
49
50     def generate_from_idl(self, generator, idl_file, output_directory, supplemental_dependency_file):
51         cmd = ['perl', '-w',
52                '-IWebCore/bindings/scripts',
53                'WebCore/bindings/scripts/generate-bindings.pl',
54                # idl include directories (path relative to generate-bindings.pl)
55                '--include', '.',
56                '--defines', 'TESTING_%s' % generator,
57                '--generator', generator,
58                '--outputDir', output_directory,
59                '--supplementalDependencyFile', supplemental_dependency_file,
60                '--idlAttributesFile', 'WebCore/bindings/scripts/IDLAttributes.json',
61                idl_file]
62
63         exit_code = 0
64         try:
65             output = self.executive.run_command(cmd)
66             if output:
67                 print(output)
68         except ScriptError as e:
69             print(e.output)
70             exit_code = e.exit_code
71         return exit_code
72
73     def generate_supplemental_dependency(self, input_directory, supplemental_dependency_file, window_constructors_file, workerglobalscope_constructors_file, dedicatedworkerglobalscope_constructors_file, serviceworkerglobalscope_constructors_file):
74         idl_files_list = tempfile.mkstemp()
75         for input_file in os.listdir(input_directory):
76             (name, extension) = os.path.splitext(input_file)
77             if extension != '.idl':
78                 continue
79             os.write(idl_files_list[0], os.path.join(input_directory, input_file) + "\n")
80         os.close(idl_files_list[0])
81
82         cmd = ['perl', '-w',
83                '-IWebCore/bindings/scripts',
84                'WebCore/bindings/scripts/preprocess-idls.pl',
85                '--idlFilesList', idl_files_list[1],
86                '--defines', '',
87                '--supplementalDependencyFile', supplemental_dependency_file,
88                '--windowConstructorsFile', window_constructors_file,
89                '--workerGlobalScopeConstructorsFile', workerglobalscope_constructors_file,
90                '--dedicatedWorkerGlobalScopeConstructorsFile', dedicatedworkerglobalscope_constructors_file,
91                '--serviceWorkerGlobalScopeConstructorsFile', serviceworkerglobalscope_constructors_file]
92
93         exit_code = 0
94         try:
95             output = self.executive.run_command(cmd)
96             if output:
97                 print(output)
98         except ScriptError as e:
99             print(e.output)
100             exit_code = e.exit_code
101         os.remove(idl_files_list[1])
102         return exit_code
103
104     def detect_changes(self, generator, work_directory, reference_directory):
105         changes_found = False
106         for output_file in os.listdir(work_directory):
107             cmd = ['diff',
108                    '-u',
109                    '-N',
110                    os.path.join(reference_directory, output_file),
111                    os.path.join(work_directory, output_file)]
112
113             exit_code = 0
114             try:
115                 output = self.executive.run_command(cmd)
116             except ScriptError as e:
117                 output = e.output
118                 exit_code = e.exit_code
119
120             if exit_code or output:
121                 print('FAIL: (%s) %s' % (generator, output_file))
122                 print(output)
123                 changes_found = True
124                 if self.json_file_name:
125                     self.failures.append("(%s) %s" % (generator, output_file))
126             elif self.verbose:
127                 print('PASS: (%s) %s' % (generator, output_file))
128         return changes_found
129
130     def test_matches_patterns(self, test):
131         if not self.patterns:
132             return True
133         for pattern in self.patterns:
134             if fnmatch.fnmatch(test, pattern):
135                 return True
136         return False
137
138     def run_tests(self, generator, input_directory, reference_directory, supplemental_dependency_file):
139         work_directory = reference_directory
140
141         passed = True
142         for input_file in os.listdir(input_directory):
143             (name, extension) = os.path.splitext(input_file)
144             if extension != '.idl':
145                 continue
146
147             if not self.test_matches_patterns(input_file):
148                 continue
149
150             # Generate output into the work directory (either the given one or a
151             # temp one if not reset_results is performed)
152             if not self.reset_results:
153                 work_directory = tempfile.mkdtemp()
154
155             if self.generate_from_idl(generator,
156                                       os.path.join(input_directory, input_file),
157                                       work_directory,
158                                       supplemental_dependency_file):
159                 passed = False
160
161             if self.reset_results:
162                 print("Reset results: (%s) %s" % (generator, input_file))
163                 continue
164
165             # Detect changes
166             if self.detect_changes(generator, work_directory, reference_directory):
167                 passed = False
168             shutil.rmtree(work_directory)
169
170         return passed
171
172     def main(self):
173         current_scm = detect_scm_system(os.curdir)
174         os.chdir(os.path.join(current_scm.checkout_root, 'Source'))
175
176         all_tests_passed = True
177
178         input_directory = os.path.join('WebCore', 'bindings', 'scripts', 'test')
179         supplemental_dependency_file = tempfile.NamedTemporaryFile()
180         window_constructors_file = tempfile.NamedTemporaryFile()
181         workerglobalscope_constructors_file = tempfile.NamedTemporaryFile()
182         dedicatedworkerglobalscope_constructors_file = tempfile.NamedTemporaryFile()
183         serviceworkerglobalscope_constructors_file = tempfile.NamedTemporaryFile()
184         if self.generate_supplemental_dependency(input_directory, supplemental_dependency_file.name, window_constructors_file.name, workerglobalscope_constructors_file.name, dedicatedworkerglobalscope_constructors_file.name, serviceworkerglobalscope_constructors_file.name):
185             print('Failed to generate a supplemental dependency file.')
186             return -1
187
188         for generator in self.generators:
189             input_directory = os.path.join('WebCore', 'bindings', 'scripts', 'test')
190             reference_directory = os.path.join('WebCore', 'bindings', 'scripts', 'test', generator)
191             if not self.run_tests(generator, input_directory, reference_directory, supplemental_dependency_file.name):
192                 all_tests_passed = False
193
194         if self.json_file_name:
195             json_data = {
196                 'failures': self.failures,
197             }
198
199             with open(self.json_file_name, 'w') as json_file:
200                 json.dump(json_data, json_file)
201
202         print('')
203         if all_tests_passed:
204             print('All tests PASS!')
205             return 0
206         else:
207             print('Some tests FAIL! (To update the reference files, execute "run-bindings-tests --reset-results")')
208             return -1