summaryrefslogtreecommitdiff
path: root/check.py
diff options
context:
space:
mode:
Diffstat (limited to 'check.py')
-rwxr-xr-xcheck.py173
1 files changed, 144 insertions, 29 deletions
diff --git a/check.py b/check.py
index b11445bf4..0792bd03d 100755
--- a/check.py
+++ b/check.py
@@ -14,7 +14,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import os, shutil, sys, subprocess, difflib, json, time
+import os, shutil, sys, subprocess, difflib, json, time, urllib2
+
+import scripts.storage
+import scripts.support
interpreter = None
requested = []
@@ -32,14 +35,65 @@ for arg in sys.argv[1:]:
else:
requested.append(arg)
+warnings = []
+
+def warn(text):
+ global warnings
+ warnings.append(text)
+ print 'warning:', text
+
+# setup
+
+BASE_DIR = os.path.abspath('test')
+WATERFALL_BUILD_DIR = os.path.join(BASE_DIR, 'wasm-install')
+BIN_DIR = os.path.abspath(os.path.join(WATERFALL_BUILD_DIR, 'wasm-install', 'bin'))
+
+def fetch_waterfall():
+ rev = open(os.path.join('test', 'revision')).read().strip()
+ try:
+ local_rev = open(os.path.join('test', 'local-revision')).read().strip()
+ except:
+ local_rev = None
+ if local_rev == rev: return
+ # fetch it
+ print '(downloading waterfall ' + rev + ')'
+ basename = 'wasm-binaries-' + rev + '.tbz2'
+ downloaded = urllib2.urlopen('https://storage.googleapis.com/wasm-llvm/builds/git/' + basename).read().strip()
+ fullname = os.path.join('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', '-xvf', os.path.abspath(fullname)], cwd=WATERFALL_BUILD_DIR)
+ print '(noting local revision)'
+ open(os.path.join('test', 'local-revision'), 'w').write(rev)
+
+def setup_waterfall():
+ # if we can use the waterfall llvm, do so
+ CLANG = os.path.join(BIN_DIR, 'clang')
+ try:
+ subprocess.check_call([CLANG, '-v'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ os.environ['LLVM'] = BIN_DIR
+ except Exception, e:
+ warn('could not run vanilla LLVM from waterfall: ' + str(e) + ', looked for clang at ' + CLANG)
+
+fetch_waterfall()
+setup_waterfall()
+
+
# external tools
has_node = False
try:
subprocess.check_call(['nodejs', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- has_node = True
+ has_node = 'nodejs'
except:
- pass
+ try:
+ subprocess.check_call(['node', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ has_node = 'node'
+ except:
+ pass
has_mozjs = False
try:
@@ -55,6 +109,13 @@ try:
except:
pass
+has_vanilla_emcc = False
+try:
+ subprocess.check_call([os.path.join('test', 'emscripten', 'emcc'), '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ has_vanilla_emcc = True
+except:
+ pass
+
# utilities
def fail(actual, expected):
@@ -76,13 +137,18 @@ else:
tests = requested[:]
if not interpreter:
- print 'warning: no interpreter provided (not testing spec interpreter validation)'
+ warn('no interpreter provided (did not test spec interpreter validation)')
if not has_node:
- print 'warning: no node found (not checking proper js form)'
+ warn('no node found (did not check proper js form)')
if not has_mozjs:
- print 'warning: no mozjs found (not checking asm.js validation)'
+ warn('no mozjs found (did not check asm.js validation)')
if not has_emcc:
- print 'warning: no emcc found (not checking emscripten/binaryen integration)'
+ warn('no emcc found (did not check non-vanilla emscripten/binaryen integration)')
+if not has_vanilla_emcc:
+ warn('no functional emcc submodule found')
+
+
+# tests
print '[ checking asm2wasm testcases... ]\n'
@@ -218,7 +284,7 @@ for wasm in tests + [os.path.join('spec', name) for name in ['address.wast']]:#s
if has_node:
# verify asm.js is valid js
- proc = subprocess.Popen(['nodejs', 'a.2asm.js'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ proc = subprocess.Popen([has_node, 'a.2asm.js'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate()
assert proc.returncode == 0
assert not out and not err, [out, err]
@@ -276,20 +342,83 @@ if torture:
fails=os.path.abspath(os.path.join('test', 's2wasm_known_gcc_test_failures.txt')),
out=s2wasm_torture_out)
assert os.path.isdir(s2wasm_torture_out), 'Expected output directory %s' % s2wasm_torture_out
+ # execute it TODO: parallelize, use waterfall
+ known_failures = set(open(os.path.join('test', 's2wasm_known_binaryen_shell_test_failures.txt')).read().split('\n'))
+ total = 0
+ bad_failures = []
+ for wast in sorted(os.listdir(s2wasm_torture_out)):
+ total += 1
+ cmd = [os.path.join('bin', 'binaryen-shell'), os.path.join(s2wasm_torture_out, wast), '--entry=main']
+ print ' '.join(cmd)
+ try:
+ subprocess.check_call(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ except:
+ if wast not in known_failures:
+ bad_failures.append(wast)
+ if len(bad_failures) > 0:
+ print '\nbad failures:\n'
+ print '\n'.join(bad_failures)
+ raise Exception('bad failures :( %d out of %d' % (len(bad_failures), total))
shutil.rmtree(s2wasm_torture_out)
if unexpected_result_count:
fail(unexpected_result_count, 0)
-print '\n[ checking wasm-as testcases... ]\n'
+print '\n[ checking binary format testcases... ]\n'
for wast in tests:
if wast.endswith('.wast') and not wast in ['unit.wast']: # blacklist some known failures
cmd = [os.path.join('bin', 'wasm-as'), os.path.join('test', wast), '-o', 'a.wasm']
- print cmd
+ print ' '.join(cmd)
if os.path.exists('a.wasm'): os.unlink('a.wasm')
subprocess.check_call(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
assert os.path.exists('a.wasm')
+ cmd = [os.path.join('bin', 'wasm-dis'), 'a.wasm', '-o', 'a.wast']
+ print ' '.join(cmd)
+ if os.path.exists('a.wast'): os.unlink('a.wast')
+ subprocess.check_call(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ assert os.path.exists('a.wast')
+ expected = open(os.path.join('test', wast + '.fromBinary')).read()
+ actual = open('a.wast').read()
+ if actual != expected:
+ fail(actual, expected)
+
+if has_vanilla_emcc:
+
+ print '\n[ checking emcc WASM_BACKEND testcases... (llvm: %s)]\n' % (os.environ.get('LLVM') or 'NULL')
+
+ # if we did not set vanilla llvm, then we must set this env var to make emcc use the wasm backend.
+ # or, if we are using vanilla llvm, things should just work.
+ if not os.environ.get('LLVM'):
+ print '(not using vanilla llvm, so settng env var to tell emcc to use wasm backend)'
+ os.environ['EMCC_WASM_BACKEND'] = '1'
+ try:
+ VANILLA_EMCC = os.path.join('test', 'emscripten', 'emcc')
+ # run emcc to make sure it sets itself up properly, if it was never run before
+ command = [VANILLA_EMCC, '-v']
+ print '____' + ' '.join(command)
+ subprocess.check_call(command)
+
+ for c in sorted(os.listdir(os.path.join('test', 'wasm_backend'))):
+ if not c.endswith('cpp'): continue
+ print '..', c
+ base = c.replace('.cpp', '').replace('.c', '')
+ expected = open(os.path.join('test', 'wasm_backend', base + '.txt')).read()
+ command = [VANILLA_EMCC, '-o', 'a.wasm.js', '-s', 'BINARYEN="' + os.getcwd() + '"', os.path.join('test', 'wasm_backend', c), '-O1', '-s', 'ONLY_MY_CODE=1']
+ print '....' + ' '.join(command)
+ if os.path.exists('a.wasm.js'): os.unlink('a.wasm.js')
+ subprocess.check_call(command)
+ if has_node:
+ print ' (check in node)'
+ proc = subprocess.Popen([has_node, 'a.wasm.js'], stdout=subprocess.PIPE)
+ out, err = proc.communicate()
+ assert proc.returncode == 0
+ if out.strip() != expected.strip():
+ fail(out, expected)
+ finally:
+ if not os.environ.get('LLVM'):
+ del os.environ['EMCC_WASM_BACKEND']
+
print '\n[ checking example testcases... ]\n'
cmd = [os.environ.get('CXX') or 'g++', '-std=c++11', os.path.join('test', 'example', 'find_div0s.cpp'), '-Isrc', '-g', '-lsupport', '-Llib/.']
@@ -337,7 +466,7 @@ if has_emcc:
else:
1/0
if has_node:
- proc = subprocess.Popen(['nodejs', 'a.wasm.js'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ proc = subprocess.Popen([has_node, 'a.wasm.js'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate()
if success:
assert proc.returncode == 0
@@ -346,23 +475,6 @@ if has_emcc:
assert proc.returncode != 0
assert 'hello, world!' not in out
- print '\n[ checking emcc WASM_BACKEND testcases... ]\n'
-
- for c in sorted(os.listdir(os.path.join('test', 'wasm_backend'))):
- if not c.endswith('cpp'): continue
- print '..', c
- base = c.replace('.cpp', '').replace('.c', '')
- expected = open(os.path.join('test', 'wasm_backend', base + '.txt')).read()
- command = ['emcc', '-o', 'a.wasm.js', '-s', 'BINARYEN="' + os.getcwd() + '"', os.path.join('test', 'wasm_backend', c), '-O1', '-s', 'WASM_BACKEND=1', '-s', 'ONLY_MY_CODE=1']
- print '....' + ' '.join(command)
- subprocess.check_call(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- if has_node:
- proc = subprocess.Popen(['nodejs', 'a.wasm.js'], stdout=subprocess.PIPE)
- out, err = proc.communicate()
- assert proc.returncode == 0
- if out.strip() != expected.strip():
- fail(out, expected)
-
print '\n[ checking wasm.js testcases... ]\n'
for c in tests:
@@ -398,10 +510,13 @@ if has_emcc:
args = []
print ' (no args)'
if has_node:
- proc = subprocess.Popen(['nodejs', 'a.' + which + '.js'] + args, stdout=subprocess.PIPE)
+ proc = subprocess.Popen([has_node, 'a.' + which + '.js'] + args, stdout=subprocess.PIPE)
out, err = proc.communicate()
assert proc.returncode == 0
if out.strip() != expected.strip():
fail(out, expected)
print '\n[ success! ]'
+
+if warnings:
+ print '\n' + '\n'.join(warnings)