Some checks failed
rules-freshness / rules (push) Failing after 13s
A literal above 2^31 is not an Int on wasm32, so those cases stay on 64-bit targets; WASI has no threads, so the nesting parse runs on the caller's stack there; the report files are written without the atomic rename WASI does not offer.
92 lines
4.2 KiB
Swift
92 lines
4.2 KiB
Swift
@testable import PureYAML
|
|
import Testing
|
|
|
|
@Suite("Numeric Coding Ladder")
|
|
struct NumericCodingLadderTests {
|
|
@Test("Decodes every integer width from an int value")
|
|
func test_decodesFullIntegerWidthLadder() throws {
|
|
#expect(try PureYAML.decode(Int8.self, from: .int(100)) == 100)
|
|
#expect(try PureYAML.decode(Int16.self, from: .int(30000)) == 30000)
|
|
#expect(try PureYAML.decode(Int32.self, from: .int(2_000_000_000)) == 2_000_000_000)
|
|
#if !arch(wasm32)
|
|
// `Model.Value.int` holds an `Int`; on a 32-bit platform no `Int` is above 2^31 - 1, so these cannot be written there.
|
|
#expect(try PureYAML.decode(Int64.self, from: .int(9_000_000_000)) == 9_000_000_000)
|
|
#expect(try PureYAML.decode(UInt32.self, from: .int(4_000_000_000)) == 4_000_000_000)
|
|
#endif
|
|
#expect(try PureYAML.decode(Int64.self, from: .int(2_000_000_000)) == 2_000_000_000)
|
|
#expect(try PureYAML.decode(UInt.self, from: .int(42)) == 42)
|
|
#expect(try PureYAML.decode(UInt8.self, from: .int(200)) == 200)
|
|
#expect(try PureYAML.decode(UInt16.self, from: .int(60000)) == 60000)
|
|
#expect(try PureYAML.decode(UInt32.self, from: .int(2_000_000_000)) == 2_000_000_000)
|
|
#expect(try PureYAML.decode(UInt64.self, from: .int(42)) == 42)
|
|
}
|
|
|
|
@Test("Reports the exact type when an int value is out of range per width")
|
|
func test_outOfRangeDecodeReportsExactTypePerWidth() {
|
|
expectDecodeOutOfRange(Int8.self, "Int8", .int(1000))
|
|
expectDecodeOutOfRange(Int16.self, "Int16", .int(40000))
|
|
#if !arch(wasm32)
|
|
// Not writable as an `Int` on a 32-bit platform, where every `Int` fits an `Int32`.
|
|
expectDecodeOutOfRange(Int32.self, "Int32", .int(5_000_000_000))
|
|
expectDecodeOutOfRange(UInt32.self, "UInt32", .int(5_000_000_000))
|
|
#endif
|
|
expectDecodeOutOfRange(UInt8.self, "UInt8", .int(300))
|
|
expectDecodeOutOfRange(UInt16.self, "UInt16", .int(70000))
|
|
expectDecodeOutOfRange(UInt32.self, "UInt32", .int(-1))
|
|
// Negative into an unsigned width is also out of range.
|
|
expectDecodeOutOfRange(UInt8.self, "UInt8", .int(-1))
|
|
expectDecodeOutOfRange(UInt.self, "UInt", .int(-1))
|
|
expectDecodeOutOfRange(UInt64.self, "UInt64", .int(-1))
|
|
}
|
|
|
|
@Test("Round-trips Float through the double representation")
|
|
func test_floatEncodeDecodeRoundTrip() throws {
|
|
#expect(try PureYAML.encode(Float(1.5)) == .double(1.5))
|
|
#expect(try PureYAML.decode(Float.self, from: .double(1.5)) == 1.5)
|
|
#expect(try PureYAML.decode(Float.self, from: .int(2)) == 2.0)
|
|
}
|
|
|
|
@Test("Double decoding rejects non-numeric kinds")
|
|
func test_doubleDecodeRejectsNonNumericKinds() {
|
|
expectDecodingError(.typeMismatch(expected: "Double", actual: "bool", path: .root)) {
|
|
try PureYAML.decode(Double.self, from: .bool(true))
|
|
}
|
|
expectDecodingError(.typeMismatch(expected: "Double", actual: "string", path: .root)) {
|
|
try PureYAML.decode(Double.self, from: .string("x"))
|
|
}
|
|
expectDecodingError(.typeMismatch(expected: "Double", actual: "null", path: .root)) {
|
|
try PureYAML.decode(Double.self, from: .null)
|
|
}
|
|
}
|
|
}
|
|
|
|
private func expectDecodeOutOfRange(
|
|
_ type: (some Decodable).Type,
|
|
_ typeName: String,
|
|
_ value: PureYAML.Model.Value,
|
|
sourceLocation: SourceLocation = #_sourceLocation,
|
|
) {
|
|
expectDecodingError(
|
|
.integerOutOfRange(type: typeName, path: .root),
|
|
sourceLocation: sourceLocation,
|
|
) {
|
|
try PureYAML.decode(type, from: value)
|
|
}
|
|
}
|
|
|
|
private func expectDecodingError(
|
|
_ expected: PureYAML.Decoding.Error,
|
|
sourceLocation: SourceLocation = #_sourceLocation,
|
|
operation: () throws -> some Any,
|
|
) {
|
|
do {
|
|
_ = try operation()
|
|
Issue.record("expected decoding error \(expected)", sourceLocation: sourceLocation)
|
|
} catch let error as PureYAML.Decoding.Error {
|
|
#expect(error == expected, sourceLocation: sourceLocation)
|
|
#expect(error.description == expected.description, sourceLocation: sourceLocation)
|
|
} catch {
|
|
Issue.record("unexpected error \(error)", sourceLocation: sourceLocation)
|
|
}
|
|
}
|