15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#! -*- python -*-
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Native Client Authors. All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import json
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import shutil
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sys.path.append(Dir('#/tools').abspath)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import command_tester
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import test_lib
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Import(['pre_base_env'])
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Underlay things migrating to ppapi repo.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Dir('#/..').addRepository(Dir('#/../ppapi'))
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Append a list of files to another, filtering out the files that already exist.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Filtering helps migrate declarations between repos by preventing redundant
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# declarations from causing an error.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def ExtendFileList(existing, additional):
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Avoid quadratic behavior by using a set.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  combined = set()
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for file_name in existing + additional:
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if file_name in combined:
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      print 'WARNING: two references to file %s in the build.' % file_name
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    combined.add(file_name)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sorted(combined)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ppapi_scons_files = {}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ppapi_scons_files['trusted_scons_files'] = []
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ppapi_scons_files['untrusted_irt_scons_files'] = []
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ppapi_scons_files['nonvariant_test_scons_files'] = [
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'tests/breakpad_crash_test/nacl.scons',
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'tests/nacl_browser/browser_dynamic_library/nacl.scons',
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'tests/ppapi_test_lib/nacl.scons',
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)]
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ppapi_scons_files['irt_variant_test_scons_files'] = [
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # 'inbrowser_test_runner' must be in the irt_variant list
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # otherwise it will run no tests.
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    'tests/nacl_browser/inbrowser_test_runner/nacl.scons',
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Disabled by Brad Chen 4 Sep to try to green Chromium
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # nacl_integration tests
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    #'tests/nacl_browser/fault_injection/nacl.scons',
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)]
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ppapi_scons_files['untrusted_scons_files'] = [
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'src/shared/ppapi/nacl.scons',
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'src/untrusted/irt_stub/nacl.scons',
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'src/untrusted/nacl_ppapi_util/nacl.scons',
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)]
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochEXTRA_ENV = [
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    'XAUTHORITY', 'HOME', 'DISPLAY', 'SSH_TTY', 'KRB5CCNAME',
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    'CHROME_DEVEL_SANDBOX' ]
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def SetupBrowserEnv(env):
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for var_name in EXTRA_ENV:
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if var_name in os.environ:
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      env['ENV'][var_name] = os.environ[var_name]
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pre_base_env.AddMethod(SetupBrowserEnv)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetHeadlessPrefix(env):
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if env.Bit('browser_headless') and env.Bit('host_linux'):
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ['xvfb-run', '--auto-servernum']
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else:
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Mac and Windows do not seem to have an equivalent.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return []
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pre_base_env.AddMethod(GetHeadlessPrefix)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# A fake file to depend on if a path to Chrome is not specified.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)no_browser = pre_base_env.File('chrome_browser_path_not_specified')
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# SCons attempts to run a test that depends on "no_browser", detect this at
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# runtime and cause a build error.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def NoBrowserError(target, source, env):
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print target, source, env
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print ("***\nYou need to specificy chrome_browser_path=... on the " +
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         "command line to run these tests.\n***\n")
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pre_base_env.Append(BUILDERS = {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'NoBrowserError': Builder(action=NoBrowserError)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)})
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pre_base_env.NoBrowserError([no_browser], [])
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def ChromeBinary(env):
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if 'chrome_browser_path' in ARGUMENTS:
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return env.File(env.SConstructAbsPath(ARGUMENTS['chrome_browser_path']))
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else:
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return no_browser
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pre_base_env.AddMethod(ChromeBinary)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetPPAPIPluginPath(env, allow_64bit_redirect=True):
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if 'force_ppapi_plugin' in ARGUMENTS:
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return env.SConstructAbsPath(ARGUMENTS['force_ppapi_plugin'])
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if env.Bit('mac'):
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fn = env.File('${STAGING_DIR}/ppNaClPlugin')
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else:
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fn = env.File('${STAGING_DIR}/${SHLIBPREFIX}ppNaClPlugin${SHLIBSUFFIX}')
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if allow_64bit_redirect and env.Bit('target_x86_64'):
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # On 64-bit Windows and on Mac, we need the 32-bit plugin because
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # the browser is 32-bit.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Unfortunately it is tricky to build the 32-bit plugin (and all the
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # libraries it needs) in a 64-bit build... so we'll assume it has already
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # been built in a previous invocation.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # TODO(ncbray) better 32/64 builds.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if env.Bit('windows'):
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fn = env.subst(fn).abspath.replace('-win-x86-64', '-win-x86-32')
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif env.Bit('mac'):
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fn = env.subst(fn).abspath.replace('-mac-x86-64', '-mac-x86-32')
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return fn
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pre_base_env.AddMethod(GetPPAPIPluginPath)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# runnable-ld.so log has following format:
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# lib_name => path_to_lib (0x....address)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def ParseLibInfoInRunnableLdLog(line):
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos = line.find(' => ')
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if pos < 0:
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return None
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lib_name = line[:pos].strip()
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lib_path = line[pos+4:]
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos1 = lib_path.rfind(' (')
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if pos1 < 0:
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return None
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lib_path = lib_path[:pos1]
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return lib_name, lib_path
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Expected name of the temporary .libs file which stores glibc library
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# dependencies in "lib_name => lib_info" format
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# (see ParseLibInfoInRunnableLdLog)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GlibcManifestLibsListFilename(manifest_base_name):
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return '${STAGING_DIR}/%s.libs' % manifest_base_name
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copy libs and manifest to the target directory.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# source[0] is a manifest file
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# source[1] is a .libs file with a list of libs generated by runnable-ld.so
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CopyLibsForExtensionCommand(target, source, env):
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source_manifest = str(source[0])
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_manifest = str(target[0])
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shutil.copyfile(source_manifest, target_manifest)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_dir = os.path.dirname(target_manifest)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  libs_file = open(str(source[1]), 'r')
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for line in libs_file.readlines():
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lib_info = ParseLibInfoInRunnableLdLog(line)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if lib_info:
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lib_name, lib_path = lib_info
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if lib_path == 'NaClMain':
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # This is a fake file name, which we cannot copy.
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shutil.copyfile(lib_path, os.path.join(target_dir, lib_name))
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shutil.copyfile(env.subst('${NACL_SDK_LIB}/runnable-ld.so'),
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  os.path.join(target_dir, 'runnable-ld.so'))
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  libs_file.close()
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Extensions are loaded from directory on disk and so all dynamic libraries
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# they use must be copied to extension directory. The option --extra_serving_dir
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# does not help us in this case.
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CopyLibsForExtension(env, target_dir, manifest):
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not env.Bit('nacl_glibc'):
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return env.Install(target_dir, manifest)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manifest_base_name = os.path.basename(str(env.subst(manifest)))
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lib_list_node = env.File(GlibcManifestLibsListFilename(manifest_base_name))
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nmf_node = env.Command(
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      target_dir + '/' + manifest_base_name,
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [manifest, lib_list_node],
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CopyLibsForExtensionCommand)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return nmf_node
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pre_base_env.AddMethod(CopyLibsForExtension)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def WhitelistLibsForExtensionCommand(target, source, env):
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Load existing extension manifest.
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  src_file = open(source[0].abspath, 'r')
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  src_json = json.load(src_file)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  src_file.close()
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Load existing 'web_accessible_resources' key.
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if 'web_accessible_resources' not in src_json:
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    src_json['web_accessible_resources'] = []
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_accessible = src_json['web_accessible_resources']
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Load list of libraries, and add libraries to web_accessible list.
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  libs_file = open(source[1].abspath, 'r')
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for line in libs_file.readlines():
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lib_info = ParseLibInfoInRunnableLdLog(line)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if lib_info:
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      web_accessible.append(lib_info[0])
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Also add the dynamic loader, which won't be in the libs_file.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_accessible.append('runnable-ld.so')
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  libs_file.close()
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Write out the appended-to extension manifest.
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_file = open(target[0].abspath, 'w')
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  json.dump(src_json, target_file, sort_keys=True, indent=2)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_file.close()
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Whitelist glibc shared libraries (if necessary), so that they are
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 'web_accessible_resources'.  This allows the libraries hosted at the origin
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# chrome-extension://[PACKAGE ID]/
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# to be made available to webpages that use this NaCl extension,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# which are in a different origin.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# See: http://code.google.com/chrome/extensions/manifest.html
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def WhitelistLibsForExtension(env, target_dir, nmf, extension_manifest):
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if env.Bit('nacl_static_link'):
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # For static linking, assume the nexe and nmf files are already
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # whitelisted, so there is no need to add entries to the extension_manifest.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return env.Install(target_dir, extension_manifest)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nmf_base_name = os.path.basename(env.File(nmf).abspath)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lib_list_node = env.File(GlibcManifestLibsListFilename(nmf_base_name))
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manifest_base_name = os.path.basename(env.File(extension_manifest).abspath)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension_manifest_node = env.Command(
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      target_dir + '/' + manifest_base_name,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [extension_manifest, lib_list_node],
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WhitelistLibsForExtensionCommand)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return extension_manifest_node
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pre_base_env.AddMethod(WhitelistLibsForExtension)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Generate manifest from newlib manifest and the list of libs generated by
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# runnable-ld.so.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GenerateManifestFunc(target, source, env):
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Open the original manifest and parse it.
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source_file = open(str(source[0]), 'r')
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  obj = json.load(source_file)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source_file.close()
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Open the file with ldd-format list of NEEDED libs and parse it.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  libs_file = open(str(source[1]), 'r')
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lib_names = []
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  arch = env.subst('${TARGET_FULLARCH}')
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for line in libs_file.readlines():
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lib_info = ParseLibInfoInRunnableLdLog(line)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if lib_info:
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lib_name, _ = lib_info
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lib_names.append(lib_name)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  libs_file.close()
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Inject the NEEDED libs into the manifest.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if 'files' not in obj:
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    obj['files'] = {}
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for lib_name in lib_names:
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    obj['files'][lib_name] = {}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    obj['files'][lib_name][arch] = {}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    obj['files'][lib_name][arch]['url'] = lib_name
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Put what used to be specified under 'program' into 'main.nexe'.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  obj['files']['main.nexe'] = {}
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for k, v in obj['program'].items():
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    obj['files']['main.nexe'][k] = v.copy()
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v['url'] = 'runnable-ld.so'
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Write the new manifest!
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_file = open(str(target[0]), 'w')
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  json.dump(obj, target_file, sort_keys=True, indent=2)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_file.close()
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GenerateManifestDynamicLink(env, dest_file, lib_list_file,
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                manifest, exe_file):
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Run sel_ldr on the nexe to trace the NEEDED libraries.
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lib_list_node = env.Command(
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lib_list_file,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [env.GetSelLdr(),
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       '${NACL_SDK_LIB}/runnable-ld.so',
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       exe_file,
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       '${SCONSTRUCT_DIR}/DEPS'],
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # We ignore the return code using '-' in order to build tests
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # where binaries do not validate.  This is a Scons feature.
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      '-${SOURCES[0]} -a -E LD_TRACE_LOADED_OBJECTS=1 ${SOURCES[1]} '
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      '--library-path ${NACL_SDK_LIB}:${LIB_DIR} ${SOURCES[2].posix} '
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      '> ${TARGET}')
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return env.Command(dest_file,
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     [manifest, lib_list_node],
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     GenerateManifestFunc)[0]
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GenerateSimpleManifestStaticLink(env, dest_file, exe_name):
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Func(target, source, env):
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    archs = ('x86-32', 'x86-64', 'arm')
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nmf_data = {'program': dict((arch, {'url': '%s_%s.nexe' % (exe_name, arch)})
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                for arch in archs)}
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fh = open(target[0].abspath, 'w')
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    json.dump(nmf_data, fh, sort_keys=True, indent=2)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fh.close()
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  node = env.Command(dest_file, [], Func)[0]
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Scons does not track the dependency of dest_file on exe_name or on
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # the Python code above, so we should always recreate dest_file when
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # it is used.
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  env.AlwaysBuild(node)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return node
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GenerateSimpleManifest(env, dest_file, exe_name):
31658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  if env.Bit('nacl_static_link'):
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GenerateSimpleManifestStaticLink(env, dest_file, exe_name)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else:
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static_manifest = GenerateSimpleManifestStaticLink(
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        env, '%s.static' % dest_file, exe_name)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GenerateManifestDynamicLink(
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        env, dest_file, '%s.tmp_lib_list' % dest_file, static_manifest,
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        '${STAGING_DIR}/%s.nexe' % env.ProgramNameForNmf(exe_name))
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pre_base_env.AddMethod(GenerateSimpleManifest)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Returns a pair (main program, is_portable), based on the program
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# specified in manifest file.
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetMainProgramFromManifest(env, manifest):
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  obj = json.loads(env.File(manifest).get_contents())
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  program_dict = obj['program']
33358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  return program_dict[env.subst('${TARGET_FULLARCH}')]['url']
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Returns scons node for generated manifest.
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GeneratedManifestNode(env, manifest):
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manifest = env.subst(manifest)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manifest_base_name = os.path.basename(manifest)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  main_program = GetMainProgramFromManifest(env, manifest)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = env.File('${STAGING_DIR}/' + manifest_base_name)
34258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  # Always generate the manifest for nacl_glibc.
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # For nacl_glibc, generating the mapping of shared libraries is non-trivial.
34458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  if not env.Bit('nacl_glibc'):
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    env.Install('${STAGING_DIR}', manifest)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result
34758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  return GenerateManifestDynamicLink(
34858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      env, '${STAGING_DIR}/' + manifest_base_name,
34958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      # Note that CopyLibsForExtension() and WhitelistLibsForExtension()
35058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      # assume that it can find the library list file under this filename.
35158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      GlibcManifestLibsListFilename(manifest_base_name),
35258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      manifest,
35358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      env.File('${STAGING_DIR}/' + os.path.basename(main_program)))
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Compares output_file and golden_file.
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# If they are different, prints the difference and returns 1.
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Otherwise, returns 0.
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CheckGoldenFile(golden_file, output_file,
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    filter_regex, filter_inverse, filter_group_only):
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  golden = open(golden_file).read()
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  actual = open(output_file).read()
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if filter_regex is not None:
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    actual = test_lib.RegexpFilterLines(
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        filter_regex,
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        filter_inverse,
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        filter_group_only,
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        actual)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if command_tester.DifferentFromGolden(actual, golden, output_file):
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Returns action that compares output_file and golden_file.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# This action can be attached to the node with
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# env.AddPostAction(target, action)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GoldenFileCheckAction(env, output_file, golden_file,
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          filter_regex=None, filter_inverse=False,
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          filter_group_only=False):
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ActionFunc(target, source, env):
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CheckGoldenFile(env.subst(golden_file), env.subst(output_file),
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           filter_regex, filter_inverse, filter_group_only)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return env.Action(ActionFunc)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def PPAPIBrowserTester(env,
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       target,
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       url,
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       files,
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       nmfs=None,
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       # List of executable basenames to generate
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       # manifest files for.
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       nmf_names=(),
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       map_files=(),
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       extensions=(),
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       mime_types=(),
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       timeout=30,
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       log_verbosity=2,
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       args=[],
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       # list of key/value pairs that are passed to the test
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       test_args=(),
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       # list of "--flag=value" pairs (no spaces!)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       browser_flags=None,
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       # redirect streams of NaCl program to files
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       nacl_exe_stdin=None,
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       nacl_exe_stdout=None,
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       nacl_exe_stderr=None,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       python_tester_script=None,
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       **extra):
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if 'TRUSTED_ENV' not in env:
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return []
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Handle issues with mutating any python default arg lists.
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if browser_flags is None:
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    browser_flags = []
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Lint the extra arguments that are being passed to the tester.
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  special_args = ['--ppapi_plugin', '--sel_ldr', '--irt_library', '--file',
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  '--map_file', '--extension', '--mime_type', '--tool',
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  '--browser_flag', '--test_arg']
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for arg_name in special_args:
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if arg_name in args:
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise Exception('%s: %r is a test argument provided by the SCons test'
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      ' wrapper, do not specify it as an additional argument' %
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      (target, arg_name))
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  env = env.Clone()
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  env.SetupBrowserEnv()
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if 'scale_timeout' in ARGUMENTS:
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    timeout = timeout * int(ARGUMENTS['scale_timeout'])
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if python_tester_script is None:
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    python_tester_script = env.File('${SCONSTRUCT_DIR}/tools/browser_tester'
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             '/browser_tester.py')
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  command = env.GetHeadlessPrefix() + [
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      '${PYTHON}', python_tester_script,
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      '--browser_path', env.ChromeBinary(),
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      '--url', url,
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # Fail if there is no response for X seconds.
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      '--timeout', str(timeout)]
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for dep_file in files:
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command.extend(['--file', dep_file])
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for extension in extensions:
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command.extend(['--extension', extension])
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for dest_path, dep_file in map_files:
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command.extend(['--map_file', dest_path, dep_file])
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for file_ext, mime_type in mime_types:
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command.extend(['--mime_type', file_ext, mime_type])
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  command.extend(['--serving_dir', '${NACL_SDK_LIB}'])
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  command.extend(['--serving_dir', '${LIB_DIR}'])
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if 'browser_tester_bw' in ARGUMENTS:
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command.extend(['-b', ARGUMENTS['browser_tester_bw']])
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not nmfs is None:
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for nmf_file in nmfs:
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      generated_manifest = GeneratedManifestNode(env, nmf_file)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # We need to add generated manifests to the list of default targets.
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # The manifests should be generated even if the tests are not run -
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # the manifests may be needed for manual testing.
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for group in env['COMPONENT_TEST_PROGRAM_GROUPS']:
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        env.Alias(group, generated_manifest)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # Generated manifests are served in the root of the HTTP server
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command.extend(['--file', generated_manifest])
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for nmf_name in nmf_names:
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tmp_manifest = '%s.tmp/%s.nmf' % (target, nmf_name)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command.extend(['--map_file', '%s.nmf' % nmf_name,
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    env.GenerateSimpleManifest(tmp_manifest, nmf_name)])
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if 'browser_test_tool' in ARGUMENTS:
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command.extend(['--tool', ARGUMENTS['browser_test_tool']])
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Suppress debugging information on the Chrome waterfall.
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if env.Bit('disable_flaky_tests') and '--debug' in args:
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    args.remove('--debug')
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  command.extend(args)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for flag in browser_flags:
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if flag.find(' ') != -1:
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise Exception('Spaces not allowed in browser_flags: '
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      'use --flag=value instead')
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command.extend(['--browser_flag', flag])
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for key, value in test_args:
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command.extend(['--test_arg', str(key), str(value)])
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Set a given file to be the nexe's stdin.
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if nacl_exe_stdin is not None:
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command.extend(['--nacl_exe_stdin', env.subst(nacl_exe_stdin['file'])])
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  post_actions = []
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  side_effects = []
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Set a given file to be the nexe's stdout or stderr.  The tester also
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # compares this output against a golden file.
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for stream, params in (
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ('stdout', nacl_exe_stdout),
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ('stderr', nacl_exe_stderr)):
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if params is None:
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stream_file = env.subst(params['file'])
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    side_effects.append(stream_file)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command.extend(['--nacl_exe_' + stream, stream_file])
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if 'golden' in params:
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      golden_file = env.subst(params['golden'])
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      filter_regex = params.get('filter_regex', None)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      filter_inverse = params.get('filter_inverse', False)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      filter_group_only = params.get('filter_group_only', False)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      post_actions.append(
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GoldenFileCheckAction(
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              env, stream_file, golden_file,
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              filter_regex, filter_inverse, filter_group_only))
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if env.ShouldUseVerboseOptions(extra):
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    env.MakeVerboseExtraOptions(target, log_verbosity, extra)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Heuristic for when to capture output...
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_output = (extra.pop('capture_output', False)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    or 'process_output_single' in extra)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  node = env.CommandTest(target,
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         command,
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         # Set to 'huge' so that the browser tester's timeout
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         # takes precedence over the default of the test_suite.
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         size='huge',
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         capture_output=capture_output,
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         **extra)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for side_effect in side_effects:
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    env.SideEffect(side_effect, node)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # We can't check output if the test is not run.
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not env.Bit('do_not_run_tests'):
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for action in post_actions:
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      env.AddPostAction(node, action)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return node
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pre_base_env.AddMethod(PPAPIBrowserTester)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Disabled for ARM and MIPS because Chrome binaries for ARM and MIPS are not
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# available.
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def PPAPIBrowserTesterIsBroken(env):
5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return env.Bit('target_arm') or env.Bit('target_mips32')
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pre_base_env.AddMethod(PPAPIBrowserTesterIsBroken)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 3D is disabled everywhere
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def PPAPIGraphics3DIsBroken(env):
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return True
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pre_base_env.AddMethod(PPAPIGraphics3DIsBroken)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def AddChromeFilesFromGroup(env, file_group):
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  env['BUILD_SCONSCRIPTS'] = ExtendFileList(
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      env.get('BUILD_SCONSCRIPTS', []),
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ppapi_scons_files[file_group])
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pre_base_env.AddMethod(AddChromeFilesFromGroup)
555