Skip to content

Commit

Permalink
working through Codable tests
Browse files Browse the repository at this point in the history
  • Loading branch information
leogdion committed Apr 29, 2024
1 parent f9b3207 commit c1669ed
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 16 deletions.
6 changes: 4 additions & 2 deletions Sources/Options/MappedEnum.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ public struct MappedEnum<EnumType: MappedValueRepresentable>: Codable, Sendable
let label = try container.decode(EnumType.MappedType.self)
let rawValue = try EnumType.rawValue(basedOn: label)
guard let value = EnumType(rawValue: rawValue) else {
preconditionFailure("Invalid Raw Value.")
assertionFailure("Every mappedValue should always return a valid rawValue.")
throw DecodingError.invalidRawValue(rawValue)
}
self.value = value
}
Expand All @@ -42,7 +43,8 @@ public struct MappedEnum<EnumType: MappedValueRepresentable>: Codable, Sendable
let label = try container.decode(EnumType.MappedType.self)
let rawValue = try EnumType.rawValue(basedOn: label)
guard let value = EnumType(rawValue: rawValue) else {
preconditionFailure("Invalid Raw Value.")
assertionFailure("Every mappedValue should always return a valid rawValue.")
throw DecodingError.invalidRawValue(rawValue)
}
self.value = value
}
Expand Down
5 changes: 2 additions & 3 deletions Sources/Options/MappedValueRepresentable+Codable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,8 @@ extension SingleValueDecodingContainer {
let rawValue = try T.rawValue(basedOn: mappedValues)

guard let value = T(rawValue: rawValue) else {
throw DecodingError.dataCorrupted(
.init(codingPath: [], debugDescription: "Invalid Raw Value.")
)
assertionFailure("Every mappedValue should always return a valid rawValue.")
throw DecodingError.invalidRawValue(rawValue)
}

return value
Expand Down
88 changes: 77 additions & 11 deletions Tests/OptionsTests/MappedValueCollectionRepresentedTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,83 @@ internal final class MappedValueCollectionRepresentedTests: XCTestCase {
XCTAssertEqual(caughtError, .valueNotFound)
}

internal func testCodingOptions() {
XCTAssertEqual(MockDictionaryEnum.codingOptions, .default)
}

internal func testInvalidRaw() throws {
let rawValue = Int.random(in: 5 ... 1_000)

let rawValueJSON = "\(rawValue)"

let rawValueJSONData = rawValueJSON.data(using: .utf8)!

let decodingError: DecodingError
do {
let value = try Self.decoder.decode(MockCollectionEnum.self, from: rawValueJSONData)
XCTAssertNil(value)
return
} catch let error as DecodingError {
decodingError = error
}

XCTAssertNotNil(decodingError)
}

internal func testCodable() throws {
let encoder: JSONEncoder = .init()
let decoder: JSONDecoder = .init()
let enumValue = MockCollectionEnum.a
let stringValue = try String(data: encoder.encode(enumValue), encoding: .utf8)
let actualStringValue = try MockCollectionEnum.mappedValue(basedOn: enumValue.rawValue)
XCTAssertEqual(stringValue, "\"\(actualStringValue)\"")
XCTAssertEqual(stringValue, "\"a\"")
let expectedStringValue = "a"
let data = "\"\(expectedStringValue)\"".data(using: .utf8) ?? .init()
let actualValue = try decoder.decode(MockCollectionEnum.self, from: data)
XCTAssertEqual(actualValue, .a)
let argumentSets = MockCollectionEnum.allCases.flatMap {
[($0, true), ($0, false)]
}.flatMap {
[($0.0, $0.1, true), ($0.0, $0.1, false)]
}

for arguments in argumentSets {
try codableTest(value: arguments.0, allowMappedValue: arguments.1, encodeAsMappedValue: arguments.2)
}
}

static let encoder = JSONEncoder()
static let decoder = JSONDecoder()

private func codableTest(value: MockCollectionEnum, allowMappedValue: Bool, encodeAsMappedValue: Bool) throws {
let mappedValue = try value.mappedValue()
let rawValue = value.rawValue

let mappedValueJSON = "\"\(mappedValue)\""
let rawValueJSON = "\(rawValue)"

let mappedValueJSONData = mappedValueJSON.data(using: .utf8)!
let rawValueJSONData = rawValueJSON.data(using: .utf8)!

let oldOptions = MockCollectionEnum.codingOptions
MockCollectionEnum.codingOptions = .init([
allowMappedValue ? CodingOptions.allowMappedValueDecoding : nil,
encodeAsMappedValue ? CodingOptions.encodeAsMappedValue : nil
].compactMap { $0 })

defer {
MockCollectionEnum.codingOptions = oldOptions
}

let mappedDecodeResult = Result {
try Self.decoder.decode(MockCollectionEnum.self, from: mappedValueJSONData)
}

let actualRawValueDecoded = try Self.decoder.decode(MockCollectionEnum.self, from: rawValueJSONData)

let actualEncodedJSON = try Self.encoder.encode(value)

switch (allowMappedValue, mappedDecodeResult) {
case (true, let .success(actualMappedDecodedValue)):
XCTAssertEqual(actualMappedDecodedValue, value)
case (false, let .failure(error)):
XCTAssert(error is DecodingError)
default:
XCTFail("Unmatched situation \(allowMappedValue): \(mappedDecodeResult)")
}

XCTAssertEqual(actualRawValueDecoded, value)

XCTAssertEqual(actualEncodedJSON, encodeAsMappedValue ? mappedValueJSONData : rawValueJSONData)
}
}
2 changes: 2 additions & 0 deletions Tests/OptionsTests/Mocks/MockCollectionEnum.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import Options
case b
case c
case d

static var codingOptions: CodingOptions = .default
}
#else
// swiftlint:disable identifier_name
Expand Down

0 comments on commit c1669ed

Please sign in to comment.