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 78 79 80 81 82 83 84 85
|
import XCTest
@testable import WasmKit
final class HostModuleTests: XCTestCase {
func testImportMemory() throws {
let runtime = Runtime()
let memoryType = MemoryType(min: 1, max: nil)
let memoryAddr = runtime.store.allocate(memoryType: memoryType)
try runtime.store.register(HostModule(memories: ["memory": memoryAddr]), as: "env")
let module = Module(
imports: [
Import(module: "env", name: "memory", descriptor: .memory(memoryType))
]
)
XCTAssertNoThrow(try runtime.instantiate(module: module))
// Ensure the allocated address is valid
_ = runtime.store.memory(at: memoryAddr)
}
func testReentrancy() throws {
let runtime = Runtime()
let voidSignature = FunctionType(parameters: [], results: [])
let module = Module(
types: [voidSignature],
functions: [
// [0] (import "env" "bar" func)
// [1] (import "env" "qux" func)
// [2] "foo"
GuestFunction(
type: 0, locals: [],
body: {
[
.call(functionIndex: 0),
.call(functionIndex: 0),
.call(functionIndex: 0),
]
}),
// [3] "bar"
GuestFunction(
type: 0, locals: [],
body: {
[
.control(.call(functionIndex: 1))
]
}),
],
imports: [
Import(module: "env", name: "bar", descriptor: .function(0)),
Import(module: "env", name: "qux", descriptor: .function(0)),
],
exports: [
Export(name: "foo", descriptor: .function(2)),
Export(name: "baz", descriptor: .function(3)),
]
)
var isExecutingFoo = false
var isQuxCalled = false
let hostModule = HostModule(
functions: [
"bar": HostFunction(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.invoke([], runtime: caller.runtime)
return []
},
"qux": HostFunction(type: voidSignature) { _, _ in
XCTAssertTrue(isExecutingFoo)
isQuxCalled = true
return []
},
]
)
try runtime.store.register(hostModule, as: "env")
let instance = try runtime.instantiate(module: module)
// Check foo(wasm) -> bar(host) -> baz(wasm) -> qux(host)
_ = try runtime.invoke(instance, function: "foo")
XCTAssertTrue(isQuxCalled)
}
}
|