Skip to content

Commit 3e01dc3

Browse files
committed
GC: Run function-references & gc proposal tests.
Setup test suite in preparation for adding support for these proposals.
1 parent 05a091c commit 3e01dc3

File tree

2 files changed

+137
-37
lines changed

2 files changed

+137
-37
lines changed

Tests/WasmKitTests/Spectest/Spectest.swift

+49-37
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,41 @@ private func loadStringArrayFromEnvironment(_ key: String) -> [String] {
77
ProcessInfo.processInfo.environment[key]?.split(separator: ",").map(String.init) ?? []
88
}
99

10+
public struct SpectestResult {
11+
var passed = 0
12+
var skipped = 0
13+
var failed = 0
14+
var total: Int { passed + skipped + failed }
15+
var failedCases: Set<String> = []
16+
17+
mutating func append(_ testCase: TestCase, _ result: Result) {
18+
switch result {
19+
case .passed:
20+
passed += 1
21+
case .skipped:
22+
skipped += 1
23+
case .failed:
24+
failed += 1
25+
failedCases.insert(testCase.path)
26+
}
27+
}
28+
29+
func percentage(_ numerator: Int, _ denominator: Int) -> String {
30+
"\(Int(Double(numerator) / Double(denominator) * 100))%"
31+
}
32+
33+
func dump() {
34+
print(
35+
"\(passed)/\(total) (\(percentage(passed, total)) passing, \(percentage(skipped, total)) skipped, \(percentage(failed, total)) failed)"
36+
)
37+
guard !failedCases.isEmpty else { return }
38+
print("Failed cases:")
39+
for testCase in failedCases.sorted() {
40+
print(" \(testCase)")
41+
}
42+
}
43+
}
44+
1045
@available(macOS 11, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
1146
public func spectest(
1247
path: [String],
@@ -16,6 +51,18 @@ public func spectest(
1651
parallel: Bool = true,
1752
configuration: EngineConfiguration = .init()
1853
) async throws -> Bool {
54+
try await spectestResult(path: path, include: include, exclude: exclude, verbose: verbose, parallel: parallel, configuration: configuration).failed == 0
55+
}
56+
57+
@available(macOS 11, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
58+
public func spectestResult(
59+
path: [String],
60+
include: [String]? = nil,
61+
exclude: [String]? = nil,
62+
verbose: Bool = false,
63+
parallel: Bool = true,
64+
configuration: EngineConfiguration = .init()
65+
) async throws -> SpectestResult {
1966
let printVerbose = verbose
2067
@Sendable func log(_ message: String, verbose: Bool = false) {
2168
if !verbose || printVerbose {
@@ -28,10 +75,6 @@ public func spectest(
2875
fputs("\(path):\(line): " + message + "\n", stderr)
2976
}
3077
}
31-
func percentage(_ numerator: Int, _ denominator: Int) -> String {
32-
"\(Int(Double(numerator) / Double(denominator) * 100))%"
33-
}
34-
3578
let include = include ?? loadStringArrayFromEnvironment("WASMKIT_SPECTEST_INCLUDE")
3679
let exclude = exclude ?? loadStringArrayFromEnvironment("WASMKIT_SPECTEST_EXCLUDE")
3780

@@ -44,7 +87,7 @@ public func spectest(
4487

4588
guard !testCases.isEmpty else {
4689
log("No test found")
47-
return true
90+
return SpectestResult()
4891
}
4992

5093
// https://github.com/WebAssembly/spec/tree/8a352708cffeb71206ca49a0f743bdc57269fb1a/interpreter#spectest-host-module
@@ -103,37 +146,6 @@ public func spectest(
103146
return testCaseResults
104147
}
105148

106-
struct SpectestResult {
107-
var passed = 0
108-
var skipped = 0
109-
var failed = 0
110-
var total: Int { passed + skipped + failed }
111-
var failedCases: Set<String> = []
112-
113-
mutating func append(_ testCase: TestCase, _ result: Result) {
114-
switch result {
115-
case .passed:
116-
passed += 1
117-
case .skipped:
118-
skipped += 1
119-
case .failed:
120-
failed += 1
121-
failedCases.insert(testCase.path)
122-
}
123-
}
124-
125-
func dump() {
126-
print(
127-
"\(passed)/\(total) (\(percentage(passed, total)) passing, \(percentage(skipped, total)) skipped, \(percentage(failed, total)) failed)"
128-
)
129-
guard !failedCases.isEmpty else { return }
130-
print("Failed cases:")
131-
for testCase in failedCases.sorted() {
132-
print(" \(testCase)")
133-
}
134-
}
135-
}
136-
137149
let result: SpectestResult
138150

139151
if parallel {
@@ -168,5 +180,5 @@ public func spectest(
168180

169181
result.dump()
170182

171-
return result.failed == 0
183+
return result
172184
}

Tests/WasmKitTests/SpectestTests.swift

+88
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ final class SpectestTests: XCTestCase {
1616
]
1717
}
1818

19+
static var gcPath: [String] {
20+
[
21+
Self.testsuite.appendingPathComponent("proposals/function-references").path,
22+
Self.testsuite.appendingPathComponent("proposals/gc").path
23+
]
24+
}
25+
1926
/// Run all the tests in the spectest suite.
2027
func testRunAll() async throws {
2128
let defaultConfig = EngineConfiguration()
@@ -42,4 +49,85 @@ final class SpectestTests: XCTestCase {
4249
)
4350
XCTAssertTrue(ok)
4451
}
52+
53+
/// Run the function-references & garbage collection proposal tests
54+
/// As we add support, we can increase the passed count and delete entries from the failed array.
55+
func testFunctionReferencesAndGarbageCollectionProposals() async throws {
56+
let defaultConfig = EngineConfiguration()
57+
let result = try await spectestResult(
58+
path: Self.gcPath,
59+
include: [],
60+
exclude: [],
61+
parallel: true,
62+
configuration: defaultConfig
63+
)
64+
65+
let failed = result.failedCases.map {
66+
URL(filePath: $0).pathComponents.suffix(2).joined(separator: "/")
67+
}.sorted()
68+
69+
XCTAssertEqual(result.passed, 1975)
70+
XCTAssertEqual(failed, [
71+
"function-references/br_on_non_null.wast",
72+
"function-references/br_on_null.wast",
73+
"function-references/br_table.wast",
74+
"function-references/call_ref.wast",
75+
"function-references/elem.wast",
76+
"function-references/func.wast",
77+
"function-references/linking.wast",
78+
"function-references/local_init.wast",
79+
"function-references/ref.wast",
80+
"function-references/ref_as_non_null.wast",
81+
"function-references/ref_is_null.wast",
82+
"function-references/ref_null.wast",
83+
"function-references/return_call.wast",
84+
"function-references/return_call_indirect.wast",
85+
"function-references/return_call_ref.wast",
86+
"function-references/select.wast",
87+
"function-references/table-sub.wast",
88+
"function-references/table.wast",
89+
"function-references/type-equivalence.wast",
90+
"function-references/unreached-valid.wast",
91+
"gc/array.wast",
92+
"gc/array_copy.wast",
93+
"gc/array_fill.wast",
94+
"gc/array_init_data.wast",
95+
"gc/array_init_elem.wast",
96+
"gc/br_if.wast",
97+
"gc/br_on_cast.wast",
98+
"gc/br_on_cast_fail.wast",
99+
"gc/br_on_non_null.wast",
100+
"gc/br_on_null.wast",
101+
"gc/br_table.wast",
102+
"gc/call_ref.wast",
103+
"gc/data.wast",
104+
"gc/elem.wast",
105+
"gc/extern.wast",
106+
"gc/func.wast",
107+
"gc/global.wast",
108+
"gc/i31.wast",
109+
"gc/linking.wast",
110+
"gc/local_init.wast",
111+
"gc/local_tee.wast",
112+
"gc/ref.wast",
113+
"gc/ref_as_non_null.wast",
114+
"gc/ref_cast.wast",
115+
"gc/ref_eq.wast",
116+
"gc/ref_is_null.wast",
117+
"gc/ref_null.wast",
118+
"gc/ref_test.wast",
119+
"gc/return_call.wast",
120+
"gc/return_call_indirect.wast",
121+
"gc/return_call_ref.wast",
122+
"gc/select.wast",
123+
"gc/struct.wast",
124+
"gc/table-sub.wast",
125+
"gc/table.wast",
126+
"gc/type-canon.wast",
127+
"gc/type-equivalence.wast",
128+
"gc/type-rec.wast",
129+
"gc/type-subtyping.wast",
130+
"gc/unreached-valid.wast"
131+
])
132+
}
45133
}

0 commit comments

Comments
 (0)