import argparse
import difflib
import os
import shutil
import subprocess
import sys
import urllib2


usage_str = ("usage: 'python check.py [options]'\n\n"
             "Runs the Binaryen test suite.")
parser = argparse.ArgumentParser(description=usage_str)
parser.add_argument(
    '--torture', dest='torture', action='store_true', default=True,
    help='Chooses whether to run the torture testcases. Default: true.')
parser.add_argument(
    '--no-torture', dest='torture', action='store_false',
    help='Disables running the torture testcases.')
parser.add_argument(
    '--only-prepare', dest='only_prepare', action='store_true', default=False,
    help='If enabled, only fetches the waterfall build. Default: false.')
parser.add_argument(
    # Backwards compatibility
    '--only_prepare', dest='only_prepare', action='store_true', default=False,
    help='If enabled, only fetches the waterfall build. Default: false.')
parser.add_argument(
    '--test-waterfall', dest='test_waterfall', action='store_true',
    default=False,
    help=('If enabled, fetches and tests the LLVM waterfall builds.'
          ' Default: false.'))
parser.add_argument(
    '--no-test-waterfall', dest='test_waterfall', action='store_false',
    help='Disables downloading and testing of the LLVM waterfall builds.')
parser.add_argument(
    '--abort-on-first-failure', dest='abort_on_first_failure',
    action='store_true', default=True,
    help=('Specifies whether to halt test suite execution on first test error.'
          ' Default: true.'))
parser.add_argument(
    '--no-abort-on-first-failure', dest='abort_on_first_failure',
    action='store_false',
    help=('If set, the whole test suite will run to completion independent of'
          ' earlier errors.'))
parser.add_argument(
    '--run-gcc-tests', dest='run_gcc_tests', action='store_true', default=True,
    help=('Chooses whether to run the tests that require building with native'
          ' GCC. Default: true.'))
parser.add_argument(
    '--no-run-gcc-tests', dest='run_gcc_tests', action='store_false',
    help='If set, disables the native GCC tests.')

parser.add_argument(
    '--interpreter', dest='interpreter', default='',
    help='Specifies the wasm interpreter executable to run tests on.')
parser.add_argument(
    '--binaryen-bin', dest='binaryen_bin', default='',
    help=('Specifies a path to where the built Binaryen executables reside at.'
          ' Default: bin/ of current directory (i.e. assume an in-tree build).'
          ' If not specified, the environment variable BINARYEN_ROOT= can also'
          ' be used to adjust this.'))
parser.add_argument(
    '--binaryen-root', dest='binaryen_root', default='',
    help=('Specifies a path to the root of the Binaryen repository tree.'
          ' Default: the directory where this file check.py resides.'))
parser.add_argument(
    '--valgrind', dest='valgrind', default='',
    help=('Specifies a path to Valgrind tool, which will be used to validate'
          ' execution if specified. (Pass --valgrind=valgrind to search in'
          ' PATH)'))
parser.add_argument(
    '--valgrind-full-leak-check', dest='valgrind_full_leak_check',
    action='store_true', default=False,
    help=('If specified, all unfreed (but still referenced) pointers at the'
          ' end of execution are considered memory leaks. Default: disabled.'))

parser.add_argument(
    'positional_args', metavar='tests', nargs=argparse.REMAINDER,
    help='Names specific tests to run.')
options = parser.parse_args()
requested = options.positional_args

num_failures = 0
warnings = []


def warn(text):
  global warnings
  warnings.append(text)
  print 'warning:', text


# setup

# Locate Binaryen build artifacts directory (bin/ by default)
if not options.binaryen_bin:
  if os.environ.get('BINARYEN_ROOT'):
    if os.path.isdir(os.path.join(os.environ.get('BINARYEN_ROOT'), 'bin')):
      options.binaryen_bin = os.path.join(
          os.environ.get('BINARYEN_ROOT'), 'bin')
    else:
      options.binaryen_bin = os.environ.get('BINARYEN_ROOT')
  else:
    options.binaryen_bin = 'bin'

options.binaryen_bin = os.path.normpath(options.binaryen_bin)

wasm_dis_filenames = ['wasm-dis', 'wasm-dis.exe']
if not any(os.path.isfile(os.path.join(options.binaryen_bin, f))
           for f in wasm_dis_filenames):
  warn('Binaryen not found (or has not been successfully built to bin/ ?')

# Locate Binaryen source directory if not specified.
if not options.binaryen_root:
  path_parts = os.path.abspath(__file__).split(os.path.sep)
  options.binaryen_root = os.path.sep.join(path_parts[:-3])

options.binaryen_test = os.path.join(options.binaryen_root, 'test')


# Finds the given executable 'program' in PATH.
# Operates like the Unix tool 'which'.
def which(program):
  def is_exe(fpath):
    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
  fpath, fname = os.path.split(program)
  if fpath:
    if is_exe(program):
      return program
  else:
    for path in os.environ["PATH"].split(os.pathsep):
      path = path.strip('"')
      exe_file = os.path.join(path, program)
      if is_exe(exe_file):
        return exe_file
      if '.' not in fname:
        if is_exe(exe_file + '.exe'):
          return exe_file + '.exe'
        if is_exe(exe_file + '.cmd'):
          return exe_file + '.cmd'
        if is_exe(exe_file + '.bat'):
          return exe_file + '.bat'


