168 lines
5.5 KiB
Swift
168 lines
5.5 KiB
Swift
@testable import PureYAML
|
|
import Testing
|
|
|
|
@Suite("Typed Coding")
|
|
struct CodingTests {
|
|
@Test("Decodes scalar values with exact results")
|
|
func test_decodesScalarValuesWithExactResults() throws {
|
|
#expect(try PureYAML.decode(String.self, from: .string("hello")) == "hello")
|
|
#expect(try PureYAML.decode(Bool.self, from: .bool(true)))
|
|
#expect(try PureYAML.decode(Int.self, from: .int(42)) == 42)
|
|
#expect(try PureYAML.decode(Double.self, from: .double(1.25)) == 1.25)
|
|
#expect(try PureYAML.decode(Double.self, from: .int(2)) == 2.0)
|
|
|
|
let optional = try PureYAML.decode(String?.self, from: .null)
|
|
#expect(optional == nil)
|
|
}
|
|
|
|
@Test("Parses YAML before decoding scalar values")
|
|
func test_parsesYAMLBeforeDecodingScalarValues() throws {
|
|
#expect(try PureYAML.decode(String.self, from: "hello") == "hello")
|
|
#expect(try PureYAML.decode(Bool.self, from: "true"))
|
|
#expect(try PureYAML.decode(Int.self, from: "7") == 7)
|
|
#expect(try PureYAML.decode(Double.self, from: "1.5") == 1.5)
|
|
}
|
|
|
|
@Test("Encoding scalar values produces exact value trees and YAML")
|
|
func test_encodingScalarValuesProducesExactValueTreesAndYAML() throws {
|
|
#expect(try PureYAML.encode("hello") == .string("hello"))
|
|
#expect(try PureYAML.encode(true) == .bool(true))
|
|
#expect(try PureYAML.encode(42) == .int(42))
|
|
#expect(try PureYAML.encode(1.25) == .double(1.25))
|
|
|
|
let nilString: String? = nil
|
|
#expect(try PureYAML.encode(nilString) == .null)
|
|
#expect(try PureYAML.encodeToYAML("hello") == "\"hello\"\n")
|
|
#expect(try !((PureYAML.encodeToYAML("hello")).contains("null")))
|
|
}
|
|
|
|
@Test("Decoding failures report exact validation-style errors", arguments: [
|
|
CodingErrorCase(
|
|
name: "string from int",
|
|
value: .int(1),
|
|
kind: .string,
|
|
expected: .typeMismatch(expected: "String", actual: "int", path: .root),
|
|
),
|
|
CodingErrorCase(
|
|
name: "int from double",
|
|
value: .double(1.5),
|
|
kind: .int,
|
|
expected: .typeMismatch(expected: "Int", actual: "double", path: .root),
|
|
),
|
|
CodingErrorCase(
|
|
name: "bool from null",
|
|
value: .null,
|
|
kind: .bool,
|
|
expected: .typeMismatch(expected: "Bool", actual: "null", path: .root),
|
|
),
|
|
CodingErrorCase(
|
|
name: "int8 from out-of-range int",
|
|
value: .int(1000),
|
|
kind: .int8,
|
|
expected: .integerOutOfRange(type: "Int8", path: .root),
|
|
),
|
|
])
|
|
func test_decodingFailuresReportExactValidationStyleErrors(
|
|
testCase: CodingErrorCase,
|
|
) {
|
|
testCase.expectFailure()
|
|
}
|
|
|
|
@Test("Out of range integer encoding reports exact errors")
|
|
func test_outOfRangeIntegerEncodingReportsExactErrors() {
|
|
expectEncodingError(
|
|
.integerOutOfRange(type: "UInt64", path: .root),
|
|
) {
|
|
_ = try PureYAML.encode(UInt64.max)
|
|
}
|
|
}
|
|
|
|
@Test("Coding error descriptions are exact")
|
|
func test_codingErrorDescriptionsAreExact() {
|
|
#expect(PureYAML.Decoding.Error.typeMismatch(
|
|
expected: "String",
|
|
actual: "int",
|
|
path: .root,
|
|
).description == "Expected String at $, found int")
|
|
|
|
#expect(PureYAML.Decoding.Error.integerOutOfRange(
|
|
type: "Int8",
|
|
path: .root,
|
|
).description == "Int8 value is outside PureYAML integer range at $")
|
|
|
|
#expect(PureYAML.Encoding.Error.integerOutOfRange(
|
|
type: "UInt64",
|
|
path: .root,
|
|
).description == "UInt64 value is outside PureYAML integer range at $")
|
|
}
|
|
}
|
|
|
|
struct CodingErrorCase: CustomStringConvertible {
|
|
enum Kind {
|
|
case string
|
|
case int
|
|
case int8
|
|
case bool
|
|
}
|
|
|
|
var name: String
|
|
var value: PureYAML.Model.Value
|
|
var kind: Kind
|
|
var expected: PureYAML.Decoding.Error
|
|
|
|
var description: String {
|
|
name
|
|
}
|
|
|
|
func expectFailure() {
|
|
do {
|
|
switch kind {
|
|
case .string:
|
|
_ = try PureYAML.decode(String.self, from: value)
|
|
case .int:
|
|
_ = try PureYAML.decode(Int.self, from: value)
|
|
case .int8:
|
|
_ = try PureYAML.decode(Int8.self, from: value)
|
|
case .bool:
|
|
_ = try PureYAML.decode(Bool.self, from: value)
|
|
}
|
|
recordIssue("expected decoding error")
|
|
} catch let error as PureYAML.Decoding.Error {
|
|
#expect(error == expected)
|
|
#expect(error.description == expected.description)
|
|
} catch {
|
|
recordIssue("unexpected error \(error)")
|
|
}
|
|
}
|
|
}
|
|
|
|
private func expectDecodingError(
|
|
_ expected: PureYAML.Decoding.Error,
|
|
operation: () throws -> some Any,
|
|
) {
|
|
do {
|
|
_ = try operation()
|
|
recordIssue("expected decoding error")
|
|
} catch let error as PureYAML.Decoding.Error {
|
|
#expect(error == expected)
|
|
#expect(error.description == expected.description)
|
|
} catch {
|
|
recordIssue("unexpected error \(error)")
|
|
}
|
|
}
|
|
|
|
private func expectEncodingError(
|
|
_ expected: PureYAML.Encoding.Error,
|
|
operation: () throws -> some Any,
|
|
) {
|
|
do {
|
|
_ = try operation()
|
|
recordIssue("expected encoding error")
|
|
} catch let error as PureYAML.Encoding.Error {
|
|
#expect(error == expected)
|
|
#expect(error.description == expected.description)
|
|
} catch {
|
|
recordIssue("unexpected error \(error)")
|
|
}
|
|
}
|