#! -*- 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'))

# 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 = {}
ppapi_scons_files['trusted_scons_files'] = []
ppapi_scons_files['untrusted_irt_scons_files'] = []

ppapi_scons_files['nonvariant_test_scons_files'] = [
    'tests/breakpad_crash_test/nacl.scons',
    'tests/nacl_browser/browser_dynamic_library/nacl.scons',
    'tests/nacl_browser/manifest_file/nacl.scons',
    'tests/nacl_browser/nameservice/nacl.scons',
    'tests/ppapi_browser/bad/nacl.scons',
    'tests/ppapi_browser/extension_mime_handler/nacl.scons',
    'tests/ppapi_browser/manifest/nacl.scons',
    'tests/ppapi_test_lib/nacl.scons',
]

ppapi_scons_files['irt_variant_test_scons_files'] = [
    # 'inbrowser_test_runner' must be in the irt_variant list
    # otherwise it will run no tests.
    'tests/nacl_browser/inbrowser_test_runner/nacl.scons',
    # Disabled by Brad Chen 4 Sep to try to green Chromium
    # nacl_integration tests
    #'tests/nacl_browser/fault_injection/nacl.scons',
]

ppapi_scons_files['untrusted_scons_files'] = [
    'src/shared/ppapi/nacl.scons',
    'src/untrusted/irt_stub/nacl.scons',
    'src/untrusted/nacl_ppapi_util/nacl.scons',
]


EXTRA_ENV = [
    'XAUTHORITY', 'HOME', 'DISPLAY', 'SSH_TTY', 'KRB5CCNAME',
    'CHROME_DEVEL_SANDBOX' ]

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)


# A fake file to depend on if a path to Chrome is not specified.
no_browser = pre_base_env.File('chrome_browser_path_not_specified')


# SCons attempts to run a test that depends on "no_browser", detect this at
# runtime and cause a build error.
def NoBrowserError(target, source, env):
  print target, source, env
  print ("***\nYou need to specificy chrome_browser_path=... on the " +
         "command line to run these tests.\n***\n")
  return 1

pre_base_env.Append(BUILDERS = {
    'NoBrowserError': Builder(action=NoBrowserError)
})

pre_base_env.NoBrowserError([no_browser], [])


def ChromeBinary(env):
  if 'chrome_browser_path' in ARGUMENTS:
    return env.File(env.SConstructAbsPath(ARGUMENTS['chrome_browser_path']))
  else:
    return no_browser

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
      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 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('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']
  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.
  # For nacl_glibc, generating the mapping of shared libraries is non-trivial.
  if not env.Bit('nacl_glibc'):
    env.Install('${STAGING_DIR}', manifest)
    return result
  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


# 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 = []

  # 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)]
  for dep_file in files:
    command.extend(['--file', dep_file])
  for extension in extensions:
    command.extend(['--extension', extension])
  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)
  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)
