diff --git a/Tests/XMLCoderTests/ClassTests.swift b/Tests/XMLCoderTests/ClassTests.swift
new file mode 100644
index 00000000..b6ed39fa
--- /dev/null
+++ b/Tests/XMLCoderTests/ClassTests.swift
@@ -0,0 +1,115 @@
+//
+// ClassTest.swift
+// XMLCoder
+//
+// Created by Matvii Hodovaniuk on 1/4/19.
+//
+
+import Foundation
+import XCTest
+@testable import XMLCoder
+
+class A: Codable {
+ let x: String
+}
+
+class B: A {
+ let y: Double
+
+ private enum CodingKeys: CodingKey {
+ case y
+ }
+
+ required init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: CodingKeys.self)
+ y = try container.decode(Double.self, forKey: .y)
+ let superDecoder = try container.superDecoder()
+ try super.init(from: superDecoder)
+ }
+
+ override func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ try container.encode(y, forKey: .y)
+ let superEncoder = container.superEncoder()
+ try super.encode(to: superEncoder)
+ }
+}
+
+class C: B {
+ let z: Int
+
+ private enum CodingKeys: CodingKey {
+ case z
+ }
+
+ required init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: CodingKeys.self)
+ z = try container.decode(Int.self, forKey: .z)
+ let superDecoder = try container.superDecoder()
+ try super.init(from: superDecoder)
+ }
+
+ override func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ try container.encode(z, forKey: .z)
+ let superEncoder = container.superEncoder()
+ try super.encode(to: superEncoder)
+ }
+}
+
+struct S: Codable {
+ let a: A
+ let b: B
+ let c: C
+}
+
+let str = "test_string"
+let int = 42
+let double = 4.2
+
+let xmlData = """
+
+
+ \(str)
+
+
+
+ \(str)
+
+ \(double)
+
+
+
+
+ \(str)
+
+ \(double)
+
+ \(int)
+
+
+""".data(using: .utf8)!
+
+class ClassTests: XCTestCase {
+ func testEmpty() throws {
+ let decoder = XMLDecoder()
+ let encoder = XMLEncoder()
+ encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
+
+ let decoded = try decoder.decode(S.self, from: xmlData)
+ XCTAssertEqual(decoded.a.x, str)
+ XCTAssertEqual(decoded.b.x, str)
+ XCTAssertEqual(decoded.b.y, double)
+ XCTAssertEqual(decoded.c.z, int)
+ XCTAssertEqual(decoded.c.x, str)
+ XCTAssertEqual(decoded.c.y, double)
+
+ let encoded = try encoder.encode(decoded, withRootKey: "s")
+
+ XCTAssertEqual(encoded, xmlData)
+ }
+
+ static var allTests = [
+ ("testEmpty", testEmpty),
+ ]
+}
diff --git a/Tests/XMLCoderTests/Minimal/IntTests.swift b/Tests/XMLCoderTests/Minimal/IntTests.swift
index ff778736..ae99c471 100644
--- a/Tests/XMLCoderTests/Minimal/IntTests.swift
+++ b/Tests/XMLCoderTests/Minimal/IntTests.swift
@@ -8,29 +8,38 @@
import XCTest
@testable import XMLCoder
+protocol IntegerContainer {
+ associatedtype Integer: BinaryInteger
+
+ var value: Integer { get }
+}
+
+extension IntegerContainer {
+ var intValue: Int {
+ return Int(value)
+ }
+}
+
class IntTests: XCTestCase {
typealias Value = Int
- struct Container: Codable, Equatable {
- let value: Value
+ struct Container: Codable, Equatable, IntegerContainer where T: Codable & Equatable & BinaryInteger {
+ let value: T
}
let values: [(Value, String)] = [
- (-42, "-42"),
(0, "0"),
(42, "42"),
]
- func testMissing() {
+ func testMissing(_ type: T.Type) throws {
let decoder = XMLDecoder()
-
let xmlString = ""
let xmlData = xmlString.data(using: .utf8)!
-
- XCTAssertThrowsError(try decoder.decode(Container.self, from: xmlData))
+ XCTAssertThrowsError(try decoder.decode(type, from: xmlData))
}
- func testAttribute() throws {
+ func testAttribute(_ type: T.Type) throws {
let decoder = XMLDecoder()
let encoder = XMLEncoder()
@@ -45,15 +54,15 @@ class IntTests: XCTestCase {
"""
let xmlData = xmlString.data(using: .utf8)!
- let decoded = try decoder.decode(Container.self, from: xmlData)
- XCTAssertEqual(decoded.value, value)
+ let decoded = try decoder.decode(type, from: xmlData)
+ XCTAssertEqual(decoded.intValue, value)
let encoded = try encoder.encode(decoded, withRootKey: "container")
XCTAssertEqual(String(data: encoded, encoding: .utf8)!, xmlString)
}
}
- func testElement() throws {
+ func testElement(_ type: T.Type) throws {
let decoder = XMLDecoder()
let encoder = XMLEncoder()
@@ -68,16 +77,56 @@ class IntTests: XCTestCase {
"""
let xmlData = xmlString.data(using: .utf8)!
- let decoded = try decoder.decode(Container.self, from: xmlData)
- XCTAssertEqual(decoded.value, value)
+ let decoded = try decoder.decode(type, from: xmlData)
+ XCTAssertEqual(decoded.intValue, value)
let encoded = try encoder.encode(decoded, withRootKey: "container")
XCTAssertEqual(String(data: encoded, encoding: .utf8)!, xmlString)
}
}
+ func testIntegerTypeMissing() throws {
+ try testMissing(Container.self)
+ try testMissing(Container.self)
+ try testMissing(Container.self)
+ try testMissing(Container.self)
+ try testMissing(Container.self)
+ try testMissing(Container.self)
+ try testMissing(Container.self)
+ try testMissing(Container.self)
+ try testMissing(Container.self)
+ try testMissing(Container.self)
+ }
+
+ func testIntegerTypeAttribute() throws {
+ try testAttribute(Container.self)
+ try testAttribute(Container.self)
+ try testAttribute(Container.self)
+ try testAttribute(Container.self)
+ try testAttribute(Container.self)
+ try testAttribute(Container.self)
+ try testAttribute(Container.self)
+ try testAttribute(Container.self)
+ try testAttribute(Container.self)
+ try testAttribute(Container.self)
+ }
+
+ func testIntegerTypeElement() throws {
+ try testElement(Container.self)
+ try testElement(Container.self)
+ try testElement(Container.self)
+ try testElement(Container.self)
+ try testElement(Container.self)
+ try testElement(Container.self)
+ try testElement(Container.self)
+ try testElement(Container.self)
+ try testElement(Container.self)
+ try testElement(Container.self)
+ }
+
static var allTests = [
- ("testAttribute", testAttribute),
- ("testElement", testElement),
+ ("testIntegerTypeMissing", testIntegerTypeMissing),
+ ("testIntegerTypeAttribute", testIntegerTypeAttribute),
+ ("testIntegerTypeElement", testIntegerTypeElement),
]
}
diff --git a/Tests/XMLCoderTests/Minimal/KeyedTests.swift b/Tests/XMLCoderTests/Minimal/KeyedTests.swift
index 9052f30d..654832ad 100644
--- a/Tests/XMLCoderTests/Minimal/KeyedTests.swift
+++ b/Tests/XMLCoderTests/Minimal/KeyedTests.swift
@@ -13,6 +13,26 @@ class KeyedTests: XCTestCase {
let value: [String: Int]
}
+ struct ContainerCamelCase: Codable, Equatable {
+ let valUe: [String: Int]
+ let testAttribute: String
+ }
+
+ struct AnyKey: CodingKey {
+ var stringValue: String
+ var intValue: Int?
+
+ init?(stringValue: String) {
+ self.stringValue = stringValue
+ intValue = nil
+ }
+
+ init?(intValue: Int) {
+ stringValue = String(intValue)
+ self.intValue = intValue
+ }
+ }
+
func testEmpty() throws {
let decoder = XMLDecoder()
@@ -72,10 +92,69 @@ class KeyedTests: XCTestCase {
)
}
+ func testConvertFromSnakeCase() throws {
+ let decoder = XMLDecoder()
+ decoder.keyDecodingStrategy = .convertFromSnakeCase
+
+ let xmlString =
+ """
+
+
+ 12
+
+
+ """
+ let xmlData = xmlString.data(using: .utf8)!
+
+ let decoded = try decoder.decode(ContainerCamelCase.self, from: xmlData)
+
+ XCTAssertEqual(decoded.valUe, ["foO": 12])
+ }
+
+ func testErrorDescriptionConvertFromSnakeCase() throws {
+ let decoder = XMLDecoder()
+ decoder.keyDecodingStrategy = .convertFromSnakeCase
+
+ let xmlString =
+ """
+
+
+ 12
+
+
+ """
+ let xmlData = xmlString.data(using: .utf8)!
+
+ XCTAssertThrowsError(try decoder.decode(ContainerCamelCase.self, from: xmlData))
+ }
+
+ func testCustomDecoderConvert() throws {
+ let decoder = XMLDecoder()
+ decoder.keyDecodingStrategy = .custom { keys in
+ let lastComponent = keys.last!.stringValue.split(separator: "_").last!
+ return AnyKey(stringValue: String(lastComponent))!
+ }
+
+ let xmlString =
+ """
+
+
+ 12
+
+
+ """
+ let xmlData = xmlString.data(using: .utf8)!
+
+ let decoded = try decoder.decode(ContainerCamelCase.self, from: xmlData)
+
+ XCTAssertEqual(decoded.valUe, ["foo": 12])
+ }
+
static var allTests = [
("testEmpty", testEmpty),
("testSingleElement", testSingleElement),
("testMultiElement", testMultiElement),
("testAttribute", testAttribute),
+ ("testConvertFromSnakeCase", testConvertFromSnakeCase),
]
}
diff --git a/XMLCoder.xcodeproj/project.pbxproj b/XMLCoder.xcodeproj/project.pbxproj
index 5c8bb7f2..fcd21e54 100644
--- a/XMLCoder.xcodeproj/project.pbxproj
+++ b/XMLCoder.xcodeproj/project.pbxproj
@@ -21,6 +21,7 @@
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
+ A61DCCD821DF9CA200C0A19D /* ClassTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A61DCCD621DF8DB300C0A19D /* ClassTests.swift */; };
BF63EF0021CCDED2001D38C5 /* XMLStackParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF63EEFF21CCDED2001D38C5 /* XMLStackParserTests.swift */; };
BF63EF0621CD7A74001D38C5 /* URLBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF63EF0521CD7A74001D38C5 /* URLBox.swift */; };
BF63EF0821CD7AF8001D38C5 /* URLBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF63EF0721CD7AF8001D38C5 /* URLBoxTests.swift */; };
@@ -115,6 +116,7 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
+ A61DCCD621DF8DB300C0A19D /* ClassTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClassTests.swift; sourceTree = ""; };
BF63EEFF21CCDED2001D38C5 /* XMLStackParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XMLStackParserTests.swift; sourceTree = ""; };
BF63EF0521CD7A74001D38C5 /* URLBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLBox.swift; sourceTree = ""; };
BF63EF0721CD7AF8001D38C5 /* URLBoxTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLBoxTests.swift; sourceTree = ""; };
@@ -335,6 +337,7 @@
OBJ_37 /* RJITest.swift */,
OBJ_38 /* RelationshipsTest.swift */,
D1FC040421C7EF8200065B43 /* RJISample.swift */,
+ A61DCCD621DF8DB300C0A19D /* ClassTests.swift */,
);
name = XMLCoderTests;
path = Tests/XMLCoderTests;
@@ -555,6 +558,7 @@
OBJ_88 /* PlantTest.swift in Sources */,
BF63EF0821CD7AF8001D38C5 /* URLBoxTests.swift in Sources */,
BF9457DD21CBB62C005ACFDE /* DateBoxTests.swift in Sources */,
+ A61DCCD821DF9CA200C0A19D /* ClassTests.swift in Sources */,
BF9457CD21CBB516005ACFDE /* FloatBoxTests.swift in Sources */,
BF9457F621CBB6BC005ACFDE /* KeyedTests.swift in Sources */,
BF9457C821CBB516005ACFDE /* BoolBoxTests.swift in Sources */,