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

ppapi_scons_files['untrusted_scons_files'] = [
    'src/shared/ppapi/nacl.scons',
    'src/untrusted/irt_stub/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)


# 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('build_arm') or env.Bit('build_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)
