147 lines
4.8 KiB
Swift
147 lines
4.8 KiB
Swift
import XCTest
|
|
import CSV
|
|
|
|
final class EncoderTests: XCTestCase {
|
|
func testAsyncEncode() throws {
|
|
var rows: [[UInt8]] = []
|
|
let encoder = CSVEncoder().async { row in rows.append(row) }
|
|
|
|
for person in people {
|
|
try encoder.encode(person)
|
|
}
|
|
|
|
let string = String(decoding: Array(rows.joined(separator: [10])), as: UTF8.self)
|
|
XCTAssertEqual(string, expected)
|
|
}
|
|
|
|
func testMeasureAsyncEncode() {
|
|
|
|
// 0.543
|
|
measure {
|
|
for _ in 0..<10_000 {
|
|
let encoder = CSVEncoder().async { _ in return }
|
|
do {
|
|
try people.forEach(encoder.encode)
|
|
} catch let error as EncodingError {
|
|
XCTFail(error.failureReason ?? "No failure reason")
|
|
error.errorDescription.map { print($0) }
|
|
error.recoverySuggestion.map { print($0) }
|
|
} catch let error {
|
|
XCTFail(error.localizedDescription)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func testSyncEncode() throws {
|
|
let encoder = CSVEncoder().sync
|
|
let encoded = try encoder.encode(people)
|
|
let string = String(decoding: encoded, as: UTF8.self)
|
|
|
|
XCTAssertEqual(string, expected)
|
|
}
|
|
|
|
func testMeasureSyncEncode() {
|
|
|
|
// 0.621
|
|
measure {
|
|
for _ in 0..<10_000 {
|
|
let encoder = CSVEncoder().sync
|
|
do {
|
|
_ = try encoder.encode(people)
|
|
} catch let error as EncodingError {
|
|
XCTFail(error.failureReason ?? "No failure reason")
|
|
error.errorDescription.map { print($0) }
|
|
error.recoverySuggestion.map { print($0) }
|
|
} catch let error {
|
|
XCTFail(error.localizedDescription)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func testEscapingDelimiters() throws {
|
|
let quotePerson = Person(firstName: "A", lastName: "J", age: 42, gender: .male, tagLine: #"All "with quotes""#)
|
|
let hashPerson = Person(firstName: "M", lastName: "A", age: 28, gender: .female, tagLine: "#iWin#")
|
|
|
|
let quoteResult = """
|
|
"first name","last_name","age","gender","tagLine"
|
|
"A","J","42","M","All ""with quotes""\"
|
|
"""
|
|
let hashResult = """
|
|
#first name#,#last_name#,#age#,#gender#,#tagLine#
|
|
#M#,#A#,#28#,#F#,###iWin###
|
|
"""
|
|
|
|
let quoteEncoder = CSVEncoder().sync
|
|
let hashEncoder = CSVEncoder(encodingOptions: .default, configuration: .init(cellSeparator: 44, cellDelimiter: 35)).sync
|
|
|
|
try XCTAssertEqual(quoteEncoder.encode([quotePerson]), Data(quoteResult.utf8))
|
|
try XCTAssertEqual(hashEncoder.encode([hashPerson]), Data(hashResult.utf8))
|
|
}
|
|
|
|
func testEncodingColumnValues() throws {
|
|
let data = [
|
|
["a": "hello", "b": "true", "c": "1"],
|
|
["a": "world", "b": "false", "c": "2"],
|
|
["a": "fizz", "b": "false", "c": "3"],
|
|
["a": "buzz", "b": "true", "c": "5"],
|
|
["a": "foo", "b": "false", "c": "8"],
|
|
["a": "bar", "b": "true", "c": "13"],
|
|
]
|
|
let expected = """
|
|
"a","b","c"
|
|
"hello","true","1"
|
|
"world","false","2"
|
|
"fizz","false","3"
|
|
"buzz","true","5"
|
|
"foo","false","8"
|
|
"bar","true",13"
|
|
"""
|
|
|
|
var csv = Data()
|
|
let encoder = CSVEncoder().async { row in
|
|
csv.append(contentsOf: row)
|
|
csv.append(10)
|
|
}
|
|
try data.forEach(encoder.encode(_:))
|
|
XCTAssertEqual(String(decoding: csv, as: UTF8.self), expected)
|
|
|
|
csv = try CSVEncoder().sync.encode(data)
|
|
XCTAssertEqual(String(decoding: csv, as: UTF8.self), expected)
|
|
}
|
|
}
|
|
|
|
fileprivate struct Person: Codable, Equatable {
|
|
let firstName: String
|
|
let lastName: String?
|
|
let age: Int
|
|
let gender: Gender
|
|
let tagLine: String?
|
|
|
|
enum Gender: String, Codable {
|
|
case female = "F"
|
|
case male = "M"
|
|
}
|
|
|
|
enum CodingKeys: String, CodingKey {
|
|
case firstName = "first name"
|
|
case lastName = "last_name"
|
|
case age
|
|
case gender
|
|
case tagLine
|
|
}
|
|
}
|
|
|
|
fileprivate let people = [
|
|
Person(firstName: "Caleb", lastName: "Kleveter", age: 18, gender: .male, tagLine: "😜"),
|
|
Person(firstName: "Benjamin", lastName: "Franklin", age: 269, gender: .male, tagLine: "A penny saved is a penny earned"),
|
|
Person(firstName: "Doc", lastName: "Holliday", age: 174, gender: .male, tagLine: "Bang"),
|
|
Person(firstName: "Grace", lastName: "Hopper", age: 119, gender: .female, tagLine: nil),
|
|
Person(
|
|
firstName: "Anne", lastName: "Shirley", age: 141, gender: .female,
|
|
tagLine: "God's in His heaven,\nall's right with the world"
|
|
),
|
|
Person(firstName: "TinTin", lastName: nil, age: 16, gender: .male, tagLine: "Great snakes!")
|
|
]
|