| Index: ppapi/native_client/chrome_main.scons
|
| diff --git a/ppapi/native_client/chrome_main.scons b/ppapi/native_client/chrome_main.scons
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8eec0559990709672d962db5a80cb7830c75f8b0
|
| --- /dev/null
|
| +++ b/ppapi/native_client/chrome_main.scons
|
| @@ -0,0 +1,664 @@
|
| +#! -*- python -*-
|
| +# Copyright (c) 2012 The Native Client Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +import json
|
| +import os
|
| +import shutil
|
| +import sys
|
| +
|
| +sys.path.append(Dir('#/tools').abspath)
|
| +import command_tester
|
| +import test_lib
|
| +
|
| +Import(['pre_base_env'])
|
| +
|
| +# Underlay things migrating to ppapi repo.
|
| +Dir('#/..').addRepository(Dir('#/../ppapi'))
|
| +
|
| +# Load a config file from the Chrome repo. This allows scons files to be added
|
| +# and removed in Chrome without requiring a DEPS roll.
|
| +ppapi_scons_files = {}
|
| +execfile(
|
| + File('#/../ppapi/native_client/ppapi_scons_files.py').abspath,
|
| + {}, # Globals
|
| + ppapi_scons_files)
|
| +
|
| +# Append a list of files to another, filtering out the files that already exist.
|
| +# Filtering helps migrate declarations between repos by preventing redundant
|
| +# declarations from causing an error.
|
| +def ExtendFileList(existing, additional):
|
| + # Avoid quadratic behavior by using a set.
|
| + combined = set()
|
| + for file_name in existing + additional:
|
| + if file_name in combined:
|
| + print 'WARNING: two references to file %s in the build.' % file_name
|
| + combined.add(file_name)
|
| + return sorted(combined)
|
| +
|
| +ppapi_scons_files['nonvariant_test_scons_files'] = ExtendFileList(
|
| + ppapi_scons_files.get('nonvariant_test_scons_files', []), [
|
| + 'tests/nacl_browser/browser_dynamic_library/nacl.scons',
|
| + 'tests/nacl_browser/browser_startup_time/nacl.scons',
|
| + 'tests/nacl_browser/exit_status/nacl.scons',
|
| + 'tests/nacl_browser/inbrowser_test_runner/nacl.scons',
|
| + 'tests/nacl_browser/manifest_file/nacl.scons',
|
| + 'tests/nacl_browser/nameservice/nacl.scons',
|
| + 'tests/nacl_browser/postmessage_redir/nacl.scons',
|
| + ])
|
| +
|
| +ppapi_scons_files['irt_variant_test_scons_files'] = ExtendFileList(
|
| + ppapi_scons_files.get('irt_variant_test_scons_files', []), [
|
| + # Disabled by Brad Chen 4 Sep to try to green Chromium
|
| + # nacl_integration tests
|
| + #'tests/nacl_browser/fault_injection/nacl.scons',
|
| + 'tests/nacl.scons',
|
| + 'tests/nacl_browser/pnacl_client_translator/nacl.scons',
|
| + ])
|
| +
|
| +ppapi_scons_files['untrusted_scons_files'] = ExtendFileList(
|
| + ppapi_scons_files.get('untrusted_scons_files', []), [
|
| + 'src/untrusted/irt_stub/nacl.scons',
|
| + 'src/untrusted/nacl_ppapi_util/nacl.scons',
|
| + 'src/untrusted/pnacl_irt_shim/nacl.scons',
|
| + 'src/untrusted/pnacl_support_extension/nacl.scons',
|
| + ])
|
| +
|
| +EXTRA_ENV = ['XAUTHORITY', 'HOME', 'DISPLAY', 'SSH_TTY', 'KRB5CCNAME']
|
| +
|
| +def SetupBrowserEnv(env):
|
| + for var_name in EXTRA_ENV:
|
| + if var_name in os.environ:
|
| + env['ENV'][var_name] = os.environ[var_name]
|
| +
|
| +pre_base_env.AddMethod(SetupBrowserEnv)
|
| +
|
| +
|
| +def GetHeadlessPrefix(env):
|
| + if env.Bit('browser_headless') and env.Bit('host_linux'):
|
| + return ['xvfb-run', '--auto-servernum']
|
| + else:
|
| + # Mac and Windows do not seem to have an equivalent.
|
| + return []
|
| +
|
| +pre_base_env.AddMethod(GetHeadlessPrefix)
|
| +
|
| +
|
| +pre_base_env['CHROME_DOWNLOAD_DIR'] = \
|
| + pre_base_env.Dir(ARGUMENTS.get('chrome_binaries_dir', '#chromebinaries'))
|
| +
|
| +def ChromeBinaryArch(env):
|
| + arch = env['BUILD_FULLARCH']
|
| + # Currently there are no 64-bit Chrome binaries for Windows or Mac OS X.
|
| + if (env.Bit('host_windows') or env.Bit('host_mac')) and arch == 'x86-64':
|
| + arch = 'x86-32'
|
| + return arch
|
| +
|
| +pre_base_env.AddMethod(ChromeBinaryArch)
|
| +
|
| +
|
| +def DownloadedChromeBinary(env):
|
| + if env.Bit('host_linux'):
|
| + os_name = 'linux'
|
| + binary = 'chrome'
|
| + elif env.Bit('host_windows'):
|
| + os_name = 'windows'
|
| + binary = 'chrome.exe'
|
| + elif env.Bit('host_mac'):
|
| + os_name = 'mac'
|
| + binary = 'Chromium.app/Contents/MacOS/Chromium'
|
| + else:
|
| + raise Exception('Unsupported OS')
|
| +
|
| + arch = env.ChromeBinaryArch()
|
| + return env.File(os.path.join('${CHROME_DOWNLOAD_DIR}',
|
| + '%s_%s' % (os_name, arch), binary))
|
| +
|
| +pre_base_env.AddMethod(DownloadedChromeBinary)
|
| +
|
| +
|
| +def ChromeBinary(env):
|
| + if 'chrome_browser_path' in ARGUMENTS:
|
| + return env.File(env.SConstructAbsPath(ARGUMENTS['chrome_browser_path']))
|
| + else:
|
| + return env.DownloadedChromeBinary()
|
| +
|
| +pre_base_env.AddMethod(ChromeBinary)
|
| +
|
| +
|
| +def GetPPAPIPluginPath(env, allow_64bit_redirect=True):
|
| + if 'force_ppapi_plugin' in ARGUMENTS:
|
| + return env.SConstructAbsPath(ARGUMENTS['force_ppapi_plugin'])
|
| + if env.Bit('mac'):
|
| + fn = env.File('${STAGING_DIR}/ppNaClPlugin')
|
| + else:
|
| + fn = env.File('${STAGING_DIR}/${SHLIBPREFIX}ppNaClPlugin${SHLIBSUFFIX}')
|
| + if allow_64bit_redirect and env.Bit('target_x86_64'):
|
| + # On 64-bit Windows and on Mac, we need the 32-bit plugin because
|
| + # the browser is 32-bit.
|
| + # Unfortunately it is tricky to build the 32-bit plugin (and all the
|
| + # libraries it needs) in a 64-bit build... so we'll assume it has already
|
| + # been built in a previous invocation.
|
| + # TODO(ncbray) better 32/64 builds.
|
| + if env.Bit('windows'):
|
| + fn = env.subst(fn).abspath.replace('-win-x86-64', '-win-x86-32')
|
| + elif env.Bit('mac'):
|
| + fn = env.subst(fn).abspath.replace('-mac-x86-64', '-mac-x86-32')
|
| + return fn
|
| +
|
| +pre_base_env.AddMethod(GetPPAPIPluginPath)
|
| +
|
| +
|
| +# runnable-ld.so log has following format:
|
| +# lib_name => path_to_lib (0x....address)
|
| +def ParseLibInfoInRunnableLdLog(line):
|
| + pos = line.find(' => ')
|
| + if pos < 0:
|
| + return None
|
| + lib_name = line[:pos].strip()
|
| + lib_path = line[pos+4:]
|
| + pos1 = lib_path.rfind(' (')
|
| + if pos1 < 0:
|
| + return None
|
| + lib_path = lib_path[:pos1]
|
| + return lib_name, lib_path
|
| +
|
| +
|
| +# Expected name of the temporary .libs file which stores glibc library
|
| +# dependencies in "lib_name => lib_info" format
|
| +# (see ParseLibInfoInRunnableLdLog)
|
| +def GlibcManifestLibsListFilename(manifest_base_name):
|
| + return '${STAGING_DIR}/%s.libs' % manifest_base_name
|
| +
|
| +
|
| +# Copy libs and manifest to the target directory.
|
| +# source[0] is a manifest file
|
| +# source[1] is a .libs file with a list of libs generated by runnable-ld.so
|
| +def CopyLibsForExtensionCommand(target, source, env):
|
| + source_manifest = str(source[0])
|
| + target_manifest = str(target[0])
|
| + shutil.copyfile(source_manifest, target_manifest)
|
| + target_dir = os.path.dirname(target_manifest)
|
| + libs_file = open(str(source[1]), 'r')
|
| + for line in libs_file.readlines():
|
| + lib_info = ParseLibInfoInRunnableLdLog(line)
|
| + if lib_info:
|
| + lib_name, lib_path = lib_info
|
| + # Note: This probably does NOT work with pnacl _pexes_ right now, because
|
| + # the NEEDED metadata in the bitcode doesn't have the original file paths.
|
| + # This should probably be done without such knowledge.
|
| + if lib_path == 'NaClMain':
|
| + # This is a fake file name, which we cannot copy.
|
| + continue
|
| + shutil.copyfile(lib_path, os.path.join(target_dir, lib_name))
|
| + shutil.copyfile(env.subst('${NACL_SDK_LIB}/runnable-ld.so'),
|
| + os.path.join(target_dir, 'runnable-ld.so'))
|
| + libs_file.close()
|
| +
|
| +
|
| +# Extensions are loaded from directory on disk and so all dynamic libraries
|
| +# they use must be copied to extension directory. The option --extra_serving_dir
|
| +# does not help us in this case.
|
| +def CopyLibsForExtension(env, target_dir, manifest):
|
| + if not env.Bit('nacl_glibc'):
|
| + return env.Install(target_dir, manifest)
|
| + manifest_base_name = os.path.basename(str(env.subst(manifest)))
|
| + lib_list_node = env.File(GlibcManifestLibsListFilename(manifest_base_name))
|
| + nmf_node = env.Command(
|
| + target_dir + '/' + manifest_base_name,
|
| + [manifest, lib_list_node],
|
| + CopyLibsForExtensionCommand)
|
| + return nmf_node
|
| +
|
| +pre_base_env.AddMethod(CopyLibsForExtension)
|
| +
|
| +
|
| +
|
| +def WhitelistLibsForExtensionCommand(target, source, env):
|
| + # Load existing extension manifest.
|
| + src_file = open(source[0].abspath, 'r')
|
| + src_json = json.load(src_file)
|
| + src_file.close()
|
| +
|
| + # Load existing 'web_accessible_resources' key.
|
| + if 'web_accessible_resources' not in src_json:
|
| + src_json['web_accessible_resources'] = []
|
| + web_accessible = src_json['web_accessible_resources']
|
| +
|
| + # Load list of libraries, and add libraries to web_accessible list.
|
| + libs_file = open(source[1].abspath, 'r')
|
| + for line in libs_file.readlines():
|
| + lib_info = ParseLibInfoInRunnableLdLog(line)
|
| + if lib_info:
|
| + web_accessible.append(lib_info[0])
|
| + # Also add the dynamic loader, which won't be in the libs_file.
|
| + web_accessible.append('runnable-ld.so')
|
| + libs_file.close()
|
| +
|
| + # Write out the appended-to extension manifest.
|
| + target_file = open(target[0].abspath, 'w')
|
| + json.dump(src_json, target_file, sort_keys=True, indent=2)
|
| + target_file.close()
|
| +
|
| +
|
| +# Whitelist glibc shared libraries (if necessary), so that they are
|
| +# 'web_accessible_resources'. This allows the libraries hosted at the origin
|
| +# chrome-extension://[PACKAGE ID]/
|
| +# to be made available to webpages that use this NaCl extension,
|
| +# which are in a different origin.
|
| +# See: http://code.google.com/chrome/extensions/manifest.html
|
| +#
|
| +# Alternatively, we could try to use the chrome commandline switch
|
| +# '--disable-extensions-resource-whitelist', but that would not be what
|
| +# users will need to do.
|
| +def WhitelistLibsForExtension(env, target_dir, nmf, extension_manifest):
|
| + if env.Bit('nacl_static_link'):
|
| + # For static linking, assume the nexe and nmf files are already
|
| + # whitelisted, so there is no need to add entries to the extension_manifest.
|
| + return env.Install(target_dir, extension_manifest)
|
| + nmf_base_name = os.path.basename(env.File(nmf).abspath)
|
| + lib_list_node = env.File(GlibcManifestLibsListFilename(nmf_base_name))
|
| + manifest_base_name = os.path.basename(env.File(extension_manifest).abspath)
|
| + extension_manifest_node = env.Command(
|
| + target_dir + '/' + manifest_base_name,
|
| + [extension_manifest, lib_list_node],
|
| + WhitelistLibsForExtensionCommand)
|
| + return extension_manifest_node
|
| +
|
| +pre_base_env.AddMethod(WhitelistLibsForExtension)
|
| +
|
| +
|
| +# Generate manifest from newlib manifest and the list of libs generated by
|
| +# runnable-ld.so.
|
| +def GenerateManifestFunc(target, source, env):
|
| + # Open the original manifest and parse it.
|
| + source_file = open(str(source[0]), 'r')
|
| + obj = json.load(source_file)
|
| + source_file.close()
|
| + # Open the file with ldd-format list of NEEDED libs and parse it.
|
| + libs_file = open(str(source[1]), 'r')
|
| + lib_names = []
|
| + arch = env.subst('${TARGET_FULLARCH}')
|
| + for line in libs_file.readlines():
|
| + lib_info = ParseLibInfoInRunnableLdLog(line)
|
| + if lib_info:
|
| + lib_name, _ = lib_info
|
| + lib_names.append(lib_name)
|
| + libs_file.close()
|
| + # Inject the NEEDED libs into the manifest.
|
| + if 'files' not in obj:
|
| + obj['files'] = {}
|
| + for lib_name in lib_names:
|
| + obj['files'][lib_name] = {}
|
| + obj['files'][lib_name][arch] = {}
|
| + obj['files'][lib_name][arch]['url'] = lib_name
|
| + # Put what used to be specified under 'program' into 'main.nexe'.
|
| + obj['files']['main.nexe'] = {}
|
| + for k, v in obj['program'].items():
|
| + obj['files']['main.nexe'][k] = v.copy()
|
| + v['url'] = 'runnable-ld.so'
|
| + # Write the new manifest!
|
| + target_file = open(str(target[0]), 'w')
|
| + json.dump(obj, target_file, sort_keys=True, indent=2)
|
| + target_file.close()
|
| + return 0
|
| +
|
| +def GenerateManifestPnacl(env, dest_file, manifest, exe_file):
|
| + return env.Command(
|
| + dest_file,
|
| + ['${GENNMF}', exe_file, manifest],
|
| + # Generate a flat url scheme to simplify file-staging.
|
| + ('${SOURCES[0]} ${SOURCES[1]} -L${NACL_SDK_LIB} -L${LIB_DIR} '
|
| + ' --flat-url-scheme --base-nmf ${SOURCES[2]} -o ${TARGET}'))
|
| +
|
| +def GenerateManifestDynamicLink(env, dest_file, lib_list_file,
|
| + manifest, exe_file):
|
| + # Run sel_ldr on the nexe to trace the NEEDED libraries.
|
| + lib_list_node = env.Command(
|
| + lib_list_file,
|
| + [env.GetSelLdr(),
|
| + '${NACL_SDK_LIB}/runnable-ld.so',
|
| + exe_file,
|
| + '${SCONSTRUCT_DIR}/DEPS'],
|
| + # We ignore the return code using '-' in order to build tests
|
| + # where binaries do not validate. This is a Scons feature.
|
| + '-${SOURCES[0]} -a -E LD_TRACE_LOADED_OBJECTS=1 ${SOURCES[1]} '
|
| + '--library-path ${NACL_SDK_LIB}:${LIB_DIR} ${SOURCES[2].posix} '
|
| + '> ${TARGET}')
|
| + return env.Command(dest_file,
|
| + [manifest, lib_list_node],
|
| + GenerateManifestFunc)[0]
|
| +
|
| +
|
| +def GenerateSimpleManifestStaticLink(env, dest_file, exe_name):
|
| + def Func(target, source, env):
|
| + archs = ('x86-32', 'x86-64', 'arm')
|
| + nmf_data = {'program': dict((arch, {'url': '%s_%s.nexe' % (exe_name, arch)})
|
| + for arch in archs)}
|
| + fh = open(target[0].abspath, 'w')
|
| + json.dump(nmf_data, fh, sort_keys=True, indent=2)
|
| + fh.close()
|
| + node = env.Command(dest_file, [], Func)[0]
|
| + # Scons does not track the dependency of dest_file on exe_name or on
|
| + # the Python code above, so we should always recreate dest_file when
|
| + # it is used.
|
| + env.AlwaysBuild(node)
|
| + return node
|
| +
|
| +
|
| +def GenerateSimpleManifest(env, dest_file, exe_name):
|
| + if env.Bit('pnacl_generate_pexe'):
|
| + static_manifest = GenerateSimpleManifestStaticLink(
|
| + env, '%s.static' % dest_file, exe_name)
|
| + return GenerateManifestPnacl(env, dest_file, static_manifest,
|
| + '${STAGING_DIR}/%s.pexe' %
|
| + env.ProgramNameForNmf(exe_name))
|
| + elif env.Bit('nacl_static_link'):
|
| + return GenerateSimpleManifestStaticLink(env, dest_file, exe_name)
|
| + else:
|
| + static_manifest = GenerateSimpleManifestStaticLink(
|
| + env, '%s.static' % dest_file, exe_name)
|
| + return GenerateManifestDynamicLink(
|
| + env, dest_file, '%s.tmp_lib_list' % dest_file, static_manifest,
|
| + '${STAGING_DIR}/%s.nexe' % env.ProgramNameForNmf(exe_name))
|
| +
|
| +pre_base_env.AddMethod(GenerateSimpleManifest)
|
| +
|
| +
|
| +# Returns a pair (main program, is_portable), based on the program
|
| +# specified in manifest file.
|
| +def GetMainProgramFromManifest(env, manifest):
|
| + obj = json.loads(env.File(manifest).get_contents())
|
| + program_dict = obj['program']
|
| + if env.Bit('pnacl_generate_pexe') and 'portable' in program_dict:
|
| + return program_dict['portable']['pnacl-translate']['url']
|
| + else:
|
| + return program_dict[env.subst('${TARGET_FULLARCH}')]['url']
|
| +
|
| +
|
| +# Returns scons node for generated manifest.
|
| +def GeneratedManifestNode(env, manifest):
|
| + manifest = env.subst(manifest)
|
| + manifest_base_name = os.path.basename(manifest)
|
| + main_program = GetMainProgramFromManifest(env, manifest)
|
| + result = env.File('${STAGING_DIR}/' + manifest_base_name)
|
| + # Always generate the manifest for nacl_glibc and pnacl pexes.
|
| + # For nacl_glibc, generating the mapping of shared libraries is non-trivial.
|
| + # For pnacl, the manifest currently hosts a sha for the pexe.
|
| + if not env.Bit('nacl_glibc') and not env.Bit('pnacl_generate_pexe'):
|
| + env.Install('${STAGING_DIR}', manifest)
|
| + return result
|
| + if env.Bit('pnacl_generate_pexe'):
|
| + return GenerateManifestPnacl(
|
| + env,
|
| + '${STAGING_DIR}/' + manifest_base_name,
|
| + manifest,
|
| + env.File('${STAGING_DIR}/' + os.path.basename(main_program)))
|
| + else:
|
| + return GenerateManifestDynamicLink(
|
| + env, '${STAGING_DIR}/' + manifest_base_name,
|
| + # Note that CopyLibsForExtension() and WhitelistLibsForExtension()
|
| + # assume that it can find the library list file under this filename.
|
| + GlibcManifestLibsListFilename(manifest_base_name),
|
| + manifest,
|
| + env.File('${STAGING_DIR}/' + os.path.basename(main_program)))
|
| + return result
|
| +
|
| +
|
| +def GetPnaclExtensionRootNode(env):
|
| + """Get the scons node representing the root directory of pnacl support files.
|
| + """
|
| + # This is "built" by src/untrusted/pnacl_support_extension/nacl.scons.
|
| + return env.Dir('${DESTINATION_ROOT}/pnacl_support')
|
| +
|
| +pre_base_env.AddMethod(GetPnaclExtensionRootNode)
|
| +
|
| +def GetPnaclExtensionDummyVersion(env):
|
| + """ We supply a dummy version number when packaging the test-extension
|
| + that is probably newer than all other versions. """
|
| + return '9999.9.9.9'
|
| +
|
| +pre_base_env.AddMethod(GetPnaclExtensionDummyVersion)
|
| +
|
| +def GetPnaclExtensionNode(env):
|
| + """Get the scons node representing a specific version of pnacl support files.
|
| + """
|
| + # This is "built" by src/untrusted/pnacl_support_extension/nacl.scons.
|
| + return env.Dir('${DESTINATION_ROOT}/pnacl_support/' +
|
| + env.GetPnaclExtensionDummyVersion())
|
| +
|
| +pre_base_env.AddMethod(GetPnaclExtensionNode)
|
| +
|
| +
|
| +# Compares output_file and golden_file.
|
| +# If they are different, prints the difference and returns 1.
|
| +# Otherwise, returns 0.
|
| +def CheckGoldenFile(golden_file, output_file,
|
| + filter_regex, filter_inverse, filter_group_only):
|
| + golden = open(golden_file).read()
|
| + actual = open(output_file).read()
|
| + if filter_regex is not None:
|
| + actual = test_lib.RegexpFilterLines(
|
| + filter_regex,
|
| + filter_inverse,
|
| + filter_group_only,
|
| + actual)
|
| + if command_tester.DifferentFromGolden(actual, golden, output_file):
|
| + return 1
|
| + return 0
|
| +
|
| +
|
| +# Returns action that compares output_file and golden_file.
|
| +# This action can be attached to the node with
|
| +# env.AddPostAction(target, action)
|
| +def GoldenFileCheckAction(env, output_file, golden_file,
|
| + filter_regex=None, filter_inverse=False,
|
| + filter_group_only=False):
|
| + def ActionFunc(target, source, env):
|
| + return CheckGoldenFile(env.subst(golden_file), env.subst(output_file),
|
| + filter_regex, filter_inverse, filter_group_only)
|
| +
|
| + return env.Action(ActionFunc)
|
| +
|
| +
|
| +def PPAPIBrowserTester(env,
|
| + target,
|
| + url,
|
| + files,
|
| + nmfs=None,
|
| + # List of executable basenames to generate
|
| + # manifest files for.
|
| + nmf_names=(),
|
| + map_files=(),
|
| + extensions=(),
|
| + mime_types=(),
|
| + timeout=30,
|
| + log_verbosity=2,
|
| + args=[],
|
| + # list of key/value pairs that are passed to the test
|
| + test_args=(),
|
| + # list of "--flag=value" pairs (no spaces!)
|
| + browser_flags=None,
|
| + # redirect streams of NaCl program to files
|
| + nacl_exe_stdin=None,
|
| + nacl_exe_stdout=None,
|
| + nacl_exe_stderr=None,
|
| + python_tester_script=None,
|
| + **extra):
|
| + if 'TRUSTED_ENV' not in env:
|
| + return []
|
| +
|
| + # No browser tests run on arm-thumb2
|
| + # Bug http://code.google.com/p/nativeclient/issues/detail?id=2224
|
| + if env.Bit('target_arm_thumb2'):
|
| + return []
|
| +
|
| + # Handle issues with mutating any python default arg lists.
|
| + if browser_flags is None:
|
| + browser_flags = []
|
| +
|
| + if env.Bit('pnacl_generate_pexe'):
|
| + # We likely prefer to choose the 'portable' field in nmfs in this mode.
|
| + args = args + ['--prefer_portable_in_manifest']
|
| + # Pass through env var controlling streaming translation
|
| + if 'NACL_STREAMING_TRANSLATION' in os.environ:
|
| + env['ENV']['NACL_STREAMING_TRANSLATION'] = 'true'
|
| +
|
| + # Lint the extra arguments that are being passed to the tester.
|
| + special_args = ['--ppapi_plugin', '--sel_ldr', '--irt_library', '--file',
|
| + '--map_file', '--extension', '--mime_type', '--tool',
|
| + '--browser_flag', '--test_arg']
|
| + for arg_name in special_args:
|
| + if arg_name in args:
|
| + raise Exception('%s: %r is a test argument provided by the SCons test'
|
| + ' wrapper, do not specify it as an additional argument' %
|
| + (target, arg_name))
|
| +
|
| + env = env.Clone()
|
| + env.SetupBrowserEnv()
|
| +
|
| + if 'scale_timeout' in ARGUMENTS:
|
| + timeout = timeout * int(ARGUMENTS['scale_timeout'])
|
| +
|
| + if python_tester_script is None:
|
| + python_tester_script = env.File('${SCONSTRUCT_DIR}/tools/browser_tester'
|
| + '/browser_tester.py')
|
| + command = env.GetHeadlessPrefix() + [
|
| + '${PYTHON}', python_tester_script,
|
| + '--browser_path', env.ChromeBinary(),
|
| + '--url', url,
|
| + # Fail if there is no response for X seconds.
|
| + '--timeout', str(timeout)]
|
| + if not env.Bit('disable_dynamic_plugin_loading'):
|
| + command.extend(['--ppapi_plugin', env['TRUSTED_ENV'].GetPPAPIPluginPath()])
|
| + command.extend(['--sel_ldr', env.GetSelLdr()])
|
| + bootstrap, _ = env.GetBootstrap()
|
| + if bootstrap is not None:
|
| + command.extend(['--sel_ldr_bootstrap', bootstrap])
|
| + if (not env.Bit('disable_dynamic_plugin_loading') or
|
| + env.Bit('override_chrome_irt')):
|
| + command.extend(['--irt_library', env.GetIrtNexe(chrome_irt=True)])
|
| + for dep_file in files:
|
| + command.extend(['--file', dep_file])
|
| + for extension in extensions:
|
| + command.extend(['--extension', extension])
|
| + if env.Bit('bitcode'):
|
| + # TODO(jvoung): remove this --extension once we have --pnacl-dir working.
|
| + command.extend(['--extension', env.GetPnaclExtensionNode().abspath])
|
| + # Enable the installed version of pnacl, and point to a custom install
|
| + # directory for testing purposes.
|
| + browser_flags.append('--enable-pnacl')
|
| + browser_flags.append('--pnacl-dir=%s' %
|
| + env.GetPnaclExtensionRootNode().abspath)
|
| + for dest_path, dep_file in map_files:
|
| + command.extend(['--map_file', dest_path, dep_file])
|
| + for file_ext, mime_type in mime_types:
|
| + command.extend(['--mime_type', file_ext, mime_type])
|
| + command.extend(['--serving_dir', '${NACL_SDK_LIB}'])
|
| + command.extend(['--serving_dir', '${LIB_DIR}'])
|
| + if 'browser_tester_bw' in ARGUMENTS:
|
| + command.extend(['-b', ARGUMENTS['browser_tester_bw']])
|
| + if not nmfs is None:
|
| + for nmf_file in nmfs:
|
| + generated_manifest = GeneratedManifestNode(env, nmf_file)
|
| + # We need to add generated manifests to the list of default targets.
|
| + # The manifests should be generated even if the tests are not run -
|
| + # the manifests may be needed for manual testing.
|
| + for group in env['COMPONENT_TEST_PROGRAM_GROUPS']:
|
| + env.Alias(group, generated_manifest)
|
| + # Generated manifests are served in the root of the HTTP server
|
| + command.extend(['--file', generated_manifest])
|
| + for nmf_name in nmf_names:
|
| + tmp_manifest = '%s.tmp/%s.nmf' % (target, nmf_name)
|
| + command.extend(['--map_file', '%s.nmf' % nmf_name,
|
| + env.GenerateSimpleManifest(tmp_manifest, nmf_name)])
|
| + if 'browser_test_tool' in ARGUMENTS:
|
| + command.extend(['--tool', ARGUMENTS['browser_test_tool']])
|
| +
|
| + # Suppress debugging information on the Chrome waterfall.
|
| + if env.Bit('disable_flaky_tests') and '--debug' in args:
|
| + args.remove('--debug')
|
| +
|
| + command.extend(args)
|
| + for flag in browser_flags:
|
| + if flag.find(' ') != -1:
|
| + raise Exception('Spaces not allowed in browser_flags: '
|
| + 'use --flag=value instead')
|
| + command.extend(['--browser_flag', flag])
|
| + for key, value in test_args:
|
| + command.extend(['--test_arg', str(key), str(value)])
|
| +
|
| + # Set a given file to be the nexe's stdin.
|
| + if nacl_exe_stdin is not None:
|
| + command.extend(['--nacl_exe_stdin', env.subst(nacl_exe_stdin['file'])])
|
| +
|
| + post_actions = []
|
| + side_effects = []
|
| + # Set a given file to be the nexe's stdout or stderr. The tester also
|
| + # compares this output against a golden file.
|
| + for stream, params in (
|
| + ('stdout', nacl_exe_stdout),
|
| + ('stderr', nacl_exe_stderr)):
|
| + if params is None:
|
| + continue
|
| + stream_file = env.subst(params['file'])
|
| + side_effects.append(stream_file)
|
| + command.extend(['--nacl_exe_' + stream, stream_file])
|
| + if 'golden' in params:
|
| + golden_file = env.subst(params['golden'])
|
| + filter_regex = params.get('filter_regex', None)
|
| + filter_inverse = params.get('filter_inverse', False)
|
| + filter_group_only = params.get('filter_group_only', False)
|
| + post_actions.append(
|
| + GoldenFileCheckAction(
|
| + env, stream_file, golden_file,
|
| + filter_regex, filter_inverse, filter_group_only))
|
| +
|
| + if env.ShouldUseVerboseOptions(extra):
|
| + env.MakeVerboseExtraOptions(target, log_verbosity, extra)
|
| + # Heuristic for when to capture output...
|
| + capture_output = (extra.pop('capture_output', False)
|
| + or 'process_output_single' in extra)
|
| + node = env.CommandTest(target,
|
| + command,
|
| + # Set to 'huge' so that the browser tester's timeout
|
| + # takes precedence over the default of the test_suite.
|
| + size='huge',
|
| + capture_output=capture_output,
|
| + **extra)
|
| + # Also indicate that we depend on the layed-out pnacl translator.
|
| + if env.Bit('bitcode'):
|
| + env.Depends(node, env.GetPnaclExtensionNode())
|
| + for side_effect in side_effects:
|
| + env.SideEffect(side_effect, node)
|
| + # We can't check output if the test is not run.
|
| + if not env.Bit('do_not_run_tests'):
|
| + for action in post_actions:
|
| + env.AddPostAction(node, action)
|
| + return node
|
| +
|
| +pre_base_env.AddMethod(PPAPIBrowserTester)
|
| +
|
| +
|
| +# Disabled for ARM and MIPS because Chrome binaries for ARM and MIPS are not
|
| +# available.
|
| +def PPAPIBrowserTesterIsBroken(env):
|
| + return (env.Bit('target_arm') or env.Bit('target_arm_thumb2')
|
| + or env.Bit('target_mips32'))
|
| +
|
| +pre_base_env.AddMethod(PPAPIBrowserTesterIsBroken)
|
| +
|
| +# 3D is disabled everywhere
|
| +def PPAPIGraphics3DIsBroken(env):
|
| + return True
|
| +
|
| +pre_base_env.AddMethod(PPAPIGraphics3DIsBroken)
|
| +
|
| +
|
| +def AddChromeFilesFromGroup(env, file_group):
|
| + env['BUILD_SCONSCRIPTS'] = ExtendFileList(
|
| + env.get('BUILD_SCONSCRIPTS', []),
|
| + ppapi_scons_files[file_group])
|
| +
|
| +pre_base_env.AddMethod(AddChromeFilesFromGroup)
|
|
|