diff options
Diffstat (limited to 'check.py')
-rwxr-xr-x | check.py | 173 |
1 files changed, 144 insertions, 29 deletions
@@ -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) |