WATERFALL_BUILD_DIR = os.path.join(options.binaryen_test, 'wasm-install')
BIN_DIR = os.path.abspath(os.path.join(
    WATERFALL_BUILD_DIR, 'wasm-install', 'bin'))

NATIVECC = (os.environ.get('CC') or which('mingw32-gcc') or
            which('gcc') or which('clang'))
NATIVEXX = (os.environ.get('CXX') or which('mingw32-g++') or
            which('g++') or which('clang++'))
NODEJS = which('nodejs') or which('node')
MOZJS = which('mozjs')
EMCC = which('emcc')

BINARYEN_INSTALL_DIR = os.path.dirname(options.binaryen_bin)
WASM_OPT = [os.path.join(options.binaryen_bin, 'wasm-opt')]
WASM_AS = [os.path.join(options.binaryen_bin, 'wasm-as')]
WASM_DIS = [os.path.join(options.binaryen_bin, 'wasm-dis')]
ASM2WASM = [os.path.join(options.binaryen_bin, 'asm2wasm')]
WASM2ASM = [os.path.join(options.binaryen_bin, 'wasm2asm')]
WASM_CTOR_EVAL = [os.path.join(options.binaryen_bin, 'wasm-ctor-eval')]
WASM_SHELL = [os.path.join(options.binaryen_bin, 'wasm-shell')]
WASM_MERGE = [os.path.join(options.binaryen_bin, 'wasm-merge')]
S2WASM = [os.path.join(options.binaryen_bin, 's2wasm')]
WASM_REDUCE = [os.path.join(options.binaryen_bin, 'wasm-reduce')]

S2WASM_EXE = S2WASM[0]
WASM_SHELL_EXE = WASM_SHELL[0]


def wrap_with_valgrind(cmd):
  # Exit code 97 is arbitrary, used to easily detect when an error occurs that
  # is detected by Valgrind.
  valgrind = [options.valgrind, '--quiet', '--error-exitcode=97']
  if options.valgrind_full_leak_check:
    valgrind += ['--leak-check=full', '--show-leak-kinds=all']
  return valgrind + cmd


if options.valgrind:
  WASM_OPT = wrap_with_valgrind(WASM_OPT)
  WASM_AS = wrap_with_valgrind(WASM_AS)
  WASM_DIS = wrap_with_valgrind(WASM_DIS)
  ASM2WASM = wrap_with_valgrind(ASM2WASM)
  WASM_SHELL = wrap_with_valgrind(WASM_SHELL)
  S2WASM = wrap_with_valgrind(S2WASM)

os.environ['BINARYEN'] = os.getcwd()


def get_platform():
  return {'linux2': 'linux',
          'darwin': 'mac',
          'win32': 'windows',
          'cygwin': 'windows'}[sys.platform]


def has_shell_timeout():
  return get_platform() != 'windows' and os.system('timeout 1s pwd') == 0


def fetch_waterfall():
  rev = open(os.path.join(options.binaryen_test, 'revision')).read().strip()
  buildername = get_platform()
  local_rev_path = os.path.join(WATERFALL_BUILD_DIR, 'local-revision')
  if os.path.exists(local_rev_path):
    with open(local_rev_path) as f:
      local_rev = f.read().strip()
    if local_rev == rev:
      return
  # fetch it
  basename = 'wasm-binaries-' + rev + '.tbz2'
  url = '/'.join(['https://storage.googleapis.com/wasm-llvm/builds',
                  buildername, rev, basename])
  print '(downloading waterfall %s: %s)' % (rev, url)
  downloaded = urllib2.urlopen(url).read().strip()
  fullname = os.path.join(options.binaryen_test, basename)
  open(fullname, 'wb').write(downloaded)
  print '(unpacking)'
  if os.path.exists(WATERFALL_BUILD_DIR):
    shutil.rmtree(WATERFALL_BUILD_DIR)
  os.mkdir(WATERFALL_BUILD_DIR)
  subprocess.check_call(['tar', '-xf', os.path.abspath(fullname)],
                        cwd=WATERFALL_BUILD_DIR)
  print '(noting local revision)'
  with open(local_rev_path, 'w') as o:
    o.write(rev + '\n')


has_vanilla_llvm = False


def setup_waterfall():
  # if we can use the waterfall llvm, do so
  global has_vanilla_llvm
  CLANG = os.path.join(BIN_DIR, 'clang')
  print 'trying waterfall clang at', CLANG
  try:
    subprocess.check_call([CLANG, '-v'])
    has_vanilla_llvm = True
    print '...success'
  except (OSError, subprocess.CalledProcessError) as e:
    warn('could not run vanilla LLVM from waterfall: ' + str(e) +
         ', looked for clang at ' + CLANG)


if options.test_waterfall:
  fetch_waterfall()
  setup_waterfall()

if options.only_prepare:
  print 'waterfall is fetched and setup, exiting since --only-prepare'
  sys.exit(0)

