#! -*- 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/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
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 []

  # 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_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)
