Add CI/CD configuration and API documentation
This commit is contained in:
+420
@@ -0,0 +1,420 @@
|
||||
import XCTest
|
||||
import Foundation
|
||||
@testable import GRDB
|
||||
|
||||
private protocol StrategyProvider {
|
||||
static var strategy: DatabaseUUIDEncodingStrategy { get }
|
||||
}
|
||||
|
||||
private enum StrategyDeferredToUUID: StrategyProvider {
|
||||
static let strategy: DatabaseUUIDEncodingStrategy = .deferredToUUID
|
||||
}
|
||||
|
||||
private enum StrategyUppercaseString: StrategyProvider {
|
||||
static let strategy: DatabaseUUIDEncodingStrategy = .uppercaseString
|
||||
}
|
||||
|
||||
private enum StrategyLowercaseString: StrategyProvider {
|
||||
static let strategy: DatabaseUUIDEncodingStrategy = .lowercaseString
|
||||
}
|
||||
|
||||
private struct RecordWithUUID<Strategy: StrategyProvider>: EncodableRecord, Encodable {
|
||||
static var databaseUUIDEncodingStrategy: DatabaseUUIDEncodingStrategy { Strategy.strategy }
|
||||
var uuid: UUID
|
||||
}
|
||||
|
||||
@available(iOS 13, macOS 10.15, tvOS 13, watchOS 6, *)
|
||||
extension RecordWithUUID: Identifiable {
|
||||
var id: UUID { uuid }
|
||||
}
|
||||
|
||||
private struct RecordWithOptionalUUID<Strategy: StrategyProvider>: EncodableRecord, Encodable {
|
||||
static var databaseUUIDEncodingStrategy: DatabaseUUIDEncodingStrategy { Strategy.strategy }
|
||||
var uuid: UUID?
|
||||
}
|
||||
|
||||
@available(iOS 13, macOS 10.15, tvOS 13, watchOS 6, *)
|
||||
extension RecordWithOptionalUUID: Identifiable {
|
||||
var id: UUID? { uuid }
|
||||
}
|
||||
|
||||
class DatabaseUUIDEncodingStrategyTests: GRDBTestCase {
|
||||
private func test<T: EncodableRecord>(
|
||||
record: T,
|
||||
expectedStorage: DatabaseValue.Storage)
|
||||
throws
|
||||
{
|
||||
var container = PersistenceContainer()
|
||||
try record.encode(to: &container)
|
||||
if let dbValue = container["uuid"]?.databaseValue {
|
||||
XCTAssertEqual(dbValue.storage, expectedStorage)
|
||||
} else {
|
||||
XCTAssertEqual(.null, expectedStorage)
|
||||
}
|
||||
}
|
||||
|
||||
private func test<Strategy: StrategyProvider>(
|
||||
strategy: Strategy.Type,
|
||||
encodesUUID uuid: UUID,
|
||||
as value: any DatabaseValueConvertible)
|
||||
throws {
|
||||
try test(record: RecordWithUUID<Strategy>(uuid: uuid), expectedStorage: value.databaseValue.storage)
|
||||
try test(record: RecordWithOptionalUUID<Strategy>(uuid: uuid), expectedStorage: value.databaseValue.storage)
|
||||
}
|
||||
|
||||
private func testNullEncoding<Strategy: StrategyProvider>(strategy: Strategy.Type) throws {
|
||||
try test(record: RecordWithOptionalUUID<Strategy>(uuid: nil), expectedStorage: .null)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - deferredToUUID
|
||||
|
||||
extension DatabaseUUIDEncodingStrategyTests {
|
||||
func testDeferredToUUID() throws {
|
||||
try testNullEncoding(strategy: StrategyDeferredToUUID.self)
|
||||
|
||||
try test(
|
||||
strategy: StrategyDeferredToUUID.self,
|
||||
encodesUUID: UUID(uuidString: "61626364-6566-6768-696A-6B6C6D6E6F70")!,
|
||||
as: "abcdefghijklmnop".data(using: .utf8)!)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UppercaseString
|
||||
|
||||
extension DatabaseUUIDEncodingStrategyTests {
|
||||
func testUppercaseString() throws {
|
||||
try testNullEncoding(strategy: StrategyUppercaseString.self)
|
||||
|
||||
try test(
|
||||
strategy: StrategyUppercaseString.self,
|
||||
encodesUUID: UUID(uuidString: "61626364-6566-6768-696A-6B6C6D6E6F70")!,
|
||||
as: "61626364-6566-6768-696A-6B6C6D6E6F70")
|
||||
|
||||
try test(
|
||||
strategy: StrategyUppercaseString.self,
|
||||
encodesUUID: UUID(uuidString: "56e7d8d3-e9e4-48b6-968e-8d102833af00")!,
|
||||
as: "56E7D8D3-E9E4-48B6-968E-8D102833AF00")
|
||||
|
||||
let uuid = UUID()
|
||||
try test(
|
||||
strategy: StrategyUppercaseString.self,
|
||||
encodesUUID: uuid,
|
||||
as: uuid.uuidString.uppercased()) // Assert stable casing
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - LowercaseString
|
||||
|
||||
extension DatabaseUUIDEncodingStrategyTests {
|
||||
func testLowercaseString() throws {
|
||||
try testNullEncoding(strategy: StrategyLowercaseString.self)
|
||||
|
||||
try test(
|
||||
strategy: StrategyLowercaseString.self,
|
||||
encodesUUID: UUID(uuidString: "61626364-6566-6768-696A-6B6C6D6E6F70")!,
|
||||
as: "61626364-6566-6768-696a-6b6c6d6e6f70")
|
||||
|
||||
try test(
|
||||
strategy: StrategyLowercaseString.self,
|
||||
encodesUUID: UUID(uuidString: "56e7d8d3-e9e4-48b6-968e-8d102833af00")!,
|
||||
as: "56e7d8d3-e9e4-48b6-968e-8d102833af00")
|
||||
|
||||
let uuid = UUID()
|
||||
try test(
|
||||
strategy: StrategyLowercaseString.self,
|
||||
encodesUUID: uuid,
|
||||
as: uuid.uuidString.lowercased()) // Assert stable casing
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Filter
|
||||
|
||||
extension DatabaseUUIDEncodingStrategyTests {
|
||||
func testFilterKey() throws {
|
||||
try makeDatabaseQueue().write { db in
|
||||
try db.create(table: "t") { $0.primaryKey("id", .blob) }
|
||||
let uuids = [
|
||||
UUID(uuidString: "61626364-6566-6768-696A-6B6C6D6E6F70")!,
|
||||
UUID(uuidString: "56e7d8d3-e9e4-48b6-968e-8d102833af00")!,
|
||||
]
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithUUID<StrategyDeferredToUUID>>("t").filter(key: uuids[0])
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE "id" = x'6162636465666768696a6b6c6d6e6f70'
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithUUID<StrategyDeferredToUUID>>("t").filter(keys: uuids)
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE "id" IN (x'6162636465666768696a6b6c6d6e6f70', x'56e7d8d3e9e448b6968e8d102833af00')
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithUUID<StrategyUppercaseString>>("t").filter(key: uuids[0])
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE "id" = '61626364-6566-6768-696A-6B6C6D6E6F70'
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithUUID<StrategyUppercaseString>>("t").filter(keys: uuids)
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE "id" IN ('61626364-6566-6768-696A-6B6C6D6E6F70', '56E7D8D3-E9E4-48B6-968E-8D102833AF00')
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithUUID<StrategyLowercaseString>>("t").filter(key: uuids[0])
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE "id" = '61626364-6566-6768-696a-6b6c6d6e6f70'
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithUUID<StrategyLowercaseString>>("t").filter(keys: uuids)
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE "id" IN ('61626364-6566-6768-696a-6b6c6d6e6f70', '56e7d8d3-e9e4-48b6-968e-8d102833af00')
|
||||
""")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testFilterID() throws {
|
||||
guard #available(iOS 13, macOS 10.15, tvOS 13, watchOS 6, *) else {
|
||||
throw XCTSkip("Identifiable not available")
|
||||
}
|
||||
|
||||
try makeDatabaseQueue().write { db in
|
||||
try db.create(table: "t") { $0.primaryKey("id", .blob) }
|
||||
let uuids = [
|
||||
UUID(uuidString: "61626364-6566-6768-696A-6B6C6D6E6F70")!,
|
||||
UUID(uuidString: "56e7d8d3-e9e4-48b6-968e-8d102833af00")!,
|
||||
]
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithUUID<StrategyDeferredToUUID>>("t").filter(id: uuids[0])
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE "id" = x'6162636465666768696a6b6c6d6e6f70'
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithUUID<StrategyDeferredToUUID>>("t").filter(ids: uuids)
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE "id" IN (x'6162636465666768696a6b6c6d6e6f70', x'56e7d8d3e9e448b6968e8d102833af00')
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithUUID<StrategyUppercaseString>>("t").filter(id: uuids[0])
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE "id" = '61626364-6566-6768-696A-6B6C6D6E6F70'
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithUUID<StrategyUppercaseString>>("t").filter(ids: uuids)
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE "id" IN ('61626364-6566-6768-696A-6B6C6D6E6F70', '56E7D8D3-E9E4-48B6-968E-8D102833AF00')
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithUUID<StrategyLowercaseString>>("t").filter(id: uuids[0])
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE "id" = '61626364-6566-6768-696a-6b6c6d6e6f70'
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithUUID<StrategyLowercaseString>>("t").filter(ids: uuids)
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE "id" IN ('61626364-6566-6768-696a-6b6c6d6e6f70', '56e7d8d3-e9e4-48b6-968e-8d102833af00')
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithOptionalUUID<StrategyDeferredToUUID>>("t").filter(id: nil)
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE 0
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithOptionalUUID<StrategyDeferredToUUID>>("t").filter(id: uuids[0])
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE "id" = x'6162636465666768696a6b6c6d6e6f70'
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithOptionalUUID<StrategyDeferredToUUID>>("t").filter(ids: uuids)
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE "id" IN (x'6162636465666768696a6b6c6d6e6f70', x'56e7d8d3e9e448b6968e8d102833af00')
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithOptionalUUID<StrategyUppercaseString>>("t").filter(id: nil)
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE 0
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithOptionalUUID<StrategyUppercaseString>>("t").filter(id: uuids[0])
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE "id" = '61626364-6566-6768-696A-6B6C6D6E6F70'
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithOptionalUUID<StrategyUppercaseString>>("t").filter(ids: uuids)
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE "id" IN ('61626364-6566-6768-696A-6B6C6D6E6F70', '56E7D8D3-E9E4-48B6-968E-8D102833AF00')
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithOptionalUUID<StrategyLowercaseString>>("t").filter(id: nil)
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE 0
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithOptionalUUID<StrategyLowercaseString>>("t").filter(id: uuids[0])
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE "id" = '61626364-6566-6768-696a-6b6c6d6e6f70'
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
let request = Table<RecordWithOptionalUUID<StrategyLowercaseString>>("t").filter(ids: uuids)
|
||||
try assertEqualSQL(db, request, """
|
||||
SELECT * FROM "t" WHERE "id" IN ('61626364-6566-6768-696a-6b6c6d6e6f70', '56e7d8d3-e9e4-48b6-968e-8d102833af00')
|
||||
""")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testDeleteID() throws {
|
||||
guard #available(iOS 13, macOS 10.15, tvOS 13, watchOS 6, *) else {
|
||||
throw XCTSkip("Identifiable not available")
|
||||
}
|
||||
|
||||
try makeDatabaseQueue().write { db in
|
||||
try db.create(table: "t") { $0.primaryKey("id", .blob) }
|
||||
let uuids = [
|
||||
UUID(uuidString: "61626364-6566-6768-696A-6B6C6D6E6F70")!,
|
||||
UUID(uuidString: "56e7d8d3-e9e4-48b6-968e-8d102833af00")!,
|
||||
]
|
||||
|
||||
do {
|
||||
try Table<RecordWithUUID<StrategyDeferredToUUID>>("t").deleteOne(db, id: uuids[0])
|
||||
XCTAssertEqual(lastSQLQuery, """
|
||||
DELETE FROM "t" WHERE "id" = x'6162636465666768696a6b6c6d6e6f70'
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
try Table<RecordWithUUID<StrategyDeferredToUUID>>("t").deleteAll(db, ids: uuids)
|
||||
XCTAssertEqual(lastSQLQuery, """
|
||||
DELETE FROM "t" WHERE "id" IN (x'6162636465666768696a6b6c6d6e6f70', x'56e7d8d3e9e448b6968e8d102833af00')
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
try Table<RecordWithUUID<StrategyUppercaseString>>("t").deleteOne(db, id: uuids[0])
|
||||
XCTAssertEqual(lastSQLQuery, """
|
||||
DELETE FROM "t" WHERE "id" = '61626364-6566-6768-696A-6B6C6D6E6F70'
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
try Table<RecordWithUUID<StrategyUppercaseString>>("t").deleteAll(db, ids: uuids)
|
||||
XCTAssertEqual(lastSQLQuery, """
|
||||
DELETE FROM "t" WHERE "id" IN ('61626364-6566-6768-696A-6B6C6D6E6F70', '56E7D8D3-E9E4-48B6-968E-8D102833AF00')
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
try Table<RecordWithUUID<StrategyLowercaseString>>("t").deleteOne(db, id: uuids[0])
|
||||
XCTAssertEqual(lastSQLQuery, """
|
||||
DELETE FROM "t" WHERE "id" = '61626364-6566-6768-696a-6b6c6d6e6f70'
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
try Table<RecordWithUUID<StrategyLowercaseString>>("t").deleteAll(db, ids: uuids)
|
||||
XCTAssertEqual(lastSQLQuery, """
|
||||
DELETE FROM "t" WHERE "id" IN ('61626364-6566-6768-696a-6b6c6d6e6f70', '56e7d8d3-e9e4-48b6-968e-8d102833af00')
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
sqlQueries.removeAll()
|
||||
try Table<RecordWithOptionalUUID<StrategyDeferredToUUID>>("t").deleteOne(db, id: nil)
|
||||
XCTAssertNil(lastSQLQuery) // Database not hit
|
||||
}
|
||||
|
||||
do {
|
||||
try Table<RecordWithOptionalUUID<StrategyDeferredToUUID>>("t").deleteOne(db, id: uuids[0])
|
||||
XCTAssertEqual(lastSQLQuery, """
|
||||
DELETE FROM "t" WHERE "id" = x'6162636465666768696a6b6c6d6e6f70'
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
try Table<RecordWithOptionalUUID<StrategyDeferredToUUID>>("t").deleteAll(db, ids: uuids)
|
||||
XCTAssertEqual(lastSQLQuery, """
|
||||
DELETE FROM "t" WHERE "id" IN (x'6162636465666768696a6b6c6d6e6f70', x'56e7d8d3e9e448b6968e8d102833af00')
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
sqlQueries.removeAll()
|
||||
try Table<RecordWithOptionalUUID<StrategyUppercaseString>>("t").deleteOne(db, id: nil)
|
||||
XCTAssertNil(lastSQLQuery) // Database not hit
|
||||
}
|
||||
|
||||
do {
|
||||
try Table<RecordWithOptionalUUID<StrategyUppercaseString>>("t").deleteOne(db, id: uuids[0])
|
||||
XCTAssertEqual(lastSQLQuery, """
|
||||
DELETE FROM "t" WHERE "id" = '61626364-6566-6768-696A-6B6C6D6E6F70'
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
try Table<RecordWithOptionalUUID<StrategyUppercaseString>>("t").deleteAll(db, ids: uuids)
|
||||
XCTAssertEqual(lastSQLQuery, """
|
||||
DELETE FROM "t" WHERE "id" IN ('61626364-6566-6768-696A-6B6C6D6E6F70', '56E7D8D3-E9E4-48B6-968E-8D102833AF00')
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
sqlQueries.removeAll()
|
||||
try Table<RecordWithOptionalUUID<StrategyLowercaseString>>("t").deleteOne(db, id: nil)
|
||||
XCTAssertNil(lastSQLQuery) // Database not hit
|
||||
}
|
||||
|
||||
do {
|
||||
try Table<RecordWithOptionalUUID<StrategyLowercaseString>>("t").deleteOne(db, id: uuids[0])
|
||||
XCTAssertEqual(lastSQLQuery, """
|
||||
DELETE FROM "t" WHERE "id" = '61626364-6566-6768-696a-6b6c6d6e6f70'
|
||||
""")
|
||||
}
|
||||
|
||||
do {
|
||||
try Table<RecordWithOptionalUUID<StrategyLowercaseString>>("t").deleteAll(db, ids: uuids)
|
||||
XCTAssertEqual(lastSQLQuery, """
|
||||
DELETE FROM "t" WHERE "id" IN ('61626364-6566-6768-696a-6b6c6d6e6f70', '56e7d8d3-e9e4-48b6-968e-8d102833af00')
|
||||
""")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user