| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2009 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Docbuilder for extension docs.""" | 6 """Docbuilder for extension docs.""" |
| 7 | 7 |
| 8 import os | 8 import os |
| 9 import os.path | 9 import os.path |
| 10 import shutil | 10 import shutil |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 | 35 |
| 36 # HACK! This is required because we can only depend on python 2.4 and | 36 # HACK! This is required because we can only depend on python 2.4 and |
| 37 # the calling environment may not be setup to set the PYTHONPATH | 37 # the calling environment may not be setup to set the PYTHONPATH |
| 38 sys.path.append(os.path.normpath(_base_dir + | 38 sys.path.append(os.path.normpath(_base_dir + |
| 39 "/../../../../third_party")) | 39 "/../../../../third_party")) |
| 40 import simplejson as json | 40 import simplejson as json |
| 41 from directory import Sample | 41 from directory import Sample |
| 42 from directory import ApiManifest | 42 from directory import ApiManifest |
| 43 from directory import SamplesManifest | 43 from directory import SamplesManifest |
| 44 | 44 |
| 45 def RenderPages(names, test_shell): | 45 def RenderPages(names, dump_render_tree): |
| 46 """ | 46 """ |
| 47 Calls test_shell --layout-tests .../generator.html?<names> and writes the | 47 Calls DumpRenderTree .../generator.html?<names> and writes the |
| 48 results to .../docs/<name>.html | 48 results to .../docs/<name>.html |
| 49 """ | 49 """ |
| 50 if not names: | 50 if not names: |
| 51 raise Exception("RenderPage called with empty names param") | 51 raise Exception("RenderPage called with empty names param") |
| 52 | 52 |
| 53 generator_url = "file:" + urllib.pathname2url(_generator_html) | 53 generator_url = "file:" + urllib.pathname2url(_generator_html) |
| 54 generator_url += "?" + ",".join(names) | 54 generator_url += "?" + ",".join(names) |
| 55 | 55 |
| 56 # Start with a fresh copy of page shell for each file. | 56 # Start with a fresh copy of page shell for each file. |
| 57 # Save the current contents so that we can look for changes later. | 57 # Save the current contents so that we can look for changes later. |
| 58 originals = {} | 58 originals = {} |
| 59 for name in names: | 59 for name in names: |
| 60 input_file = _base_dir + "/" + name + ".html" | 60 input_file = _base_dir + "/" + name + ".html" |
| 61 | 61 |
| 62 if (os.path.isfile(input_file)): | 62 if (os.path.isfile(input_file)): |
| 63 originals[name] = open(input_file, 'rb').read() | 63 originals[name] = open(input_file, 'rb').read() |
| 64 os.remove(input_file) | 64 os.remove(input_file) |
| 65 else: | 65 else: |
| 66 originals[name] = "" | 66 originals[name] = "" |
| 67 | 67 |
| 68 shutil.copy(_page_shell_html, input_file) | 68 shutil.copy(_page_shell_html, input_file) |
| 69 | 69 |
| 70 # Run test_shell and capture result | 70 # Run DumpRenderTree and capture result |
| 71 test_shell_timeout = 1000 * 60 * 5 # five minutes | 71 dump_render_tree_timeout = 1000 * 60 * 5 # five minutes |
| 72 p = Popen( | 72 p = Popen( |
| 73 [test_shell, "--layout-tests", "--time-out-ms=%s" % test_shell_timeout, | 73 [dump_render_tree, "--test-shell", |
| 74 generator_url], | 74 "%s %s" % (generator_url, dump_render_tree_timeout)], |
| 75 stdout=PIPE) | 75 stdout=PIPE) |
| 76 | 76 |
| 77 # The remaining output will be the content of the generated pages. | 77 # The remaining output will be the content of the generated pages. |
| 78 output = p.stdout.read() | 78 output = p.stdout.read() |
| 79 | 79 |
| 80 # Parse out just the JSON part. | 80 # Parse out just the JSON part. |
| 81 begin = output.find(_expected_output_preamble) | 81 begin = output.find(_expected_output_preamble) |
| 82 end = output.rfind(_expected_output_postamble) | 82 end = output.rfind(_expected_output_postamble) |
| 83 | 83 |
| 84 if (begin < 0 or end < 0): | 84 if (begin < 0 or end < 0): |
| 85 raise Exception ("test_shell returned invalid output:\n\n" + output) | 85 raise Exception("%s returned invalid output:\n\n%s" % |
| 86 (dump_render_tree, output)) |
| 86 | 87 |
| 87 begin += len(_expected_output_preamble) | 88 begin += len(_expected_output_preamble) |
| 88 | 89 |
| 89 try: | 90 try: |
| 90 output_parsed = json.loads(output[begin:end]) | 91 output_parsed = json.loads(output[begin:end]) |
| 91 except ValueError, msg: | 92 except ValueError, msg: |
| 92 raise Exception("Could not parse test_shell output as JSON. Error: " + msg + | 93 raise Exception("Could not parse DumpRenderTree output as JSON. Error: " + |
| 93 "\n\nOutput was:\n" + output) | 94 msg + "\n\nOutput was:\n" + output) |
| 94 | 95 |
| 95 changed_files = [] | 96 changed_files = [] |
| 96 for name in names: | 97 for name in names: |
| 97 result = output_parsed[name].encode("utf8") + '\n' | 98 result = output_parsed[name].encode("utf8") + '\n' |
| 98 | 99 |
| 99 # Remove CRs that are appearing from captured test_shell output. | 100 # Remove CRs that are appearing from captured DumpRenderTree output. |
| 100 result = result.replace('\r', '') | 101 result = result.replace('\r', '') |
| 101 | 102 |
| 102 # Remove page_shell | 103 # Remove page_shell |
| 103 input_file = _base_dir + "/" + name + ".html" | 104 input_file = _base_dir + "/" + name + ".html" |
| 104 os.remove(input_file) | 105 os.remove(input_file) |
| 105 | 106 |
| 106 # Write output | 107 # Write output |
| 107 open(input_file, 'wb').write(result) | 108 open(input_file, 'wb').write(result) |
| 108 if (originals[name] and result != originals[name]): | 109 if (originals[name] and result != originals[name]): |
| 109 changed_files.append(input_file) | 110 changed_files.append(input_file) |
| 110 | 111 |
| 111 return changed_files | 112 return changed_files |
| 112 | 113 |
| 113 | 114 |
| 114 def FindTestShell(): | 115 def FindDumpRenderTree(): |
| 115 # This is hacky. It is used to guess the location of the test_shell | 116 # This is hacky. It is used to guess the location of the DumpRenderTree |
| 116 chrome_dir = os.path.normpath(_base_dir + "/../../../") | 117 chrome_dir = os.path.normpath(_base_dir + "/../../../") |
| 117 src_dir = os.path.normpath(chrome_dir + "/../") | 118 src_dir = os.path.normpath(chrome_dir + "/../") |
| 118 | 119 |
| 119 search_locations = [] | 120 search_locations = [] |
| 120 | 121 |
| 121 if (sys.platform in ('cygwin', 'win32')): | 122 if (sys.platform in ('cygwin', 'win32')): |
| 122 home_dir = os.path.normpath(os.getenv("HOMEDRIVE") + os.getenv("HOMEPATH")) | 123 home_dir = os.path.normpath(os.getenv("HOMEDRIVE") + os.getenv("HOMEPATH")) |
| 123 search_locations.append(chrome_dir + "/Release/test_shell.exe") | 124 search_locations.append(chrome_dir + "/Release/DumpRenderTree.exe") |
| 124 search_locations.append(chrome_dir + "/Debug/test_shell.exe") | 125 search_locations.append(chrome_dir + "/Debug/DumpRenderTree.exe") |
| 125 search_locations.append(home_dir + "/bin/test_shell/" + | 126 search_locations.append(home_dir + "/bin/DumpRenderTree/" |
| 126 "test_shell.exe") | 127 "DumpRenderTree.exe") |
| 127 | 128 |
| 128 if (sys.platform in ('linux', 'linux2')): | 129 if (sys.platform in ('linux', 'linux2')): |
| 129 search_locations.append(src_dir + "/sconsbuild/Release/test_shell") | 130 search_locations.append(src_dir + "/sconsbuild/Release/DumpRenderTree") |
| 130 search_locations.append(src_dir + "/out/Release/test_shell") | 131 search_locations.append(src_dir + "/out/Release/DumpRenderTree") |
| 131 search_locations.append(src_dir + "/sconsbuild/Debug/test_shell") | 132 search_locations.append(src_dir + "/sconsbuild/Debug/DumpRenderTree") |
| 132 search_locations.append(src_dir + "/out/Debug/test_shell") | 133 search_locations.append(src_dir + "/out/Debug/DumpRenderTree") |
| 133 search_locations.append(os.getenv("HOME") + "/bin/test_shell/test_shell") | 134 search_locations.append(os.getenv("HOME") + "/bin/DumpRenderTree/" |
| 135 "DumpRenderTree") |
| 134 | 136 |
| 135 if (sys.platform == 'darwin'): | 137 if (sys.platform == 'darwin'): |
| 136 search_locations.append(src_dir + | 138 search_locations.append(src_dir + |
| 137 "/xcodebuild/Release/TestShell.app/Contents/MacOS/TestShell") | 139 "/xcodebuild/Release/DumpRenderTree.app/Contents/MacOS/DumpRenderTree") |
| 138 search_locations.append(src_dir + | 140 search_locations.append(src_dir + |
| 139 "/xcodebuild/Debug/TestShell.app/Contents/MacOS/TestShell") | 141 "/xcodebuild/Debug/DumpRenderTree.app/Contents/MacOS/DumpRenderTree") |
| 140 search_locations.append(os.getenv("HOME") + "/bin/test_shell/" + | 142 search_locations.append(os.getenv("HOME") + "/bin/DumpRenderTree/" + |
| 141 "TestShell.app/Contents/MacOS/TestShell") | 143 "DumpRenderTree.app/Contents/MacOS/DumpRenderTree") |
| 142 | 144 |
| 143 for loc in search_locations: | 145 for loc in search_locations: |
| 144 if os.path.isfile(loc): | 146 if os.path.isfile(loc): |
| 145 return loc | 147 return loc |
| 146 | 148 |
| 147 raise Exception("Could not find test_shell executable\n" + | 149 raise Exception("Could not find DumpRenderTree executable\n" |
| 148 "**test_shell may need to be built**\n" + | 150 "**DumpRenderTree may need to be built**\n" |
| 149 "Searched: \n" + "\n".join(search_locations) + "\n" + | 151 "Searched: \n" + "\n".join(search_locations) + "\n" |
| 150 "To specify a path to test_shell use --test-shell-path") | 152 "To specify a path to DumpRenderTree use " |
| 153 "--dump-render-tree-path") |
| 151 | 154 |
| 152 def GetStaticFileNames(): | 155 def GetStaticFileNames(): |
| 153 static_files = os.listdir(_static_dir) | 156 static_files = os.listdir(_static_dir) |
| 154 return set(os.path.splitext(file_name)[0] | 157 return set(os.path.splitext(file_name)[0] |
| 155 for file_name in static_files | 158 for file_name in static_files |
| 156 if file_name.endswith(".html") and not file_name.startswith(".")) | 159 if file_name.endswith(".html") and not file_name.startswith(".")) |
| 157 | 160 |
| 158 def main(): | 161 def main(): |
| 159 # Prevent windows from using cygwin python. | 162 # Prevent windows from using cygwin python. |
| 160 if (sys.platform == "cygwin"): | 163 if (sys.platform == "cygwin"): |
| 161 sys.exit("Building docs not supported for cygwin python. Please run the " | 164 sys.exit("Building docs not supported for cygwin python. Please run the " |
| 162 "build.sh script instead, which uses depot_tools python.") | 165 "build.sh script instead, which uses depot_tools python.") |
| 163 | 166 |
| 164 parser = OptionParser() | 167 parser = OptionParser() |
| 165 parser.add_option("--test-shell-path", dest="test_shell_path", | 168 parser.add_option("--dump-render-tree-path", dest="dump_render_tree_path", |
| 166 metavar="PATH", | 169 metavar="PATH", |
| 167 help="path to test_shell executable") | 170 help="path to DumpRenderTree executable") |
| 168 parser.add_option("--page-name", dest="page_name", metavar="PAGE", | 171 parser.add_option("--page-name", dest="page_name", metavar="PAGE", |
| 169 help="only generate docs for PAGE.html") | 172 help="only generate docs for PAGE.html") |
| 170 parser.add_option("--nozip", dest="zips", action="store_false", | 173 parser.add_option("--nozip", dest="zips", action="store_false", |
| 171 help="do not generate zip files for samples", | 174 help="do not generate zip files for samples", |
| 172 default=True) | 175 default=True) |
| 173 (options, args) = parser.parse_args() | 176 options, args = parser.parse_args() |
| 174 | 177 |
| 175 if (options.test_shell_path and os.path.isfile(options.test_shell_path)): | 178 if (options.dump_render_tree_path and |
| 176 test_shell = options.test_shell_path | 179 os.path.isfile(options.dump_render_tree_path)): |
| 180 dump_render_tree = options.dump_render_tree_path |
| 177 else: | 181 else: |
| 178 test_shell = FindTestShell() | 182 dump_render_tree = FindDumpRenderTree() |
| 179 | 183 |
| 180 # Load the manifest of existing API Methods | 184 # Load the manifest of existing API Methods |
| 181 api_manifest = ApiManifest(_extension_api_json) | 185 api_manifest = ApiManifest(_extension_api_json) |
| 182 | 186 |
| 183 # Read static file names | 187 # Read static file names |
| 184 static_names = GetStaticFileNames() | 188 static_names = GetStaticFileNames() |
| 185 | 189 |
| 186 # Read module names | 190 # Read module names |
| 187 module_names = api_manifest.getModuleNames() | 191 module_names = api_manifest.getModuleNames() |
| 188 | 192 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 201 samples_manifest = SamplesManifest(_samples_dir, _base_dir, api_manifest) | 205 samples_manifest = SamplesManifest(_samples_dir, _base_dir, api_manifest) |
| 202 samples_manifest.writeToFile(_samples_json) | 206 samples_manifest.writeToFile(_samples_json) |
| 203 | 207 |
| 204 # Write zipped versions of the samples listed in the manifest to the | 208 # Write zipped versions of the samples listed in the manifest to the |
| 205 # filesystem, unless the user has disabled it | 209 # filesystem, unless the user has disabled it |
| 206 if options.zips: | 210 if options.zips: |
| 207 modified_zips = samples_manifest.writeZippedSamples() | 211 modified_zips = samples_manifest.writeZippedSamples() |
| 208 else: | 212 else: |
| 209 modified_zips = [] | 213 modified_zips = [] |
| 210 | 214 |
| 211 modified_files = RenderPages(page_names, test_shell) | 215 modified_files = RenderPages(page_names, dump_render_tree) |
| 212 modified_files.extend(modified_zips) | 216 modified_files.extend(modified_zips) |
| 213 | 217 |
| 214 if len(modified_files) == 0: | 218 if len(modified_files) == 0: |
| 215 print "Output files match existing files. No changes made." | 219 print "Output files match existing files. No changes made." |
| 216 else: | 220 else: |
| 217 print ("ATTENTION: EXTENSION DOCS HAVE CHANGED\n" + | 221 print ("ATTENTION: EXTENSION DOCS HAVE CHANGED\n" + |
| 218 "The following files have been modified and should be checked\n" + | 222 "The following files have been modified and should be checked\n" + |
| 219 "into source control (ideally in the same changelist as the\n" + | 223 "into source control (ideally in the same changelist as the\n" + |
| 220 "underlying files that resulting in their changing).") | 224 "underlying files that resulting in their changing).") |
| 221 for f in modified_files: | 225 for f in modified_files: |
| 222 print " * %s" % f | 226 print " * %s" % f |
| 223 | 227 |
| 224 # Hack. Sleep here, otherwise windows doesn't properly close the debug.log | 228 # Hack. Sleep here, otherwise windows doesn't properly close the debug.log |
| 225 # and the os.remove will fail with a "Permission denied". | 229 # and the os.remove will fail with a "Permission denied". |
| 226 time.sleep(1) | 230 time.sleep(1) |
| 227 debug_log = os.path.normpath(_build_dir + "/" + "debug.log") | 231 debug_log = os.path.normpath(_build_dir + "/" + "debug.log") |
| 228 if (os.path.isfile(debug_log)): | 232 if (os.path.isfile(debug_log)): |
| 229 os.remove(debug_log) | 233 os.remove(debug_log) |
| 230 | 234 |
| 231 if 'EX_OK' in dir(os): | 235 if 'EX_OK' in dir(os): |
| 232 return os.EX_OK | 236 return os.EX_OK |
| 233 else: | 237 else: |
| 234 return 0 | 238 return 0 |
| 235 | 239 |
| 236 if __name__ == '__main__': | 240 if __name__ == '__main__': |
| 237 sys.exit(main()) | 241 sys.exit(main()) |
| OLD | NEW |