Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Increase test coverage #56

Merged
merged 11 commits into from Jan 4, 2019
115 changes: 115 additions & 0 deletions 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 = """
<s>
<a>
<x>\(str)</x>
</a>
<b>
<super>
<x>\(str)</x>
</super>
<y>\(double)</y>
</b>
<c>
<super>
<super>
<x>\(str)</x>
</super>
<y>\(double)</y>
</super>
<z>\(int)</z>
</c>
</s>
""".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),
]
}
79 changes: 64 additions & 15 deletions Tests/XMLCoderTests/Minimal/IntTests.swift
Expand Up @@ -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<T>: 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<T: Decodable>(_ type: T.Type) throws {
let decoder = XMLDecoder()

let xmlString = "<container />"
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<T: Codable & IntegerContainer>(_ type: T.Type) throws {
let decoder = XMLDecoder()
let encoder = XMLEncoder()

Expand All @@ -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<T: Codable & IntegerContainer>(_ type: T.Type) throws {
let decoder = XMLDecoder()
let encoder = XMLEncoder()

Expand All @@ -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<Int>.self)
try testMissing(Container<Int8>.self)
try testMissing(Container<Int16>.self)
try testMissing(Container<Int32>.self)
try testMissing(Container<Int64>.self)
try testMissing(Container<UInt>.self)
try testMissing(Container<UInt8>.self)
try testMissing(Container<UInt16>.self)
try testMissing(Container<UInt32>.self)
try testMissing(Container<UInt64>.self)
}

func testIntegerTypeAttribute() throws {
try testAttribute(Container<Int>.self)
try testAttribute(Container<Int8>.self)
try testAttribute(Container<Int16>.self)
try testAttribute(Container<Int32>.self)
try testAttribute(Container<Int64>.self)
try testAttribute(Container<UInt>.self)
try testAttribute(Container<UInt8>.self)
try testAttribute(Container<UInt16>.self)
try testAttribute(Container<UInt32>.self)
try testAttribute(Container<UInt64>.self)
}

func testIntegerTypeElement() throws {
try testElement(Container<Int>.self)
try testElement(Container<Int8>.self)
try testElement(Container<Int16>.self)
try testElement(Container<Int32>.self)
try testElement(Container<Int64>.self)
try testElement(Container<UInt>.self)
try testElement(Container<UInt8>.self)
try testElement(Container<UInt16>.self)
try testElement(Container<UInt32>.self)
try testElement(Container<UInt64>.self)
}

static var allTests = [
("testAttribute", testAttribute),
("testElement", testElement),
("testIntegerTypeMissing", testIntegerTypeMissing),
("testIntegerTypeAttribute", testIntegerTypeAttribute),
("testIntegerTypeElement", testIntegerTypeElement),
]
}
79 changes: 79 additions & 0 deletions Tests/XMLCoderTests/Minimal/KeyedTests.swift
Expand Up @@ -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()

Expand Down Expand Up @@ -72,10 +92,69 @@ class KeyedTests: XCTestCase {
)
}

func testConvertFromSnakeCase() throws {
let decoder = XMLDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase

let xmlString =
"""
<cont_ainer test_attribute="test_container">
<val_ue>
<fo_o>12</fo_o>
</val_ue>
</cont_ainer>
"""
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 =
"""
<cont_aine test_attribut="test_container">
<val_u>
<fo_oo>12</fo_oo>
</val_u>
</cont_aine>
"""
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 =
"""
<container testAttribute="test_container">
<test_valUe>
<foo>12</foo>
</test_valUe>
</container>
"""
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),
]
}
4 changes: 4 additions & 0 deletions XMLCoder.xcodeproj/project.pbxproj
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -115,6 +116,7 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
A61DCCD621DF8DB300C0A19D /* ClassTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClassTests.swift; sourceTree = "<group>"; };
BF63EEFF21CCDED2001D38C5 /* XMLStackParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XMLStackParserTests.swift; sourceTree = "<group>"; };
BF63EF0521CD7A74001D38C5 /* URLBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLBox.swift; sourceTree = "<group>"; };
BF63EF0721CD7AF8001D38C5 /* URLBoxTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLBoxTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -335,6 +337,7 @@
OBJ_37 /* RJITest.swift */,
OBJ_38 /* RelationshipsTest.swift */,
D1FC040421C7EF8200065B43 /* RJISample.swift */,
A61DCCD621DF8DB300C0A19D /* ClassTests.swift */,
);
name = XMLCoderTests;
path = Tests/XMLCoderTests;
Expand Down Expand Up @@ -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 */,
Expand Down