| 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 |