def test_exports_all_kind(): module = Module( Store(), """ (module (func (export "func") (param i32 i64)) (global (export "glob") i32 (i32.const 7)) (table (export "tab") 0 funcref) (memory (export "mem") 1)) """) instance = Instance(module) exports = instance.exports assert isinstance(exports, Exports) assert isinstance(exports.func, Function) assert isinstance(exports.glob, Global) assert isinstance(exports.tab, Table) assert isinstance(exports.mem, Memory)
def validate_wasm(base64_encoded_bot): try: wasm_bytes = b64decode(base64_encoded_bot) module = Module(wasm_bytes) except: # invalid base64 or wasm return False # module should not require any imports if module.imports != []: return False # module should only export makeMove exports = [ f["name"] for f in module.exports if f["kind"] == ExportKind.FUNCTION ] return exports == ["makeMove"]
def test_import_object_extend(): import_object = Module(TEST_BYTES).generate_import_object() import_object.extend({ "env": { "sum": lambda x, y: x + y, } }) import_descriptors = import_object.import_descriptors() assert import_object.import_descriptors() == [ {'kind': ImportKind.FUNCTION, 'name': 'sum', 'namespace': 'env'} ]
def build_instance(): import_object = ImportObject() store = Store(engine.JIT(Compiler)) import_object.register( "env", { "__sys_getpid": Function(store, lambda: 42, FunctionType([], [Type.I32])), }) import_object.register( "wasi_snapshot_preview1", { "proc_exit": Function(store, lambda *args: None, FunctionType([Type.I32], [])), "clock_time_get": Function(store, lambda *args: int(time.time()), FunctionType([Type.I32, Type.I64, Type.I32], [Type.I32])), "fd_close": Function(store, lambda *args: 1, FunctionType([Type.I32], [Type.I32])), "fd_write": Function( store, lambda *args: 1, FunctionType([Type.I32, Type.I32, Type.I32, Type.I32], [Type.I32])), "fd_seek": Function( store, lambda *args: 1, FunctionType([Type.I32, Type.I64, Type.I32, Type.I32], [Type.I32])), "fd_read": Function( store, lambda *args: 1, FunctionType([Type.I32, Type.I32, Type.I32, Type.I32], [Type.I32])), }) # Let's compile the module to be able to execute it! module = Module(store, open(quiet_path, 'rb').read()) # Now the module is compiled, we can instantiate it. return Instance(module, import_object)
def test_exports_iterable(): module = Module( Store(), """ (module (func (export "func") (param i32 i64)) (global (export "glob") i32 (i32.const 7)) (table (export "tab") 0 funcref) (memory (export "mem") 1)) """) instance = Instance(module) exports_iterator = iter(instance.exports) assert isinstance(exports_iterator, ExportsIterator) (export_name, export) = next(exports_iterator) assert export_name == "func" assert isinstance(export, Function) (export_name, export) = next(exports_iterator) assert export_name == "glob" assert isinstance(export, Global) (export_name, export) = next(exports_iterator) assert export_name == "tab" assert isinstance(export, Table) (export_name, export) = next(exports_iterator) assert export_name == "mem" assert isinstance(export, Memory) with pytest.raises(StopIteration): next(exports_iterator) # Works in a loop. for (name, export) in instance.exports: assert True # Works in a loop with `iter` called while it's not necessary. for (name, export) in iter(instance.exports): assert True assert [name for (name, _) in instance.exports ] == ["func", "glob", "tab", "mem"]
def test_import_function_defaultdict(): def sum(x: int, y: int) -> int: return x + y store = Store() module = Module( store, """ (module (import "math" "sum" (func $sum (param i32 i32) (result i32))) (func (export "add_one") (param i32) (result i32) local.get 0 i32.const 1 call $sum)) """) import_object = defaultdict(dict) import_object["math"]["sum"] = Function(store, sum) instance = Instance(module, import_object) assert instance.exports.add_one(1) == 2
def test_import_function(): def sum(x: int, y: int) -> int: return x + y store = Store() module = Module( store, """ (module (import "math" "sum" (func $sum (param i32 i32) (result i32))) (func (export "add_one") (param i32) (result i32) local.get 0 i32.const 1 call $sum)) """) import_object = ImportObject() import_object.register("math", {"sum": Function(store, sum)}) instance = Instance(module, import_object) assert instance.exports.add_one(1) == 2
def test_cross_compilation_roundtrip(): triple = target.Triple('x86_64-linux-musl') cpu_features = target.CpuFeatures() cpu_features.add('sse2') target_ = target.Target(triple, cpu_features) engine_ = engine.Native(Compiler, target_) store = Store(engine_) module = Module( store, """ (module (type $sum_t (func (param i32 i32) (result i32))) (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) local.get $x local.get $y i32.add) (export "sum" (func $sum_f))) """) assert isinstance(module, Module)
def test_early_exit(): store = Store() module = Module( store, """ (module (type $run_t (func (param i32 i32) (result i32))) (type $early_exit_t (func (param) (result))) (import "env" "early_exit" (func $early_exit (type $early_exit_t))) (func $run (type $run_t) (param $x i32) (param $y i32) (result i32) (call $early_exit) (i32.add local.get $x local.get $y)) (export "run" (func $run))) """ ) def early_exit(): raise Exception('oops') import_object = ImportObject() import_object.register( "env", { "early_exit": Function(store, early_exit), } ) instance = Instance(module, import_object) try: instance.exports.run(1, 2) except Exception as err: assert 'oops' in str(err) else: assert False
def main(): # Create a store store = Store(engine.JIT(Compiler)) # Convert Wat file contents into Wasm binary code wat_file_name = str(sys.argv[1]) with open(wat_file_name) as wat_file: wat_source_code = wat_file.read() wasm_bytes = wat2wasm(wat_source_code) # Compile the Wasm module module = Module(store, wasm_bytes) # Obtain functions to be imported from the Wasm module import_object = make_import_object(store) # Instantiate the module instance = Instance(module, import_object) # Run start function and return to OS its exit code sys.exit(instance.exports.main())
def test_imports(): imports = Module( Store(), """ (module (import "ns" "function" (func)) (import "ns" "global" (global f32)) (import "ns" "table" (table 1 2 anyfunc)) (import "ns" "memory" (memory 3 4))) """).imports assert isinstance(imports[0], ImportType) assert imports[0].module == "ns" assert imports[0].name == "function" assert isinstance(imports[0].type, FunctionType) assert imports[0].type.params == [] assert imports[0].type.results == [] assert imports[1].module == "ns" assert imports[1].name == "global" assert isinstance(imports[1].type, GlobalType) assert imports[1].type.type == Type.F32 assert imports[1].type.mutable == False assert imports[2].module == "ns" assert imports[2].name == "table" assert isinstance(imports[2].type, TableType) assert imports[2].type.type == Type.FUNC_REF assert imports[2].type.minimum == 1 assert imports[2].type.maximum == 2 assert imports[3].module == "ns" assert imports[3].name == "memory" assert isinstance(imports[3].type, MemoryType) assert imports[3].type.minimum == 3 assert imports[3].type.maximum == 4 assert imports[3].type.shared == False
def test_import_global(): store = Store() module = Module( store, """ (module (import "env" "global" (global $global (mut i32))) (func (export "read_g") (result i32) global.get $global) (func (export "write_g") (param i32) local.get 0 global.set $global)) """) global_ = Global(store, Value.i32(7), mutable=True) import_object = defaultdict(dict) import_object["env"]["global"] = global_ instance = Instance(module, import_object) assert instance.exports.read_g() == 7 global_.value = 153 assert instance.exports.read_g() == 153 instance.exports.write_g(11) assert global_.value == 11
def test_name_some(): assert Module(Store(), '(module $moduleName)').name == 'moduleName'
def test_compile_wat(): assert isinstance(Module(Store(), '(module)'), Module)
def test_failed_to_compile(): with pytest.raises(RuntimeError) as context_manager: Module(Store(), INVALID_TEST_BYTES)
def test_compile_bytes(): assert isinstance(Module(Store(), TEST_BYTES), Module)
def test_instantiate(): assert Module(TEST_BYTES).instantiate().exports.sum(1, 2) == 3
import os __dir__ = os.path.dirname(os.path.realpath(__file__)) wasm_bytes = open(__dir__ + '/imported_function.wasm', 'rb').read() def sum(x: int, y: int) -> int: return x + y instance = Instance( wasm_bytes, { "env": { "sum": sum } } ) print(instance.exports.sum_plus_one(1, 2)) module = Module(wasm_bytes) import_object = module.generate_import_object() import_object.extend({ "env": { "sum": sum } }) instance = module.instantiate(import_object) print(instance.exports.sum_plus_one(3, 4))
def test_name_none(): assert Module(Store(), '(module)').name == None
def test_wasi_env_memory(): store = Store() wasi_env = wasi.StateBuilder("foo").finalize() import_object = wasi_env.generate_import_object(store, wasi.Version.LATEST) instance = Instance(Module(store, TEST_BYTES), import_object)
def test_name_set(): module = Module(Store(), '(module)') module.name = 'hello' assert module.name == 'hello'
""") # Define the engine that will drive everything. # # In this case, the engine is `wasmer.engine.Dylib` which means that # a native object is going to be generated. So when we are going to # serialize the compiled Wasm module, we are going to store it in a # file with the `.so` extension for example (or `.dylib`, or `.dll` # depending of the platform). engine = engine.Dylib(Compiler) # Create a store, that holds the engine. store = Store(engine) # Let's compile the Wasm module. module = Module(store, wasm_bytes) # Here we go. Let's serialize the compiled Wasm module in a file. serialized_module = module.serialize() serialized_module_file = tempfile.TemporaryFile() serialized_module_file.write(serialized_module) # We seek to the initial position, so when we read it starts from the beginning serialized_module_file.seek(0, 0) # Second step, deserialize the compiled Wasm module, and execute it, # for example with Wasmer without a compiler. from wasmer import engine, Store, Instance, Module
def test_wasi_get_version(): assert wasi.get_version(Module(Store(), TEST_BYTES), strict=True) == wasi.Version.SNAPSHOT1
def test_validate(): assert Module.validate(Store(), TEST_BYTES)
def initiate_instance(): wasm_bytes = open(wasm_file_location, 'rb').read() store = Store() module = Module(store, wasm_bytes) instance = Instance(module) return instance
def test_custom_section(): module = Module(Store(), open(here + '/custom_sections.wasm', 'rb').read()) assert module.custom_sections('easter_egg') == [b'Wasmer'] assert module.custom_sections('hello') == [b'World!'] assert module.custom_sections('foo') == []
def instance(): return Instance(Module(Store(), TEST_BYTES))
def test_serialize(): assert type(Module(Store(), "(module)").serialize()) == bytes
# Define the engine that will drive everything. # # In this case, the engine is `wasmer.engine.JIT` which roughly # means that the executable code will live in memory. engine = engine.JIT(Compiler) # Create a store, that holds the engine. store = Store(engine) # Here we go. # # Let's compile the Wasm module. It is at this step that the Wasm text # is transformed into Wasm bytes (if necessary), and then compiled to # executable code by the compiler, which is then stored in memory by # the engine. module = Module(store, wasm_bytes) # Congrats, the Wasm module is compiled! Now let's execute it for the # sake of having a complete example. # # Let's instantiate the Wasm module. instance = Instance(module) # The Wasm module exports a function called `sum`. sum = instance.exports.sum results = sum(1, 2) print(results) assert results == 3
def test_validate_invalid(): assert not Module.validate(Store(), INVALID_TEST_BYTES)