File: EncoderTests.swift

package info (click to toggle)
swiftlang 6.2.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,856,264 kB
  • sloc: cpp: 9,995,718; ansic: 2,234,019; asm: 1,092,167; python: 313,940; objc: 82,726; f90: 80,126; lisp: 38,373; pascal: 25,580; sh: 20,378; ml: 5,058; perl: 4,751; makefile: 4,725; awk: 3,535; javascript: 3,018; xml: 918; fortran: 664; cs: 573; ruby: 396
file content (176 lines) | stat: -rw-r--r-- 6,943 bytes parent folder | download
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import Foundation
import WasmParser
import XCTest

@testable import WAT

class EncoderTests: XCTestCase {

    struct CompatibilityTestStats {
        var run: Int = 0
        var failed: Set<String> = []
    }

    func checkWabtCompatibility(
        wast: URL, json: URL, stats parentStats: inout CompatibilityTestStats
    ) throws {
        var stats = parentStats
        defer { parentStats = stats }
        func recordFail() {
            stats.failed.insert(wast.lastPathComponent)
        }
        func assertEqual<T: Equatable>(_ lhs: T, _ rhs: T, file: StaticString = #file, line: UInt = #line) {
            XCTAssertEqual(lhs, rhs, file: file, line: line)
            if lhs != rhs {
                recordFail()
            }
        }

        print("Checking\n  wast: \(wast.path)\n  json: \(json.path)")
        var parser = WastParser(try String(contentsOf: wast), features: Spectest.deriveFeatureSet(wast: wast))
        var watModules: [ModuleDirective] = []

        while let directive = try parser.nextDirective() {
            switch directive {
            case .module(let moduleDirective):
                watModules.append(moduleDirective)
            case .assertMalformed(let module, let message):
                let diagnostic = {
                    let (line, column) = module.location.computeLineAndColumn()
                    return "\(wast.path):\(line):\(column) should be malformed: \(message)"
                }
                switch module.source {
                case .text(var wat):
                    XCTAssertThrowsError(
                        try {
                            _ = try wat.encode()
                            recordFail()
                        }(), diagnostic())
                case .quote(let bytes):
                    XCTAssertThrowsError(
                        try {
                            _ = try wat2wasm(String(decoding: bytes, as: UTF8.self))
                            recordFail()
                        }(), diagnostic())
                case .binary: break
                }
            default: break
            }
        }
        guard FileManager.default.fileExists(atPath: json.path) else {
            print("Skipping binary comparison because the oracle file (\(json.path)) does not exist.")
            return
        }
        let moduleBinaryFiles = try Spectest.moduleFiles(json: json)
        assertEqual(watModules.count, moduleBinaryFiles.count)

        for (watModule, (moduleBinaryFile, expectedName)) in zip(watModules, moduleBinaryFiles) {
            func assertEqual<T: Equatable>(_ lhs: T, _ rhs: T, file: StaticString = #file, line: UInt = #line) {
                XCTAssertEqual(lhs, rhs, moduleBinaryFile.path, file: file, line: line)
                if lhs != rhs {
                    recordFail()
                }
            }
            stats.run += 1
            let moduleBytes: [UInt8]
            let expectedBytes = try Array(Data(contentsOf: moduleBinaryFile))
            do {
                assertEqual(watModule.id, expectedName)
                switch watModule.source {
                case .text(var watModule):
                    moduleBytes = try encode(module: &watModule, options: .default)
                case .binary(let bytes):
                    moduleBytes = bytes
                case .quote(let watText):
                    moduleBytes = try wat2wasm(String(decoding: watText, as: UTF8.self))
                }
            } catch {
                recordFail()
                XCTFail("Error while encoding \(moduleBinaryFile.lastPathComponent): \(error)")
                return
            }
            if moduleBytes != expectedBytes {
                recordFail()
            }
            assertEqual(moduleBytes.count, expectedBytes.count)
            if moduleBytes.count == expectedBytes.count {
                assertEqual(moduleBytes, expectedBytes)
            }
        }
    }

    func testSpectest() throws {
        #if os(iOS) || os(watchOS) || os(tvOS) || os(visionOS)
            throw XCTSkip("Spectest compatibility test requires Foundation.Process")
        #else
            guard let wast2json = TestSupport.lookupExecutable("wast2json") else {
                throw XCTSkip("wast2json not found in PATH")
            }

            var stats = CompatibilityTestStats()
            let excluded: [String] = []
            for wastFile in Spectest.wastFiles(include: [], exclude: excluded) {
                try TestSupport.withTemporaryDirectory { tempDir, shouldRetain in
                    let jsonFileName = wastFile.deletingPathExtension().lastPathComponent + ".json"
                    let json = URL(fileURLWithPath: tempDir).appendingPathComponent(jsonFileName)

                    let wast2jsonProcess = try Process.run(
                        wast2json,
                        arguments: [
                            wastFile.path,
                            "--enable-memory64",
                            "--enable-tail-call",
                            "-o", json.path,
                        ]
                    )
                    wast2jsonProcess.waitUntilExit()

                    do {
                        try checkWabtCompatibility(wast: wastFile, json: json, stats: &stats)
                    } catch {
                        stats.failed.insert(wastFile.lastPathComponent)
                        shouldRetain = true
                        XCTFail("Error while checking compatibility between \(wastFile) and \(json.path): \(error)")
                    }
                }
            }
            print("Spectest compatibility: \(stats.run - stats.failed.count) / \(stats.run)")
            if !stats.failed.isEmpty {
                print("Failed test cases: \(stats.failed.sorted())")
            }
        #endif
    }

    func testEncodeNameSection() throws {
        let bytes = try wat2wasm(
            """
            (module
                (func $foo)
                (func)
                (func $bar)
            )
            """,
            options: EncodeOptions(nameSection: true)
        )

        var parser = WasmParser.Parser(bytes: bytes)
        var customSections: [CustomSection] = []
        while let payload = try parser.parseNext() {
            guard case .customSection(let section) = payload else {
                continue
            }
            customSections.append(section)
        }
        let nameSection = customSections.first(where: { $0.name == "name" })
        let nameParser = NameSectionParser(
            stream: StaticByteStream(bytes: nameSection?.bytes ?? [])
        )
        let names = try nameParser.parseAll()
        XCTAssertEqual(names.count, 1)
        guard case .functions(let functionNames) = try XCTUnwrap(names.first) else {
            XCTFail()
            return
        }
        XCTAssertEqual(functionNames, [0: "foo", 2: "bar"])
    }
}