Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions Tests/PenguinCSVTests/CSVInterpreterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,37 @@ final class CSVInterpreterTests: XCTestCase {
]
}

#if swift(>=5.3)
fileprivate func assertCompatible(
_ cell: String, with type: CSVType, file: StaticString = #filePath, line: UInt = #line
) {
XCTAssert(
type.isCompatibleWith(cell), "\(type) should be compatible with \(cell)", file: file, line: line
)
}

fileprivate func assertNotCompatible(
_ cell: String, with type: CSVType, file: StaticString = #filePath, line: UInt = #line
) {
XCTAssertFalse(
type.isCompatibleWith(cell), "\(type) should not be compatible with \(cell)", file: file,
line: line)
}

fileprivate func assertParsedHeuristics(
_ text: String, _ heuristics: [SeparatorHeuristics], file: StaticString = #file,
line: UInt = #line
) {
var text2 = text // Make a mutable copy, as withUTF8 might modify the string.
text2.withUTF8 { body in
let lines = body.split(separator: UInt8(ascii: "\n"))
precondition(lines.count > 2)
let fullLines = lines[0..<lines.count - 1] // Drop last linee as it could be incomplete.
let separatorHeuristics = computeSeparatorHeuristics(fullLines)
assertEqual(heuristics, separatorHeuristics, file: file, line: line)
}
}
#else
fileprivate func assertCompatible(
_ cell: String, with type: CSVType, file: StaticString = #file, line: UInt = #line
) {
Expand Down Expand Up @@ -319,6 +350,7 @@ fileprivate func assertParsedHeuristics(
assertEqual(heuristics, separatorHeuristics, file: file, line: line)
}
}
#endif

fileprivate func assertEqual(
_ expected: [SeparatorHeuristics], _ actual: [SeparatorHeuristics], file: StaticString, line: UInt
Expand All @@ -337,6 +369,72 @@ fileprivate func assertEqual(
}
}

#if swift(>=5.3)
fileprivate func checkColumnGuesser(
expected: [CSVType], best: CSVType, cells: String..., file: StaticString = #filePath,
line: UInt = #line
) {
var guesser = CSVColumnGuesser()
for cell in cells {
guesser.updateCompatibilities(cell: cell)
}
XCTAssertEqual(Set(expected), guesser.possibleTypes, "Cells: \(cells)", file: file, line: line)
XCTAssertEqual(best, guesser.bestGuess, "Cells: \(cells)", file: file, line: line)
}

fileprivate func checkColumnSniffing(
withoutFirstRow: [CSVType],
withFirstRow: [CSVType],
_ contents: String,
separator: Unicode.Scalar = ",",
file: StaticString = #filePath,
line: UInt = #line
) {
precondition(
withoutFirstRow.count == withFirstRow.count,
"Mismatched counts: \(withoutFirstRow.count) and \(withFirstRow.count)")
var c = contents // Must make a mutable copy first. :-(
c.withUTF8 { contents in
let lines = contents.split(separator: UInt8(ascii: "\n"))
let allLines = lines[0..<lines.count] // Don't drop the last one in tests!
let result = try! computeColumnTypes(
allLines, separator: separator, columnCount: withoutFirstRow.count)
XCTAssertEqual(
withoutFirstRow, result.withoutFirstRow.map { $0.bestGuess }, "Without first row problems!",
file: file, line: line)
XCTAssertEqual(
withFirstRow, result.withFirstRow.map { $0.bestGuess }, "With first row problems!",
file: file, line: line)
}
}

fileprivate func checkComputeColumnNames(
expected: [String], separator: Unicode.Scalar = ",", _ contents: String,
file: StaticString = #filePath, line: UInt = #line
) {
var c = contents
c.withUTF8 { contents in
let lines = contents.split(separator: UInt8(ascii: "\n"))
let result = try! computeColumnNames(
headerRow: lines[0], separator: separator, columnCount: expected.count)
XCTAssertEqual(expected, result, file: file, line: line)
}
}

fileprivate func assertColumnNames(
_ expected: [String], _ result: CSVGuess, file: StaticString = #filePath, line: UInt = #line
) {
let actual = result.columns.map { $0.name }
XCTAssertEqual(expected, actual, file: file, line: line)
}

