#!/usr/bin/env python # # Copyright 2016 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 from support import run_command from shared import ( fail_with_error, fail_if_not_contained, options, S2WASM, WASM_SHELL, fail_if_not_identical_to_file ) def test_s2wasm(): print '\n[ checking .s testcases... ]\n' cmd = S2WASM + [ os.path.join(options.binaryen_test, 'dot_s', 'basics.s'), '--import-memory'] output = run_command(cmd) fail_if_not_contained( output, '(import "env" "memory" (memory $0 1))') extension_arg_map = { '.wast': [], '.clamp.wast': ['--trap-mode=clamp'], '.js.wast': ['--trap-mode=js'], '.jscall.wast': ['--emscripten-reserved-function-pointers=3'], } for dot_s_dir in ['dot_s', 'llvm_autogenerated']: dot_s_path = os.path.join(options.binaryen_test, dot_s_dir) for s in sorted(os.listdir(dot_s_path)): if not s.endswith('.s'): continue print '..', s for ext, ext_args in extension_arg_map.iteritems(): wasm = s.replace('.s', ext) expected_file = os.path.join(options.binaryen_test, dot_s_dir, wasm) expected_exists = os.path.exists(expected_file) if ext != '.wast' and not expected_exists: continue full = os.path.join(options.binaryen_test, dot_s_dir, s) stack_alloc = (['--allocate-stack=1024'] if dot_s_dir == 'llvm_autogenerated' else []) cmd = S2WASM + [full, '--emscripten-glue'] + stack_alloc + ext_args if s.startswith('start_'): cmd.append('--start') actual = run_command(cmd) # verify output if not expected_exists: print actual fail_with_error('output ' + expected_file + ' does not exist') fail_if_not_identical_to_file(actual, expected_file) # verify with options cmd = S2WASM + [full, '--global-base=1024'] + stack_alloc run_command(cmd) # run wasm-shell on the .wast to verify that it parses cmd = WASM_SHELL + [expected_file] run_command(cmd) def test_linker(): print '\n[ running linker tests... ]\n' # The {main,foo,bar,baz}.s files were created by running clang over the # respective c files. The foobar.bar archive was created by running: # llvm-ar -format=gnu rc foobar.a quux.s foo.s bar.s baz.s cmd = S2WASM + [ os.path.join(options.binaryen_test, 'linker', 'main.s'), '-l', os.path.join(options.binaryen_test, 'linker', 'archive', 'foobar.a')] output = run_command(cmd) # foo should come from main.s and return 42 fail_if_not_contained(output, '(func $foo') fail_if_not_contained(output, '(i32.const 42)') # bar should be linked in from bar.s fail_if_not_contained(output, '(func $bar') # quux should be linked in from bar.s even though it comes before bar.s in # the archive fail_if_not_contained(output, '(func $quux') # baz should not be linked in at all if 'baz' in output: fail_with_error('output should not contain "baz": ' + output) # Test an archive using a string table cmd = S2WASM + [ os.path.join(options.binaryen_test, 'linker', 'main.s'), '-l', os.path.join(options.binaryen_test, 'linker', 'archive', 'barlong.a')] output = run_command(cmd) # bar should be linked from the archive fail_if_not_contained(output, '(func $bar') # Test exporting memory growth function and emscripten runtime functions cmd = S2WASM + [ os.path.join(options.binaryen_test, 'linker', 'main.s'), '--emscripten-glue', '--allow-memory-growth'] output = run_command(cmd) expected_funcs = [ ('__growWasmMemory', '(param $newSize i32)'), ('stackSave', '(result i32)'), ('stackAlloc', '(param $0 i32) (result i32)'), ('stackRestore', '(param $0 i32)'), ] for name, extra in expected_funcs: space = ' ' if extra else '' fail_if_not_contained(output, '(export "{0}" (func ${0}))'.format(name)) for line in output.split('\n'): if '(func ${0}'.format(name + space) in line: # we found the relevant line for the function definition. remove # a (; X ;) comment with its index start = line.find('(; ') if start >= 0: end = line.find(' ;)') line = line[:start] + line[end + 4:] fail_if_not_contained(line, '(func ${0}'.format(name + space + extra)) if __name__ == '__main__': test_s2wasm() test_linker()