| OLD | NEW |
| (Empty) | |
| 1 #! -*- python -*- |
| 2 # Copyright (c) 2012 The Native Client Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. |
| 5 |
| 6 import json |
| 7 import os |
| 8 import shutil |
| 9 import sys |
| 10 |
| 11 sys.path.append(Dir('#/tools').abspath) |
| 12 import command_tester |
| 13 import test_lib |
| 14 |
| 15 Import(['pre_base_env']) |
| 16 |
| 17 # Underlay things migrating to ppapi repo. |
| 18 Dir('#/..').addRepository(Dir('#/../ppapi')) |
| 19 |
| 20 # Load a config file from the Chrome repo. This allows scons files to be added |
| 21 # and removed in Chrome without requiring a DEPS roll. |
| 22 ppapi_scons_files = {} |
| 23 execfile( |
| 24 File('#/../ppapi/native_client/ppapi_scons_files.py').abspath, |
| 25 {}, # Globals |
| 26 ppapi_scons_files) |
| 27 |
| 28 # Append a list of files to another, filtering out the files that already exist. |
| 29 # Filtering helps migrate declarations between repos by preventing redundant |
| 30 # declarations from causing an error. |
| 31 def ExtendFileList(existing, additional): |
| 32 # Avoid quadratic behavior by using a set. |
| 33 combined = set() |
| 34 for file_name in existing + additional: |
| 35 if file_name in combined: |
| 36 print 'WARNING: two references to file %s in the build.' % file_name |
| 37 combined.add(file_name) |
| 38 return sorted(combined) |
| 39 |
| 40 ppapi_scons_files['nonvariant_test_scons_files'] = ExtendFileList( |
| 41 ppapi_scons_files.get('nonvariant_test_scons_files', []), [ |
| 42 'tests/nacl_browser/browser_dynamic_library/nacl.scons', |
| 43 'tests/nacl_browser/browser_startup_time/nacl.scons', |
| 44 'tests/nacl_browser/exit_status/nacl.scons', |
| 45 'tests/nacl_browser/inbrowser_test_runner/nacl.scons', |
| 46 'tests/nacl_browser/manifest_file/nacl.scons', |
| 47 'tests/nacl_browser/nameservice/nacl.scons', |
| 48 'tests/nacl_browser/postmessage_redir/nacl.scons', |
| 49 'tests/nacl_browser/untrusted_crash_dump/nacl.scons', |
| 50 ]) |
| 51 |
| 52 ppapi_scons_files['irt_variant_test_scons_files'] = ExtendFileList( |
| 53 ppapi_scons_files.get('irt_variant_test_scons_files', []), [ |
| 54 # Disabled by Brad Chen 4 Sep to try to green Chromium |
| 55 # nacl_integration tests |
| 56 #'tests/nacl_browser/fault_injection/nacl.scons', |
| 57 'tests/nacl.scons', |
| 58 'tests/nacl_browser/pnacl_client_translator/nacl.scons', |
| 59 ]) |
| 60 |
| 61 ppapi_scons_files['untrusted_scons_files'] = ExtendFileList( |
| 62 ppapi_scons_files.get('untrusted_scons_files', []), [ |
| 63 'src/untrusted/irt_stub/nacl.scons', |
| 64 'src/untrusted/nacl_ppapi_util/nacl.scons', |
| 65 'src/untrusted/pnacl_irt_shim/nacl.scons', |
| 66 'src/untrusted/pnacl_support_extension/nacl.scons', |
| 67 ]) |
| 68 |
| 69 EXTRA_ENV = ['XAUTHORITY', 'HOME', 'DISPLAY', 'SSH_TTY', 'KRB5CCNAME'] |
| 70 |
| 71 def SetupBrowserEnv(env): |
| 72 for var_name in EXTRA_ENV: |
| 73 if var_name in os.environ: |
| 74 env['ENV'][var_name] = os.environ[var_name] |
| 75 |
| 76 pre_base_env.AddMethod(SetupBrowserEnv) |
| 77 |
| 78 |
| 79 def GetHeadlessPrefix(env): |
| 80 if env.Bit('browser_headless') and env.Bit('host_linux'): |
| 81 return ['xvfb-run', '--auto-servernum'] |
| 82 else: |
| 83 # Mac and Windows do not seem to have an equivalent. |
| 84 return [] |
| 85 |
| 86 pre_base_env.AddMethod(GetHeadlessPrefix) |
| 87 |
| 88 |
| 89 pre_base_env['CHROME_DOWNLOAD_DIR'] = \ |
| 90 pre_base_env.Dir(ARGUMENTS.get('chrome_binaries_dir', '#chromebinaries')) |
| 91 |
| 92 def ChromeBinaryArch(env): |
| 93 arch = env['BUILD_FULLARCH'] |
| 94 # Currently there are no 64-bit Chrome binaries for Windows or Mac OS X. |
| 95 if (env.Bit('host_windows') or env.Bit('host_mac')) and arch == 'x86-64': |
| 96 arch = 'x86-32' |
| 97 return arch |
| 98 |
| 99 pre_base_env.AddMethod(ChromeBinaryArch) |
| 100 |
| 101 |
| 102 def DownloadedChromeBinary(env): |
| 103 if env.Bit('host_linux'): |
| 104 os_name = 'linux' |
| 105 binary = 'chrome' |
| 106 elif env.Bit('host_windows'): |
| 107 os_name = 'windows' |
| 108 binary = 'chrome.exe' |
| 109 elif env.Bit('host_mac'): |
| 110 os_name = 'mac' |
| 111 binary = 'Chromium.app/Contents/MacOS/Chromium' |
| 112 else: |
| 113 raise Exception('Unsupported OS') |
| 114 |
| 115 arch = env.ChromeBinaryArch() |
| 116 return env.File(os.path.join('${CHROME_DOWNLOAD_DIR}', |
| 117 '%s_%s' % (os_name, arch), binary)) |
| 118 |
| 119 pre_base_env.AddMethod(DownloadedChromeBinary) |
| 120 |
| 121 |
| 122 def ChromeBinary(env): |
| 123 if 'chrome_browser_path' in ARGUMENTS: |
| 124 return env.File(env.SConstructAbsPath(ARGUMENTS['chrome_browser_path'])) |
| 125 else: |
| 126 return env.DownloadedChromeBinary() |
| 127 |
| 128 pre_base_env.AddMethod(ChromeBinary) |
| 129 |
| 130 |
| 131 def GetPPAPIPluginPath(env, allow_64bit_redirect=True): |
| 132 if 'force_ppapi_plugin' in ARGUMENTS: |
| 133 return env.SConstructAbsPath(ARGUMENTS['force_ppapi_plugin']) |
| 134 if env.Bit('mac'): |
| 135 fn = env.File('${STAGING_DIR}/ppNaClPlugin') |
| 136 else: |
| 137 fn = env.File('${STAGING_DIR}/${SHLIBPREFIX}ppNaClPlugin${SHLIBSUFFIX}') |
| 138 if allow_64bit_redirect and env.Bit('target_x86_64'): |
| 139 # On 64-bit Windows and on Mac, we need the 32-bit plugin because |
| 140 # the browser is 32-bit. |
| 141 # Unfortunately it is tricky to build the 32-bit plugin (and all the |
| 142 # libraries it needs) in a 64-bit build... so we'll assume it has already |
| 143 # been built in a previous invocation. |
| 144 # TODO(ncbray) better 32/64 builds. |
| 145 if env.Bit('windows'): |
| 146 fn = env.subst(fn).abspath.replace('-win-x86-64', '-win-x86-32') |
| 147 elif env.Bit('mac'): |
| 148 fn = env.subst(fn).abspath.replace('-mac-x86-64', '-mac-x86-32') |
| 149 return fn |
| 150 |
| 151 pre_base_env.AddMethod(GetPPAPIPluginPath) |
| 152 |
| 153 |
| 154 # runnable-ld.so log has following format: |
| 155 # lib_name => path_to_lib (0x....address) |
| 156 def ParseLibInfoInRunnableLdLog(line): |
| 157 pos = line.find(' => ') |
| 158 if pos < 0: |
| 159 return None |
| 160 lib_name = line[:pos].strip() |
| 161 lib_path = line[pos+4:] |
| 162 pos1 = lib_path.rfind(' (') |
| 163 if pos1 < 0: |
| 164 return None |
| 165 lib_path = lib_path[:pos1] |
| 166 return lib_name, lib_path |
| 167 |
| 168 |
| 169 # Expected name of the temporary .libs file which stores glibc library |
| 170 # dependencies in "lib_name => lib_info" format |
| 171 # (see ParseLibInfoInRunnableLdLog) |
| 172 def GlibcManifestLibsListFilename(manifest_base_name): |
| 173 return '${STAGING_DIR}/%s.libs' % manifest_base_name |
| 174 |
| 175 |
| 176 # Copy libs and manifest to the target directory. |
| 177 # source[0] is a manifest file |
| 178 # source[1] is a .libs file with a list of libs generated by runnable-ld.so |
| 179 def CopyLibsForExtensionCommand(target, source, env): |
| 180 source_manifest = str(source[0]) |
| 181 target_manifest = str(target[0]) |
| 182 shutil.copyfile(source_manifest, target_manifest) |
| 183 target_dir = os.path.dirname(target_manifest) |
| 184 libs_file = open(str(source[1]), 'r') |
| 185 for line in libs_file.readlines(): |
| 186 lib_info = ParseLibInfoInRunnableLdLog(line) |
| 187 if lib_info: |
| 188 lib_name, lib_path = lib_info |
| 189 # Note: This probably does NOT work with pnacl _pexes_ right now, because |
| 190 # the NEEDED metadata in the bitcode doesn't have the original file paths. |
| 191 # This should probably be done without such knowledge. |
| 192 if lib_path == 'NaClMain': |
| 193 # This is a fake file name, which we cannot copy. |
| 194 continue |
| 195 shutil.copyfile(lib_path, os.path.join(target_dir, lib_name)) |
| 196 shutil.copyfile(env.subst('${NACL_SDK_LIB}/runnable-ld.so'), |
| 197 os.path.join(target_dir, 'runnable-ld.so')) |
| 198 libs_file.close() |
| 199 |
| 200 |
| 201 # Extensions are loaded from directory on disk and so all dynamic libraries |
| 202 # they use must be copied to extension directory. The option --extra_serving_dir |
| 203 # does not help us in this case. |
| 204 def CopyLibsForExtension(env, target_dir, manifest): |
| 205 if not env.Bit('nacl_glibc'): |
| 206 return env.Install(target_dir, manifest) |
| 207 manifest_base_name = os.path.basename(str(env.subst(manifest))) |
| 208 lib_list_node = env.File(GlibcManifestLibsListFilename(manifest_base_name)) |
| 209 nmf_node = env.Command( |
| 210 target_dir + '/' + manifest_base_name, |
| 211 [manifest, lib_list_node], |
| 212 CopyLibsForExtensionCommand) |
| 213 return nmf_node |
| 214 |
| 215 pre_base_env.AddMethod(CopyLibsForExtension) |
| 216 |
| 217 |
| 218 |
| 219 def WhitelistLibsForExtensionCommand(target, source, env): |
| 220 # Load existing extension manifest. |
| 221 src_file = open(source[0].abspath, 'r') |
| 222 src_json = json.load(src_file) |
| 223 src_file.close() |
| 224 |
| 225 # Load existing 'web_accessible_resources' key. |
| 226 if 'web_accessible_resources' not in src_json: |
| 227 src_json['web_accessible_resources'] = [] |
| 228 web_accessible = src_json['web_accessible_resources'] |
| 229 |
| 230 # Load list of libraries, and add libraries to web_accessible list. |
| 231 libs_file = open(source[1].abspath, 'r') |
| 232 for line in libs_file.readlines(): |
| 233 lib_info = ParseLibInfoInRunnableLdLog(line) |
| 234 if lib_info: |
| 235 web_accessible.append(lib_info[0]) |
| 236 # Also add the dynamic loader, which won't be in the libs_file. |
| 237 web_accessible.append('runnable-ld.so') |
| 238 libs_file.close() |
| 239 |
| 240 # Write out the appended-to extension manifest. |
| 241 target_file = open(target[0].abspath, 'w') |
| 242 json.dump(src_json, target_file, sort_keys=True, indent=2) |
| 243 target_file.close() |
| 244 |
| 245 |
| 246 # Whitelist glibc shared libraries (if necessary), so that they are |
| 247 # 'web_accessible_resources'. This allows the libraries hosted at the origin |
| 248 # chrome-extension://[PACKAGE ID]/ |
| 249 # to be made available to webpages that use this NaCl extension, |
| 250 # which are in a different origin. |
| 251 # See: http://code.google.com/chrome/extensions/manifest.html |
| 252 # |
| 253 # Alternatively, we could try to use the chrome commandline switch |
| 254 # '--disable-extensions-resource-whitelist', but that would not be what |
| 255 # users will need to do. |
| 256 def WhitelistLibsForExtension(env, target_dir, nmf, extension_manifest): |
| 257 if env.Bit('nacl_static_link'): |
| 258 # For static linking, assume the nexe and nmf files are already |
| 259 # whitelisted, so there is no need to add entries to the extension_manifest. |
| 260 return env.Install(target_dir, extension_manifest) |
| 261 nmf_base_name = os.path.basename(env.File(nmf).abspath) |
| 262 lib_list_node = env.File(GlibcManifestLibsListFilename(nmf_base_name)) |
| 263 manifest_base_name = os.path.basename(env.File(extension_manifest).abspath) |
| 264 extension_manifest_node = env.Command( |
| 265 target_dir + '/' + manifest_base_name, |
| 266 [extension_manifest, lib_list_node], |
| 267 WhitelistLibsForExtensionCommand) |
| 268 return extension_manifest_node |
| 269 |
| 270 pre_base_env.AddMethod(WhitelistLibsForExtension) |
| 271 |
| 272 |
| 273 # Generate manifest from newlib manifest and the list of libs generated by |
| 274 # runnable-ld.so. |
| 275 def GenerateManifestFunc(target, source, env): |
| 276 # Open the original manifest and parse it. |
| 277 source_file = open(str(source[0]), 'r') |
| 278 obj = json.load(source_file) |
| 279 source_file.close() |
| 280 # Open the file with ldd-format list of NEEDED libs and parse it. |
| 281 libs_file = open(str(source[1]), 'r') |
| 282 lib_names = [] |
| 283 arch = env.subst('${TARGET_FULLARCH}') |
| 284 for line in libs_file.readlines(): |
| 285 lib_info = ParseLibInfoInRunnableLdLog(line) |
| 286 if lib_info: |
| 287 lib_name, _ = lib_info |
| 288 lib_names.append(lib_name) |
| 289 libs_file.close() |
| 290 # Inject the NEEDED libs into the manifest. |
| 291 if 'files' not in obj: |
| 292 obj['files'] = {} |
| 293 for lib_name in lib_names: |
| 294 obj['files'][lib_name] = {} |
| 295 obj['files'][lib_name][arch] = {} |
| 296 obj['files'][lib_name][arch]['url'] = lib_name |
| 297 # Put what used to be specified under 'program' into 'main.nexe'. |
| 298 obj['files']['main.nexe'] = {} |
| 299 for k, v in obj['program'].items(): |
| 300 obj['files']['main.nexe'][k] = v.copy() |
| 301 v['url'] = 'runnable-ld.so' |
| 302 # Write the new manifest! |
| 303 target_file = open(str(target[0]), 'w') |
| 304 json.dump(obj, target_file, sort_keys=True, indent=2) |
| 305 target_file.close() |
| 306 return 0 |
| 307 |
| 308 def GenerateManifestPnacl(env, dest_file, manifest, exe_file): |
| 309 return env.Command( |
| 310 dest_file, |
| 311 ['${GENNMF}', exe_file, manifest], |
| 312 # Generate a flat url scheme to simplify file-staging. |
| 313 ('${SOURCES[0]} ${SOURCES[1]} -L${NACL_SDK_LIB} -L${LIB_DIR} ' |
| 314 ' --flat-url-scheme --base-nmf ${SOURCES[2]} -o ${TARGET}')) |
| 315 |
| 316 def GenerateManifestDynamicLink(env, dest_file, lib_list_file, |
| 317 manifest, exe_file): |
| 318 # Run sel_ldr on the nexe to trace the NEEDED libraries. |
| 319 lib_list_node = env.Command( |
| 320 lib_list_file, |
| 321 [env.GetSelLdr(), |
| 322 '${NACL_SDK_LIB}/runnable-ld.so', |
| 323 exe_file, |
| 324 '${SCONSTRUCT_DIR}/DEPS'], |
| 325 # We ignore the return code using '-' in order to build tests |
| 326 # where binaries do not validate. This is a Scons feature. |
| 327 '-${SOURCES[0]} -a -E LD_TRACE_LOADED_OBJECTS=1 ${SOURCES[1]} ' |
| 328 '--library-path ${NACL_SDK_LIB}:${LIB_DIR} ${SOURCES[2].posix} ' |
| 329 '> ${TARGET}') |
| 330 return env.Command(dest_file, |
| 331 [manifest, lib_list_node], |
| 332 GenerateManifestFunc)[0] |
| 333 |
| 334 |
| 335 def GenerateSimpleManifestStaticLink(env, dest_file, exe_name): |
| 336 def Func(target, source, env): |
| 337 archs = ('x86-32', 'x86-64', 'arm') |
| 338 nmf_data = {'program': dict((arch, {'url': '%s_%s.nexe' % (exe_name, arch)}) |
| 339 for arch in archs)} |
| 340 fh = open(target[0].abspath, 'w') |
| 341 json.dump(nmf_data, fh, sort_keys=True, indent=2) |
| 342 fh.close() |
| 343 node = env.Command(dest_file, [], Func)[0] |
| 344 # Scons does not track the dependency of dest_file on exe_name or on |
| 345 # the Python code above, so we should always recreate dest_file when |
| 346 # it is used. |
| 347 env.AlwaysBuild(node) |
| 348 return node |
| 349 |
| 350 |
| 351 def GenerateSimpleManifest(env, dest_file, exe_name): |
| 352 if env.Bit('pnacl_generate_pexe'): |
| 353 static_manifest = GenerateSimpleManifestStaticLink( |
| 354 env, '%s.static' % dest_file, exe_name) |
| 355 return GenerateManifestPnacl(env, dest_file, static_manifest, |
| 356 '${STAGING_DIR}/%s.pexe' % |
| 357 env.ProgramNameForNmf(exe_name)) |
| 358 elif env.Bit('nacl_static_link'): |
| 359 return GenerateSimpleManifestStaticLink(env, dest_file, exe_name) |
| 360 else: |
| 361 static_manifest = GenerateSimpleManifestStaticLink( |
| 362 env, '%s.static' % dest_file, exe_name) |
| 363 return GenerateManifestDynamicLink( |
| 364 env, dest_file, '%s.tmp_lib_list' % dest_file, static_manifest, |
| 365 '${STAGING_DIR}/%s.nexe' % env.ProgramNameForNmf(exe_name)) |
| 366 |
| 367 pre_base_env.AddMethod(GenerateSimpleManifest) |
| 368 |
| 369 |
| 370 # Returns a pair (main program, is_portable), based on the program |
| 371 # specified in manifest file. |
| 372 def GetMainProgramFromManifest(env, manifest): |
| 373 obj = json.loads(env.File(manifest).get_contents()) |
| 374 program_dict = obj['program'] |
| 375 if env.Bit('pnacl_generate_pexe') and 'portable' in program_dict: |
| 376 return program_dict['portable']['pnacl-translate']['url'] |
| 377 else: |
| 378 return program_dict[env.subst('${TARGET_FULLARCH}')]['url'] |
| 379 |
| 380 |
| 381 # Returns scons node for generated manifest. |
| 382 def GeneratedManifestNode(env, manifest): |
| 383 manifest = env.subst(manifest) |
| 384 manifest_base_name = os.path.basename(manifest) |
| 385 main_program = GetMainProgramFromManifest(env, manifest) |
| 386 result = env.File('${STAGING_DIR}/' + manifest_base_name) |
| 387 # Always generate the manifest for nacl_glibc and pnacl pexes. |
| 388 # For nacl_glibc, generating the mapping of shared libraries is non-trivial. |
| 389 # For pnacl, the manifest currently hosts a sha for the pexe. |
| 390 if not env.Bit('nacl_glibc') and not env.Bit('pnacl_generate_pexe'): |
| 391 env.Install('${STAGING_DIR}', manifest) |
| 392 return result |
| 393 if env.Bit('pnacl_generate_pexe'): |
| 394 return GenerateManifestPnacl( |
| 395 env, |
| 396 '${STAGING_DIR}/' + manifest_base_name, |
| 397 manifest, |
| 398 env.File('${STAGING_DIR}/' + os.path.basename(main_program))) |
| 399 else: |
| 400 return GenerateManifestDynamicLink( |
| 401 env, '${STAGING_DIR}/' + manifest_base_name, |
| 402 # Note that CopyLibsForExtension() and WhitelistLibsForExtension() |
| 403 # assume that it can find the library list file under this filename. |
| 404 GlibcManifestLibsListFilename(manifest_base_name), |
| 405 manifest, |
| 406 env.File('${STAGING_DIR}/' + os.path.basename(main_program))) |
| 407 return result |
| 408 |
| 409 |
| 410 def GetPnaclExtensionRootNode(env): |
| 411 """Get the scons node representing the root directory of pnacl support files. |
| 412 """ |
| 413 # This is "built" by src/untrusted/pnacl_support_extension/nacl.scons. |
| 414 return env.Dir('${DESTINATION_ROOT}/pnacl_support') |
| 415 |
| 416 pre_base_env.AddMethod(GetPnaclExtensionRootNode) |
| 417 |
| 418 def GetPnaclExtensionDummyVersion(env): |
| 419 """ We supply a dummy version number when packaging the test-extension |
| 420 that is probably newer than all other versions. """ |
| 421 return '9999.9.9.9' |
| 422 |
| 423 pre_base_env.AddMethod(GetPnaclExtensionDummyVersion) |
| 424 |
| 425 def GetPnaclExtensionNode(env): |
| 426 """Get the scons node representing a specific version of pnacl support files. |
| 427 """ |
| 428 # This is "built" by src/untrusted/pnacl_support_extension/nacl.scons. |
| 429 return env.Dir('${DESTINATION_ROOT}/pnacl_support/' + |
| 430 env.GetPnaclExtensionDummyVersion()) |
| 431 |
| 432 pre_base_env.AddMethod(GetPnaclExtensionNode) |
| 433 |
| 434 |
| 435 # Compares output_file and golden_file. |
| 436 # If they are different, prints the difference and returns 1. |
| 437 # Otherwise, returns 0. |
| 438 def CheckGoldenFile(golden_file, output_file, |
| 439 filter_regex, filter_inverse, filter_group_only): |
| 440 golden = open(golden_file).read() |
| 441 actual = open(output_file).read() |
| 442 if filter_regex is not None: |
| 443 actual = test_lib.RegexpFilterLines( |
| 444 filter_regex, |
| 445 filter_inverse, |
| 446 filter_group_only, |
| 447 actual) |
| 448 if command_tester.DifferentFromGolden(actual, golden, output_file): |
| 449 return 1 |
| 450 return 0 |
| 451 |
| 452 |
| 453 # Returns action that compares output_file and golden_file. |
| 454 # This action can be attached to the node with |
| 455 # env.AddPostAction(target, action) |
| 456 def GoldenFileCheckAction(env, output_file, golden_file, |
| 457 filter_regex=None, filter_inverse=False, |
| 458 filter_group_only=False): |
| 459 def ActionFunc(target, source, env): |
| 460 return CheckGoldenFile(env.subst(golden_file), env.subst(output_file), |
| 461 filter_regex, filter_inverse, filter_group_only) |
| 462 |
| 463 return env.Action(ActionFunc) |
| 464 |
| 465 |
| 466 def PPAPIBrowserTester(env, |
| 467 target, |
| 468 url, |
| 469 files, |
| 470 nmfs=None, |
| 471 # List of executable basenames to generate |
| 472 # manifest files for. |
| 473 nmf_names=(), |
| 474 map_files=(), |
| 475 extensions=(), |
| 476 mime_types=(), |
| 477 timeout=30, |
| 478 log_verbosity=2, |
| 479 args=[], |
| 480 # list of key/value pairs that are passed to the test |
| 481 test_args=(), |
| 482 # list of "--flag=value" pairs (no spaces!) |
| 483 browser_flags=None, |
| 484 # redirect streams of NaCl program to files |
| 485 nacl_exe_stdin=None, |
| 486 nacl_exe_stdout=None, |
| 487 nacl_exe_stderr=None, |
| 488 python_tester_script=None, |
| 489 **extra): |
| 490 if 'TRUSTED_ENV' not in env: |
| 491 return [] |
| 492 |
| 493 # No browser tests run on arm-thumb2 |
| 494 # Bug http://code.google.com/p/nativeclient/issues/detail?id=2224 |
| 495 if env.Bit('target_arm_thumb2'): |
| 496 return [] |
| 497 |
| 498 # Handle issues with mutating any python default arg lists. |
| 499 if browser_flags is None: |
| 500 browser_flags = [] |
| 501 |
| 502 if env.Bit('pnacl_generate_pexe'): |
| 503 # We likely prefer to choose the 'portable' field in nmfs in this mode. |
| 504 args = args + ['--prefer_portable_in_manifest'] |
| 505 # Pass through env var controlling streaming translation |
| 506 if 'NACL_STREAMING_TRANSLATION' in os.environ: |
| 507 env['ENV']['NACL_STREAMING_TRANSLATION'] = 'true' |
| 508 |
| 509 # Lint the extra arguments that are being passed to the tester. |
| 510 special_args = ['--ppapi_plugin', '--sel_ldr', '--irt_library', '--file', |
| 511 '--map_file', '--extension', '--mime_type', '--tool', |
| 512 '--browser_flag', '--test_arg'] |
| 513 for arg_name in special_args: |
| 514 if arg_name in args: |
| 515 raise Exception('%s: %r is a test argument provided by the SCons test' |
| 516 ' wrapper, do not specify it as an additional argument' % |
| 517 (target, arg_name)) |
| 518 |
| 519 env = env.Clone() |
| 520 env.SetupBrowserEnv() |
| 521 |
| 522 if 'scale_timeout' in ARGUMENTS: |
| 523 timeout = timeout * int(ARGUMENTS['scale_timeout']) |
| 524 |
| 525 if python_tester_script is None: |
| 526 python_tester_script = env.File('${SCONSTRUCT_DIR}/tools/browser_tester' |
| 527 '/browser_tester.py') |
| 528 command = env.GetHeadlessPrefix() + [ |
| 529 '${PYTHON}', python_tester_script, |
| 530 '--browser_path', env.ChromeBinary(), |
| 531 '--url', url, |
| 532 # Fail if there is no response for X seconds. |
| 533 '--timeout', str(timeout)] |
| 534 if not env.Bit('disable_dynamic_plugin_loading'): |
| 535 command.extend(['--ppapi_plugin', env['TRUSTED_ENV'].GetPPAPIPluginPath()]) |
| 536 command.extend(['--sel_ldr', env.GetSelLdr()]) |
| 537 bootstrap, _ = env.GetBootstrap() |
| 538 if bootstrap is not None: |
| 539 command.extend(['--sel_ldr_bootstrap', bootstrap]) |
| 540 if (not env.Bit('disable_dynamic_plugin_loading') or |
| 541 env.Bit('override_chrome_irt')): |
| 542 command.extend(['--irt_library', env.GetIrtNexe(chrome_irt=True)]) |
| 543 for dep_file in files: |
| 544 command.extend(['--file', dep_file]) |
| 545 for extension in extensions: |
| 546 command.extend(['--extension', extension]) |
| 547 if env.Bit('bitcode'): |
| 548 # TODO(jvoung): remove this --extension once we have --pnacl-dir working. |
| 549 command.extend(['--extension', env.GetPnaclExtensionNode().abspath]) |
| 550 # Enable the installed version of pnacl, and point to a custom install |
| 551 # directory for testing purposes. |
| 552 browser_flags.append('--enable-pnacl') |
| 553 browser_flags.append('--pnacl-dir=%s' % |
| 554 env.GetPnaclExtensionRootNode().abspath) |
| 555 for dest_path, dep_file in map_files: |
| 556 command.extend(['--map_file', dest_path, dep_file]) |
| 557 for file_ext, mime_type in mime_types: |
| 558 command.extend(['--mime_type', file_ext, mime_type]) |
| 559 command.extend(['--serving_dir', '${NACL_SDK_LIB}']) |
| 560 command.extend(['--serving_dir', '${LIB_DIR}']) |
| 561 if 'browser_tester_bw' in ARGUMENTS: |
| 562 command.extend(['-b', ARGUMENTS['browser_tester_bw']]) |
| 563 if not nmfs is None: |
| 564 for nmf_file in nmfs: |
| 565 generated_manifest = GeneratedManifestNode(env, nmf_file) |
| 566 # We need to add generated manifests to the list of default targets. |
| 567 # The manifests should be generated even if the tests are not run - |
| 568 # the manifests may be needed for manual testing. |
| 569 for group in env['COMPONENT_TEST_PROGRAM_GROUPS']: |
| 570 env.Alias(group, generated_manifest) |
| 571 # Generated manifests are served in the root of the HTTP server |
| 572 command.extend(['--file', generated_manifest]) |
| 573 for nmf_name in nmf_names: |
| 574 tmp_manifest = '%s.tmp/%s.nmf' % (target, nmf_name) |
| 575 command.extend(['--map_file', '%s.nmf' % nmf_name, |
| 576 env.GenerateSimpleManifest(tmp_manifest, nmf_name)]) |
| 577 if 'browser_test_tool' in ARGUMENTS: |
| 578 command.extend(['--tool', ARGUMENTS['browser_test_tool']]) |
| 579 |
| 580 # Suppress debugging information on the Chrome waterfall. |
| 581 if env.Bit('disable_flaky_tests') and '--debug' in args: |
| 582 args.remove('--debug') |
| 583 |
| 584 command.extend(args) |
| 585 for flag in browser_flags: |
| 586 if flag.find(' ') != -1: |
| 587 raise Exception('Spaces not allowed in browser_flags: ' |
| 588 'use --flag=value instead') |
| 589 command.extend(['--browser_flag', flag]) |
| 590 for key, value in test_args: |
| 591 command.extend(['--test_arg', str(key), str(value)]) |
| 592 |
| 593 # Set a given file to be the nexe's stdin. |
| 594 if nacl_exe_stdin is not None: |
| 595 command.extend(['--nacl_exe_stdin', env.subst(nacl_exe_stdin['file'])]) |
| 596 |
| 597 post_actions = [] |
| 598 side_effects = [] |
| 599 # Set a given file to be the nexe's stdout or stderr. The tester also |
| 600 # compares this output against a golden file. |
| 601 for stream, params in ( |
| 602 ('stdout', nacl_exe_stdout), |
| 603 ('stderr', nacl_exe_stderr)): |
| 604 if params is None: |
| 605 continue |
| 606 stream_file = env.subst(params['file']) |
| 607 side_effects.append(stream_file) |
| 608 command.extend(['--nacl_exe_' + stream, stream_file]) |
| 609 if 'golden' in params: |
| 610 golden_file = env.subst(params['golden']) |
| 611 filter_regex = params.get('filter_regex', None) |
| 612 filter_inverse = params.get('filter_inverse', False) |
| 613 filter_group_only = params.get('filter_group_only', False) |
| 614 post_actions.append( |
| 615 GoldenFileCheckAction( |
| 616 env, stream_file, golden_file, |
| 617 filter_regex, filter_inverse, filter_group_only)) |
| 618 |
| 619 if env.ShouldUseVerboseOptions(extra): |
| 620 env.MakeVerboseExtraOptions(target, log_verbosity, extra) |
| 621 # Heuristic for when to capture output... |
| 622 capture_output = (extra.pop('capture_output', False) |
| 623 or 'process_output_single' in extra) |
| 624 node = env.CommandTest(target, |
| 625 command, |
| 626 # Set to 'huge' so that the browser tester's timeout |
| 627 # takes precedence over the default of the test_suite. |
| 628 size='huge', |
| 629 capture_output=capture_output, |
| 630 **extra) |
| 631 # Also indicate that we depend on the layed-out pnacl translator. |
| 632 if env.Bit('bitcode'): |
| 633 env.Depends(node, env.GetPnaclExtensionNode()) |
| 634 for side_effect in side_effects: |
| 635 env.SideEffect(side_effect, node) |
| 636 # We can't check output if the test is not run. |
| 637 if not env.Bit('do_not_run_tests'): |
| 638 for action in post_actions: |
| 639 env.AddPostAction(node, action) |
| 640 return node |
| 641 |
| 642 pre_base_env.AddMethod(PPAPIBrowserTester) |
| 643 |
| 644 |
| 645 # Disabled for ARM and MIPS because Chrome binaries for ARM and MIPS are not |
| 646 # available. |
| 647 def PPAPIBrowserTesterIsBroken(env): |
| 648 return (env.Bit('target_arm') or env.Bit('target_arm_thumb2') |
| 649 or env.Bit('target_mips32')) |
| 650 |
| 651 pre_base_env.AddMethod(PPAPIBrowserTesterIsBroken) |
| 652 |
| 653 # 3D is disabled everywhere |
| 654 def PPAPIGraphics3DIsBroken(env): |
| 655 return True |
| 656 |
| 657 pre_base_env.AddMethod(PPAPIGraphics3DIsBroken) |
| 658 |
| 659 |
| 660 def AddChromeFilesFromGroup(env, file_group): |
| 661 env['BUILD_SCONSCRIPTS'] = ExtendFileList( |
| 662 env.get('BUILD_SCONSCRIPTS', []), |
| 663 ppapi_scons_files[file_group]) |
| 664 |
| 665 pre_base_env.AddMethod(AddChromeFilesFromGroup) |
| OLD | NEW |