summaryrefslogtreecommitdiff
path: root/test/run-d8.py
blob: e0d9172f70bdd495db17b661d47e14925bf445aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/usr/bin/env python

import argparse
import os
import signal
import subprocess
import sys
import tempfile

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
REPO_ROOT_DIR = os.path.dirname(SCRIPT_DIR)
DEFAULT_EXE = os.path.join(REPO_ROOT_DIR, 'out', 'sexpr-wasm')
BUILT_D8 = os.path.join(REPO_ROOT_DIR, 'third_party', 'v8-native-prototype',
                        'v8', 'v8', 'out', 'Release', 'd8')
DOWNLOAD_D8 = os.path.join(REPO_ROOT_DIR, 'out', 'd8')
WASM_JS = os.path.join(SCRIPT_DIR, 'wasm.js')
SPEC_JS = os.path.join(SCRIPT_DIR, 'spec.js')

# Get signal names from numbers in Python
# http://stackoverflow.com/a/2549950
SIGNAMES = dict((k, v) for v, k in reversed(sorted(signal.__dict__.items()))
                       if v.startswith('SIG') and not v.startswith('SIG_'))

class Error(Exception):
  pass


def CleanD8Stdout(stdout):
  def FixLine(line):
    idx = line.find('WasmModule::Instantiate()')
    if idx != -1:
      return line[idx:]
    return line
  lines = [FixLine(line) for line in stdout.splitlines(1)]
  return ''.join(lines)


def CleanD8Stderr(stderr):
  idx = stderr.find('==== C stack trace')
  if idx != -1:
    stderr = stderr[:idx]
  return stderr.strip()


def main(args):
  parser = argparse.ArgumentParser()
  parser.add_argument('-e', '--executable', metavar='EXE',
                      help='override sexpr-wasm executable.')
  parser.add_argument('--d8-executable', metavar='EXE',
                      help='override d8 executable.')
  parser.add_argument('-v', '--verbose', help='print more diagnotic messages.',
                      action='store_true')
  parser.add_argument('--spec', help='run spec tests.', action='store_true')
  parser.add_argument('file', help='test file.')
  options = parser.parse_args(args)

  if options.executable:
    if not os.path.exists(options.executable):
      parser.error('executable %s does not exist' % options.executable)
    exe = os.path.abspath(options.executable)
  else:
    exe = DEFAULT_EXE

  d8 = options.d8_executable
  if not d8 or not os.path.exists(d8):
    d8 = BUILT_D8
    if not os.path.exists(d8):
      d8 = DOWNLOAD_D8
      if not os.path.exists(d8):
        raise Error('d8 executable does not exist.\n'
                    'Run scripts/build-d8.sh to build it.\n'
                    'path: %s\npath: %s\n' % (BUILT_D8, DOWNLOAD_D8))

  generated = None
  try:
    generated = tempfile.NamedTemporaryFile(prefix='sexpr-wasm-')
    # First compile the file
    cmd = [exe, options.file, '-o', generated.name]
    if options.verbose:
      cmd.append('-v')
    if options.spec:
      cmd.extend(['--spec', '--spec-verbose'])
    try:
      process = subprocess.Popen(cmd, stderr=subprocess.PIPE)
      _, stderr = process.communicate()
      if process.returncode != 0:
        raise Error(stderr)
    except OSError as e:
      raise Error(str(e))

    # Now run the generated file
    if options.spec:
      # The generated file is JavaScript, so run it directly.
      cmd = [d8, SPEC_JS, generated.name]
    else:
      cmd = [d8, WASM_JS, '--', generated.name]
    try:
      process = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                                      stderr=subprocess.PIPE)
      stdout, stderr = process.communicate()
      sys.stdout.write(CleanD8Stdout(stdout))
      msg = CleanD8Stderr(stderr)
      if process.returncode < 0:
        # Terminated by signal
        signame = SIGNAMES.get(-process.returncode, '<unknown>')
        if msg:
          msg += '\n\n'
        raise Error(msg + 'd8 raised signal ' + signame)
      elif process.returncode > 0:
        raise Error(msg)
    except OSError as e:
      raise Error(str(e))

  finally:
    if generated:
      generated.close()

  return 0


if __name__ == '__main__':
  try:
    sys.exit(main(sys.argv[1:]))
  except Error as e:
    sys.stderr.write(str(e) + '\n')
    sys.exit(1)