summaryrefslogtreecommitdiff
path: root/scripts/test/asm2wasm.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/test/asm2wasm.py')
-rw-r--r--scripts/test/asm2wasm.py160
1 files changed, 160 insertions, 0 deletions
diff --git a/scripts/test/asm2wasm.py b/scripts/test/asm2wasm.py
new file mode 100644
index 000000000..db37a237a
--- /dev/null
+++ b/scripts/test/asm2wasm.py
@@ -0,0 +1,160 @@
+#!/usr/bin/env python
+
+# Copyright 2017 WebAssembly Community Group participants
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import subprocess
+
+from support import run_command
+from shared import (
+ ASM2WASM, WASM_OPT, binary_format_check, delete_from_orbit,
+ fail, fail_with_error, fail_if_not_identical, options, tests
+)
+
+
+def test_asm2wasm():
+ print '[ checking asm2wasm testcases... ]\n'
+
+ for asm in tests:
+ if not asm.endswith('.asm.js'):
+ continue
+ for precise in [0, 1, 2]:
+ for opts in [1, 0]:
+ cmd = ASM2WASM + [os.path.join(options.binaryen_test, asm)]
+ wasm = asm.replace('.asm.js', '.fromasm')
+ if not precise:
+ cmd += ['--emit-potential-traps', '--ignore-implicit-traps']
+ wasm += '.imprecise'
+ elif precise == 2:
+ cmd += ['--emit-clamped-potential-traps']
+ wasm += '.clamp'
+ if not opts:
+ wasm += '.no-opts'
+ if precise:
+ cmd += ['-O0'] # test that -O0 does nothing
+ else:
+ cmd += ['-O']
+ if 'debugInfo' in asm:
+ cmd += ['-g']
+ if 'noffi' in asm:
+ cmd += ['--no-legalize-javascript-ffi']
+ if precise and opts:
+ # test mem init importing
+ open('a.mem', 'wb').write(asm)
+ cmd += ['--mem-init=a.mem']
+ if asm[0] == 'e':
+ cmd += ['--mem-base=1024']
+ if 'i64' in asm or 'wasm-only' in asm or 'noffi' in asm:
+ cmd += ['--wasm-only']
+ wasm = os.path.join(options.binaryen_test, wasm)
+ print '..', asm, wasm
+
+ def do_asm2wasm_test():
+ actual = run_command(cmd)
+
+ # verify output
+ if not os.path.exists(wasm):
+ fail_with_error('output .wast file %s does not exist' % wasm)
+ expected = open(wasm, 'rb').read()
+ if actual != expected:
+ fail(actual, expected)
+
+ binary_format_check(wasm, verify_final_result=False)
+
+ # test both normally and with pass debug (so each inter-pass state
+ # is validated)
+ old_pass_debug = os.environ.get('BINARYEN_PASS_DEBUG')
+ try:
+ os.environ['BINARYEN_PASS_DEBUG'] = '1'
+ print "With BINARYEN_PASS_DEBUG=1:"
+ do_asm2wasm_test()
+ del os.environ['BINARYEN_PASS_DEBUG']
+ print "With BINARYEN_PASS_DEBUG disabled:"
+ do_asm2wasm_test()
+ finally:
+ if old_pass_debug is not None:
+ os.environ['BINARYEN_PASS_DEBUG'] = old_pass_debug
+ else:
+ if 'BINARYEN_PASS_DEBUG' in os.environ:
+ del os.environ['BINARYEN_PASS_DEBUG']
+
+ # verify in wasm
+ if options.interpreter:
+ # remove imports, spec interpreter doesn't know what to do with them
+ subprocess.check_call(WASM_OPT + ['--remove-imports', wasm],
+ stdout=open('ztemp.wast', 'w'),
+ stderr=subprocess.PIPE)
+ proc = subprocess.Popen([options.interpreter, 'ztemp.wast'],
+ stderr=subprocess.PIPE)
+ out, err = proc.communicate()
+ if proc.returncode != 0:
+ try: # to parse the error
+ reported = err.split(':')[1]
+ start, end = reported.split('-')
+ start_line, start_col = map(int, start.split('.'))
+ lines = open('ztemp.wast').read().split('\n')
+ print
+ print '=' * 80
+ print lines[start_line - 1]
+ print (' ' * (start_col - 1)) + '^'
+ print (' ' * (start_col - 2)) + '/_\\'
+ print '=' * 80
+ print err
+ except Exception:
+ # failed to pretty-print
+ fail_with_error('wasm interpreter error: ' + err)
+ fail_with_error('wasm interpreter error')
+
+ # verify debug info
+ if 'debugInfo' in asm:
+ jsmap = 'a.wasm.map'
+ cmd += ['--source-map', jsmap,
+ '--source-map-url', 'http://example.org/' + jsmap,
+ '-o', 'a.wasm']
+ run_command(cmd)
+ if not os.path.isfile(jsmap):
+ fail_with_error('Debug info map not created: %s' % jsmap)
+ with open(wasm + '.map', 'rb') as expected:
+ with open(jsmap, 'rb') as actual:
+ fail_if_not_identical(actual.read(), expected.read())
+ with open('a.wasm', 'rb') as binary:
+ url_section_name = bytearray([16]) + bytearray('sourceMappingURL')
+ url = 'http://example.org/' + jsmap
+ assert len(url) < 256, 'name too long'
+ url_section_contents = bytearray([len(url)]) + bytearray(url)
+ print url_section_name
+ binary_contents = bytearray(binary.read())
+ if url_section_name not in binary_contents:
+ fail_with_error('source map url section not found in binary')
+ url_section_index = binary_contents.index(url_section_name)
+ if url_section_contents not in binary_contents[url_section_index:]:
+ fail_with_error('source map url not found in url section')
+
+
+def test_asm2wasm_binary():
+ print '\n[ checking asm2wasm binary reading/writing... ]\n'
+
+ asmjs = os.path.join(options.binaryen_test, 'hello_world.asm.js')
+ delete_from_orbit('a.wasm')
+ delete_from_orbit('b.wast')
+ run_command(ASM2WASM + [asmjs, '-o', 'a.wasm'])
+ assert open('a.wasm', 'rb').read()[0] == '\0', 'we emit binary by default'
+ run_command(ASM2WASM + [asmjs, '-o', 'b.wast', '-S'])
+ assert open('b.wast', 'rb').read()[0] != '\0', 'we emit text with -S'
+
+
+if __name__ == '__main__':
+ test_asm2wasm()
+ test_asm2wasm_binary()