@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) #expect(try PureYAML.decode(Int64.self, from: .int(9_000_000_000)) == 9_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(4_000_000_000)) == 4_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)) expectDecodeOutOfRange(Int32.self, "Int32", .int(5_000_000_000)) expectDecodeOutOfRange(UInt8.self, "UInt8", .int(300)) expectDecodeOutOfRange(UInt16.self, "UInt16", .int(70000)) expectDecodeOutOfRange(UInt32.self, "UInt32", .int(5_000_000_000)) // 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) } }