diff --git a/Sources/XMLCoder/Box/KeyedBox.swift b/Sources/XMLCoder/Box/KeyedBox.swift index cb9225cb..652c740a 100644 --- a/Sources/XMLCoder/Box/KeyedBox.swift +++ b/Sources/XMLCoder/Box/KeyedBox.swift @@ -72,6 +72,12 @@ extension KeyedStorage: ExpressibleByDictionaryLiteral { } } +extension KeyedStorage: CustomStringConvertible { + var description: String { + return "\(buffer)" + } +} + class KeyedBox { typealias Key = String typealias Attribute = SimpleBox @@ -116,3 +122,9 @@ extension KeyedBox: Box { return nil } } + +extension KeyedBox: CustomStringConvertible { + var description: String { + return "{attributes: \(attributes), elements: \(elements)}" + } +} diff --git a/Sources/XMLCoder/Box/UnkeyedBox.swift b/Sources/XMLCoder/Box/UnkeyedBox.swift index a5755b3a..4ac49a58 100644 --- a/Sources/XMLCoder/Box/UnkeyedBox.swift +++ b/Sources/XMLCoder/Box/UnkeyedBox.swift @@ -76,6 +76,6 @@ extension UnkeyedBox: Sequence { extension UnkeyedBox: CustomStringConvertible { var description: String { - return unboxed.description + return "\(unboxed)" } } diff --git a/Tests/XMLCoderTests/BenchmarkTests.swift b/Tests/XMLCoderTests/BenchmarkTests.swift new file mode 100644 index 00000000..cb421bb3 --- /dev/null +++ b/Tests/XMLCoderTests/BenchmarkTests.swift @@ -0,0 +1,225 @@ +import XCTest +@testable import XMLCoder + +class BenchmarkTests: XCTestCase { + struct Container: Codable { + let unkeyed: [T] + let keyed: [String: T] + } + + func container(with value: T) -> Container { + // unkeyed.count + keyed.count = self.count: + let count = self.count / 2 + + let unkeyed = [T](repeating: value, count: count) + let keyed = Dictionary(uniqueKeysWithValues: unkeyed.enumerated().map { index, value in + ("key_\(index)", value) + }) + + return Container(unkeyed: unkeyed, keyed: keyed) + } + + func encodedContainer(of _: T.Type, with value: T) throws -> Data { + let container = self.container(with: value) + + let encoder = XMLEncoder() + encoder.outputFormatting = .prettyPrinted + + return try encoder.encode(container, withRootKey: "container") + } + + func testEncoding(with value: T, _ closure: (() -> Void) -> Void) throws { + try testEncoding(of: T.self, with: value, closure) + } + + func testEncoding(of type: T.Type, with value: T, _ closure: (() -> Void) -> Void) throws { + let container: Container = self.container(with: value) + + let encoder = XMLEncoder() + + closure { + _ = try! encoder.encode(container, withRootKey: "container") + } + } + + func testDecoding(with value: T, _ closure: (() -> Void) -> Void) throws { + try testDecoding(of: T.self, with: value, closure) + } + + func testDecoding(of type: T.Type, with value: T, _ closure: (() -> Void) -> Void) throws { + let data: Data = try encodedContainer(of: T.self, with: value) + let string = String(data: data, encoding: .utf8) + print(string!) + + let decoder = XMLDecoder() + + closure { + _ = try! decoder.decode(Container.self, from: data) + } + } + + let count: Int = 10 + + let null: Bool? = nil + let bool: Bool = true + let int: Int = -42 + let uint: UInt = 42 + let float: Float = 42.0 + let decimal: Decimal = 42.0 + let date: Date = Date() + let data: Data = Data(base64Encoded: "bG9yZW0gaXBzdW0=")! + let url: URL = URL(string: "http://example.com")! + let array: [Int] = [1, 2, 3, 4, 5] + let dictionary: [String: Int] = ["key_1": 1, "key_2": 2, "key_3": 3, "key_4": 4, "key_5": 5] + + func testEncodeNulls() throws { + try testEncoding(with: null) { closure in + self.measure { closure() } + } + } + + func testDecodeNulls() throws { + try testDecoding(with: null) { closure in + self.measure { closure() } + } + } + + func testEncodeBools() throws { + try testEncoding(with: bool) { closure in + self.measure { closure() } + } + } + + func testDecodeBools() throws { + try testDecoding(with: bool) { closure in + self.measure { closure() } + } + } + + func testEncodeInts() throws { + try testEncoding(with: int) { closure in + self.measure { closure() } + } + } + + func testDecodeInts() throws { + try testDecoding(with: int) { closure in + self.measure { closure() } + } + } + + func testEncodeUInts() throws { + try testEncoding(with: uint) { closure in + self.measure { closure() } + } + } + + func testDecodeUInts() throws { + try testDecoding(with: uint) { closure in + self.measure { closure() } + } + } + + func testEncodeFloats() throws { + try testEncoding(with: float) { closure in + self.measure { closure() } + } + } + + func testDecodeFloats() throws { + try testDecoding(with: float) { closure in + self.measure { closure() } + } + } + + func testEncodeDecimals() throws { + try testEncoding(with: decimal) { closure in + self.measure { closure() } + } + } + + func testDecodeDecimals() throws { + try testDecoding(with: decimal) { closure in + self.measure { closure() } + } + } + + func testEncodeDates() throws { + try testEncoding(with: date) { closure in + self.measure { closure() } + } + } + + func testDecodeDates() throws { + try testDecoding(with: date) { closure in + self.measure { closure() } + } + } + + func testEncodeDatas() throws { + try testEncoding(with: data) { closure in + self.measure { closure() } + } + } + + func testDecodeDatas() throws { + try testDecoding(with: data) { closure in + self.measure { closure() } + } + } + + func testEncodeURLs() throws { + try testEncoding(with: url) { closure in + self.measure { closure() } + } + } + + func testDecodeURLs() throws { + try testDecoding(with: url) { closure in + self.measure { closure() } + } + } + + func testEncodeArrays() throws { + try testEncoding(with: array) { closure in + self.measure { closure() } + } + } + + func testDecodeArrays() throws { + try testDecoding(with: array) { closure in + self.measure { closure() } + } + } + + func testEncodeDictionaries() throws { + try testEncoding(with: dictionary) { closure in + self.measure { closure() } + } + } + + func testDecodeDictionaries() throws { + try testDecoding(with: dictionary) { closure in + self.measure { closure() } + } + } + + static var allTests = [ + ("testEncodeNulls", testEncodeNulls), + ("testDecodeNulls", testDecodeNulls), + ("testEncodeBools", testEncodeBools), + ("testDecodeBools", testDecodeBools), + ("testEncodeInts", testEncodeInts), + ("testDecodeInts", testDecodeInts), + ("testEncodeUInts", testEncodeUInts), + ("testDecodeUInts", testDecodeUInts), + ("testEncodeFloats", testEncodeFloats), + ("testDecodeFloats", testDecodeFloats), + ("testEncodeDecimals", testEncodeDecimals), + ("testDecodeDecimals", testDecodeDecimals), + ("testEncodeArrays", testEncodeArrays), + ("testDecodeArrays", testDecodeArrays), + ("testEncodeDictionaries", testEncodeDictionaries), + ("testDecodeDictionaries", testDecodeDictionaries), + ] +} diff --git a/XMLCoder.xcodeproj/project.pbxproj b/XMLCoder.xcodeproj/project.pbxproj index c76b16d6..7ddbe2d4 100644 --- a/XMLCoder.xcodeproj/project.pbxproj +++ b/XMLCoder.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ BF63EF0821CD7AF8001D38C5 /* URLBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF63EF0721CD7AF8001D38C5 /* URLBoxTests.swift */; }; BF63EF0A21CD7C1A001D38C5 /* URLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF63EF0921CD7C1A001D38C5 /* URLTests.swift */; }; BF63EF0C21CD7F28001D38C5 /* EmptyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF63EF0B21CD7F28001D38C5 /* EmptyTests.swift */; }; + BF63EF1E21CEC99B001D38C5 /* BenchmarkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF63EF1D21CEC99A001D38C5 /* BenchmarkTests.swift */; }; BF9457A821CBB498005ACFDE /* NullBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF94579E21CBB497005ACFDE /* NullBox.swift */; }; BF9457A921CBB498005ACFDE /* KeyedBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF94579F21CBB497005ACFDE /* KeyedBox.swift */; }; BF9457AA21CBB498005ACFDE /* UnkeyedBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9457A021CBB497005ACFDE /* UnkeyedBox.swift */; }; @@ -115,6 +116,7 @@ BF63EF0721CD7AF8001D38C5 /* URLBoxTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLBoxTests.swift; sourceTree = ""; }; BF63EF0921CD7C1A001D38C5 /* URLTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLTests.swift; sourceTree = ""; }; BF63EF0B21CD7F28001D38C5 /* EmptyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyTests.swift; sourceTree = ""; }; + BF63EF1D21CEC99A001D38C5 /* BenchmarkTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BenchmarkTests.swift; sourceTree = ""; }; BF94579E21CBB497005ACFDE /* NullBox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NullBox.swift; sourceTree = ""; }; BF94579F21CBB497005ACFDE /* KeyedBox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyedBox.swift; sourceTree = ""; }; BF9457A021CBB497005ACFDE /* UnkeyedBox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnkeyedBox.swift; sourceTree = ""; }; @@ -319,6 +321,7 @@ OBJ_36 /* PlantTest.swift */, OBJ_37 /* RJITest.swift */, OBJ_38 /* RelationshipsTest.swift */, + BF63EF1D21CEC99A001D38C5 /* BenchmarkTests.swift */, D1FC040421C7EF8200065B43 /* RJISample.swift */, ); name = XMLCoderTests; @@ -522,6 +525,7 @@ OBJ_82 /* CDCatalog.swift in Sources */, BF63EF0021CCDED2001D38C5 /* XMLStackParserTests.swift in Sources */, BF9457CC21CBB516005ACFDE /* NullBoxTests.swift in Sources */, + BF63EF1E21CEC99B001D38C5 /* BenchmarkTests.swift in Sources */, BF9457CF21CBB516005ACFDE /* IntBoxTests.swift in Sources */, BF9457E021CBB68A005ACFDE /* DataBoxTests.swift in Sources */, BF9457F521CBB6BC005ACFDE /* DecimalTests.swift in Sources */,