1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
import WAT
import XCTest
@testable import WasmKit
@testable import WasmParser
final class HostModuleTests: XCTestCase {
func testImportMemory() throws {
let engine = Engine()
let store = Store(engine: engine)
let memoryType = MemoryType(min: 1, max: nil)
let memory = try WasmKit.Memory(store: store, type: memoryType)
let imports: Imports = [
"env": ["memory": memory]
]
let module = try parseWasm(
bytes: wat2wasm(
"""
(module
(import "env" "memory" (memory 1))
)
"""))
XCTAssertNoThrow(try module.instantiate(store: store, imports: imports))
// Ensure the allocated address is valid
_ = memory.data
}
func testReentrancy() throws {
let engine = Engine()
let store = Store(engine: engine)
let voidSignature = WasmTypes.FunctionType(parameters: [], results: [])
let module = try parseWasm(
bytes: wat2wasm(
"""
(module
(import "env" "bar" (func $bar))
(import "env" "qux" (func $qux))
(func (export "foo")
(call $bar)
(call $bar)
(call $bar)
)
(func (export "baz")
(call $qux)
)
)
""")
)
var isExecutingFoo = false
var isQuxCalled = false
let imports: Imports = [
"env": [
"bar": Function(store: store, type: voidSignature) { caller, _ in
// Ensure "invoke" executes instructions under the current call
XCTAssertFalse(isExecutingFoo, "bar should not be called recursively")
isExecutingFoo = true
defer { isExecutingFoo = false }
let foo = try XCTUnwrap(caller.instance?.exportedFunction(name: "baz"))
_ = try foo()
return []
},
"qux": Function(store: store, type: voidSignature) { caller, _ in
XCTAssertTrue(isExecutingFoo)
isQuxCalled = true
return []
},
]
]
let instance = try module.instantiate(store: store, imports: imports)
// Check foo(wasm) -> bar(host) -> baz(wasm) -> qux(host)
let foo = try XCTUnwrap(instance.exports[function: "foo"])
try foo()
XCTAssertTrue(isQuxCalled)
}
}
|