# external tools

try:
  if NODEJS is not None:
    subprocess.check_call(
        [NODEJS, '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except (OSError, subprocess.CalledProcessError):
  NODEJS = None
if NODEJS is None:
  warn('no node found (did not check proper js form)')

try:
  if MOZJS is not None:
    subprocess.check_call(
        [MOZJS, '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except (OSError, subprocess.CalledProcessError):
  MOZJS = None
if MOZJS is None:
  warn('no mozjs found (did not check native wasm support nor asm.js'
       ' validation)')

try:
  if EMCC is not None:
    subprocess.check_call(
        [EMCC, '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except (OSError, subprocess.CalledProcessError):
  EMCC = None
if EMCC is None:
  warn('no emcc found (did not check non-vanilla emscripten/binaryen'
       ' integration)')

has_vanilla_emcc = False
try:
  subprocess.check_call(
      [os.path.join(options.binaryen_test, 'emscripten', 'emcc'), '--version'],
      stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  has_vanilla_emcc = True
except (OSError, subprocess.CalledProcessError):
  pass


# utilities

# removes a file if it exists, using any and all ways of doing so
def delete_from_orbit(filename):
  try:
    os.unlink(filename)
  except OSError:
    pass
  if not os.path.exists(filename):
    return
  try:
    shutil.rmtree(filename, ignore_errors=True)
  except OSError:
    pass
  if not os.path.exists(filename):
    return
  try:
    import stat
    os.chmod(filename, os.stat(filename).st_mode | stat.S_IWRITE)

    def remove_readonly_and_try_again(func, path, exc_info):
      if not (os.stat(path).st_mode & stat.S_IWRITE):
        os.chmod(path, os.stat(path).st_mode | stat.S_IWRITE)
        func(path)
      else:
        raise
    shutil.rmtree(filename, onerror=remove_readonly_and_try_again)
  except OSError:
    pass


def fail_with_error(msg):
  global num_failures
  try:
    num_failures += 1
    raise Exception(msg)
  except Exception, e:
    print >> sys.stderr, str(e)
    if options.abort_on_first_failure:
      raise


def fail(actual, expected):
  diff_lines = difflib.unified_diff(
      expected.split('\n'), actual.split('\n'),
      fromfile='expected', tofile='actual')
  diff_str = ''.join([a.rstrip() + '\n' for a in diff_lines])[:]
  fail_with_error("incorrect output, diff:\n\n%s" % diff_str)


def fail_if_not_identical(actual, expected):
  if expected != actual:
    fail(actual, expected)


def fail_if_not_contained(actual, expected):
  if expected not in actual:
    fail(actual, expected)


if len(requested) == 0:
  tests = sorted(os.listdir(os.path.join(options.binaryen_test)))
else:
  tests = requested[:]

if not options.interpreter:
  warn('no interpreter provided (did not test spec interpreter validation)')

if not has_vanilla_emcc:
  warn('no functional emcc submodule found')


# check utilities

def binary_format_check(wast, verify_final_result=True, wasm_as_args=['-g'],
                        binary_suffix='.fromBinary'):
  # checks we can convert the wast to binary and back

  print '     (binary format check)'
  cmd = WASM_AS + [wast, '-o', 'a.wasm'] + wasm_as_args
  print '      ', ' '.join(cmd)
  if os.path.exists('a.wasm'):
    os.unlink('a.wasm')
  subprocess.check_call(cmd, stdout=subprocess.PIPE)
  assert os.path.exists('a.wasm')

  cmd = WASM_DIS + ['a.wasm', '-o', 'ab.wast']
  print '      ', ' '.join(cmd)
  if os.path.exists('ab.wast'):
    os.unlink('ab.wast')
  subprocess.check_call(cmd, stdout=subprocess.PIPE)
  assert os.path.exists('ab.wast')

  # make sure it is a valid wast
  cmd = WASM_OPT + ['ab.wast']
  print '      ', ' '.join(cmd)
  subprocess.check_call(cmd, stdout=subprocess.PIPE)

  if verify_final_result:
    expected = open(wast + binary_suffix).read()
    actual = open('ab.wast').read()
    if actual != expected:
      fail(actual, expected)

  return 'ab.wast'


def minify_check(wast, verify_final_result=True):
  # checks we can parse minified output

  print '     (minify check)'
  cmd = WASM_OPT + [wast, '--print-minified']
  print '      ', ' '.join(cmd)
  subprocess.check_call(
      WASM_OPT + [wast, '--print-minified'],
      stdout=open('a.wast', 'w'), stderr=subprocess.PIPE)
  assert os.path.exists('a.wast')
  subprocess.check_call(
      WASM_OPT + ['a.wast', '--print-minified'],
      stdout=open('b.wast', 'w'), stderr=subprocess.PIPE)
  assert os.path.exists('b.wast')
  if verify_final_result:
    expected = open('a.wast').read()
    actual = open('b.wast').read()
    if actual != expected:
      fail(actual, expected)
  if os.path.exists('a.wast'):
    os.unlink('a.wast')
  if os.path.exists('b.wast'):
    os.unlink('b.wast')
