The scanner now errors with "found character that cannot start any token" when a tab leads a token in block context, matching libyaml's final guard in fetch_next_token (a plain scalar may not begin with a blank). Adds a differential harness (env-gated) that dumps the ported pipeline's yeast events for the whole suite. Verified against the libyaml reference dumper across all 308 vendored valid cases: the port is byte-for-byte identical to libyaml on 307, and the single difference (L24T/01) is the port matching the canonical test.event where libyaml drops a trailing line break. 333 tests.
67 lines
2.6 KiB
Swift
67 lines
2.6 KiB
Swift
import Foundation
|
|
@testable import PureYAML
|
|
import Testing
|
|
|
|
/// Differential measurement of the ported libyaml scanner+parser against the full
|
|
/// vendored YAML test suite, using the same yeast serializer as the canonical
|
|
/// gate. Gated by an environment flag so it only runs when measuring; it prints a
|
|
/// score and the failing ids split into throws vs wrong-stream.
|
|
@Suite("LibYAML Port Conformance")
|
|
struct LibYAMLPortConformanceTests {
|
|
@Test("measure the ported pipeline against the suite")
|
|
func test_measure() throws {
|
|
guard ProcessInfo.processInfo.environment["PUREYAML_PORT_MEASURE"] == "1" else { return }
|
|
var pass = 0
|
|
var throwing: [String] = []
|
|
var wrong: [String] = []
|
|
let cases = CanonicalEventCorpus.validCases()
|
|
for testCase in cases {
|
|
guard let yaml = testCase.input, let expected = testCase.expectedEvents else { continue }
|
|
do {
|
|
var parser = try PureYAML.Parsing.LibYAML.Parser(yaml)
|
|
let actual = try parser.parse().map(CanonicalEventCorpus.serialize).joined(separator: "\n")
|
|
if actual == expected.trimmedTrailing {
|
|
pass += 1
|
|
} else {
|
|
wrong.append(testCase.id)
|
|
}
|
|
} catch {
|
|
throwing.append(testCase.id)
|
|
}
|
|
}
|
|
print("PORT-SCORE pass=\(pass) wrong=\(wrong.count) throws=\(throwing.count) total=\(cases.count)")
|
|
print("PORT-WRONG \(wrong.sorted().joined(separator: " "))")
|
|
print("PORT-THROWS \(throwing.sorted().joined(separator: " "))")
|
|
}
|
|
|
|
@Test("dump port yeast for ids in PUREYAML_PORT_DUMP_IDS")
|
|
func test_dump() throws {
|
|
guard let ids = ProcessInfo.processInfo.environment["PUREYAML_PORT_DUMP_IDS"] else { return }
|
|
let cases = ids == "ALL"
|
|
? CanonicalEventCorpus.validCases().map(\.id)
|
|
: ids.split(separator: ",").map(String.init)
|
|
for id in cases {
|
|
let testCase = CanonicalEventCorpus.Case(id: id)
|
|
guard let yaml = testCase.input else { continue }
|
|
print("@@@ID@@@ \(id)")
|
|
do {
|
|
var parser = try PureYAML.Parsing.LibYAML.Parser(yaml)
|
|
try print(parser.parse().map(CanonicalEventCorpus.serialize).joined(separator: "\n"))
|
|
} catch {
|
|
print("@@@ERROR@@@ \(error)")
|
|
}
|
|
print("@@@END@@@")
|
|
}
|
|
}
|
|
}
|
|
|
|
private extension String {
|
|
var trimmedTrailing: String {
|
|
var copy = self
|
|
while copy.hasSuffix("\n") {
|
|
copy.removeLast()
|
|
}
|
|
return copy
|
|
}
|
|
}
|