fileprivate func assertColumnTypes(
_ expected: [CSVType], _ result: CSVGuess, file: StaticString = #filePath, line: UInt = #line
) {
let actual = result.columns.map { $0.type }
XCTAssertEqual(expected, actual, file: file, line: line)
}
#else
fileprivate func checkColumnGuesser(
expected: [CSVType], best: CSVType, cells: String..., file: StaticString = #file,
line: UInt = #line
Expand Down Expand Up @@ -401,6 +499,7 @@ fileprivate func assertColumnTypes(
let actual = result.columns.map { $0.type }
XCTAssertEqual(expected, actual, file: file, line: line)
}
#endif

extension SeparatorHeuristics {
fileprivate init(
Expand Down
10 changes: 10 additions & 0 deletions Tests/PenguinCSVTests/CSVReaderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -258,10 +258,20 @@ fileprivate enum TestError: Error {
case missingMetadata
}

#if swift(>=5.3)
fileprivate func assertMetadataNotNil(
_ reader: CSVReader, file: StaticString = #filePath, line: UInt = #line
) throws -> CSVGuess {
XCTAssertNotNil(reader.metadata, file: file, line: line)
guard let metadata = reader.metadata else { throw TestError.missingMetadata }
return metadata
}
#else
fileprivate func assertMetadataNotNil(
_ reader: CSVReader, file: StaticString = #file, line: UInt = #line
) throws -> CSVGuess {
XCTAssertNotNil(reader.metadata, file: file, line: line)
guard let metadata = reader.metadata else { throw TestError.missingMetadata }
return metadata
}
#endif
12 changes: 12 additions & 0 deletions Tests/PenguinParallelTests/NonBlockingThreadPoolTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,17 @@ final class NonBlockingThreadPoolTests: XCTestCase {
}

// Overload for 2-tuple
#if swift(>=5.3)
fileprivate func XCTAssertEqual(
_ lhs: (Int, Int), _ rhs: (Int, Int), _ msg: String = "", file: StaticString = #filePath,
line: UInt = #line
) {
XCTAssertEqual(
lhs.0, rhs.0, "items 0 did not agree: \(lhs) vs \(rhs) \(msg)", file: file, line: line)
XCTAssertEqual(
lhs.1, rhs.1, "items 1 did not agree: \(lhs) vs \(rhs) \(msg)", file: file, line: line)
}
#else
fileprivate func XCTAssertEqual(
_ lhs: (Int, Int), _ rhs: (Int, Int), _ msg: String = "", file: StaticString = #file,
line: UInt = #line
Expand All @@ -119,6 +130,7 @@ fileprivate func XCTAssertEqual(
XCTAssertEqual(
lhs.1, rhs.1, "items 1 did not agree: \(lhs) vs \(rhs) \(msg)", file: file, line: line)
}
#endif

/// A platform to count threads and to ensure deallocation.
///
Expand Down
15 changes: 15 additions & 0 deletions Tests/PenguinTablesTests/CSVParsibleTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@ final class CSVParsibleTests: XCTestCase {
]
}

#if swift(>=5.3)
fileprivate func assertParse<T: PCSVParsible & Equatable>(
_ bytes: String,
as val: T,
file: StaticString = #filePath,
line: UInt = #line
) {
var s = bytes
s.withUTF8 { s in
let parsed = T(CSVCell.raw(s))
XCTAssertEqual(parsed, val, file: file, line: line)
}
}
#else
fileprivate func assertParse<T: PCSVParsible & Equatable>(
_ bytes: String,
as val: T,
Expand All @@ -42,3 +56,4 @@ fileprivate func assertParse<T: PCSVParsible & Equatable>(
XCTAssertEqual(parsed, val, file: file, line: line)
}
}
#endif
32 changes: 32 additions & 0 deletions Tests/PenguinTablesTests/StringParsibleTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,37 @@ final class StringParsibleTests: XCTestCase {
]
}

#if swift(>=5.3)
fileprivate func assertParses<T: PStringParsible & Equatable>(
expected: T, source: String, file: StaticString = #filePath, line: UInt = #line
) {
let result = T(parsing: source)
XCTAssertEqual(expected, result, file: file, line: line)
}

fileprivate func assertParseFailure<T: PStringParsible>(
a type: T.Type,
from source: String,
reason: String? = nil,
file: StaticString = #filePath,
line: UInt = #line
) {
do {
let unexpected = try T(parseOrThrow: source)
XCTFail(
"\"\(source)\" parsed as \(type) unexpectedly as \(unexpected).", file: file, line: line)
} catch {
let msg = String(describing: error)
if let reason = reason {
XCTAssert(
msg.contains(reason),
"Error message \"\(msg)\" did not contain expected string \"\(reason)\".",
file: file,
line: line)
}
}
}
#else
fileprivate func assertParses<T: PStringParsible & Equatable>(
expected: T, source: String, file: StaticString = #file, line: UInt = #line
) {
Expand Down Expand Up @@ -96,3 +127,4 @@ fileprivate func assertParseFailure<T: PStringParsible>(
}
}
}
#endif
26 changes: 25 additions & 1 deletion Tests/PenguinTablesTests/TableTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,10 @@ final class TableTests: XCTestCase {
]
}

#if swift(>=5.3)
fileprivate func assertPColumnsEqual<T: ElementRequirements>(
_ lhs: PColumn?, _ rhs: PColumn?, dtype: T.Type, file: StaticString = #file, line: UInt = #line
_ lhs: PColumn?, _ rhs: PColumn?, dtype: T.Type,
file: StaticString = #filePath, line: UInt = #line
) {
if lhs == nil && rhs == nil { return }

Expand All @@ -296,3 +298,25 @@ fileprivate func assertPColumnsEqual<T: ElementRequirements>(
}
XCTAssertEqual(lhsT, rhsT, file: file, line: line)
}
#else
fileprivate func assertPColumnsEqual<T: ElementRequirements>(
_ lhs: PColumn?, _ rhs: PColumn?, dtype: T.Type,
file: StaticString = #file, line: UInt = #line
) {
if lhs == nil && rhs == nil { return }

guard let lhsT: PTypedColumn<T> = try? lhs?.asDType() else {
XCTFail(
"lhs could not be interpreted as dtype \(dtype): \(String(describing: lhs))",
file: file, line: line)
return
}
guard let rhsT: PTypedColumn<T> = try? rhs?.asDType() else {
XCTFail(
"rhs could not be interpreted as dtype \(dtype): \(String(describing: rhs))",
file: file, line: line)
return
}
XCTAssertEqual(lhsT, rhsT, file: file, line: line)
}
#endif