Files
UUVPN/iOS-SwiftUI-Code/GRDB.swift-6.29.3/Tests/GRDBTests/DatabaseQueueTemporaryCopyTests.swift

167 lines
5.9 KiB
Swift

import XCTest
import GRDB
private final class TestStream: TextOutputStream {
var output: String
init() {
output = ""
}
func write(_ string: String) {
output.append(string)
}
}
final class DatabaseQueueTemporaryCopyTests: GRDBTestCase {
private func makeSourceDatabase() throws -> DatabaseQueue {
let dbQueue = try makeDatabaseQueue()
try dbQueue.write { db in
try db.create(table: "player") { t in
t.autoIncrementedPrimaryKey("id")
t.column("name", .text)
t.column("score", .integer)
}
try db.execute(sql: "INSERT INTO player VALUES (NULL, 'Arthur', 500)")
try db.execute(sql: "INSERT INTO player VALUES (NULL, 'Barbara', 1000)")
}
return dbQueue
}
func test_temporaryCopy() throws {
let source = try makeSourceDatabase()
let dbQueue = try DatabaseQueue.temporaryCopy(
fromPath: source.path,
configuration: dbConfiguration)
// Test that content was faithfully copied
let stream = TestStream()
try dbQueue.dumpContent(format: .quote(), to: stream)
XCTAssertEqual(stream.output, """
sqlite_master
CREATE TABLE "player" ("id" INTEGER PRIMARY KEY AUTOINCREMENT, "name" TEXT, "score" INTEGER);
player
1,'Arthur',500
2,'Barbara',1000
""")
}
func test_temporaryCopy_write() throws {
let source = try makeSourceDatabase()
let dbQueue = try DatabaseQueue.temporaryCopy(
fromPath: source.path,
configuration: dbConfiguration)
// The in-memory copy is writable (necessary for testing migrations)
try dbQueue.write { db in
try db.execute(sql: "INSERT INTO player VALUES (NULL, 'Craig', 200)")
}
let stream = TestStream()
try dbQueue.dumpContent(format: .quote(), to: stream)
XCTAssertEqual(stream.output, """
sqlite_master
CREATE TABLE "player" ("id" INTEGER PRIMARY KEY AUTOINCREMENT, "name" TEXT, "score" INTEGER);
player
1,'Arthur',500
2,'Barbara',1000
3,'Craig',200
""")
}
func test_temporaryCopy_readOnly() throws {
let source = try makeSourceDatabase()
var config = dbConfiguration!
config.readonly = true
let dbQueue = try DatabaseQueue.temporaryCopy(fromPath: source.path, configuration: config)
// Test that the copy is read-only
XCTAssertThrowsError(try dbQueue.write { try $0.execute(sql: "DROP TABLE player") }) { error in
guard let dbError = error as? DatabaseError else {
XCTFail("Expected DatabaseError")
return
}
XCTAssertEqual(dbError.message, "attempt to write a readonly database")
}
// Test that the copy is still read-only after a read
try dbQueue.read { _ in }
XCTAssertThrowsError(try dbQueue.write { try $0.execute(sql: "DROP TABLE player") }) { error in
guard let dbError = error as? DatabaseError else {
XCTFail("Expected DatabaseError")
return
}
XCTAssertEqual(dbError.message, "attempt to write a readonly database")
}
// Test that content was faithfully copied
let stream = TestStream()
try dbQueue.dumpContent(format: .quote(), to: stream)
XCTAssertEqual(stream.output, """
sqlite_master
CREATE TABLE "player" ("id" INTEGER PRIMARY KEY AUTOINCREMENT, "name" TEXT, "score" INTEGER);
player
1,'Arthur',500
2,'Barbara',1000
""")
}
func test_migrations_are_testable() throws {
// Given a migrator…
var migrator = DatabaseMigrator()
migrator.registerMigration("v1") { try $0.create(table: "team") { $0.autoIncrementedPrimaryKey("id") } }
migrator.registerMigration("v2") { try $0.create(table: "match") { $0.autoIncrementedPrimaryKey("id") } }
migrator.registerMigration("v3") { try $0.drop(table: "match") }
// …GRDB users can test the migrator on fixtures
let source = try makeSourceDatabase()
let dbQueue = try DatabaseQueue.temporaryCopy(
fromPath: source.path,
configuration: dbConfiguration)
try migrator.migrate(dbQueue, upTo: "v2")
do {
let stream = TestStream()
try dbQueue.dumpContent(format: .quote(), to: stream)
XCTAssertEqual(stream.output, """
sqlite_master
CREATE TABLE "match" ("id" INTEGER PRIMARY KEY AUTOINCREMENT);
CREATE TABLE "player" ("id" INTEGER PRIMARY KEY AUTOINCREMENT, "name" TEXT, "score" INTEGER);
CREATE TABLE "team" ("id" INTEGER PRIMARY KEY AUTOINCREMENT);
match
player
1,'Arthur',500
2,'Barbara',1000
team
""")
}
try migrator.migrate(dbQueue, upTo: "v3")
do {
let stream = TestStream()
try dbQueue.dumpContent(format: .quote(), to: stream)
XCTAssertEqual(stream.output, """
sqlite_master
CREATE TABLE "player" ("id" INTEGER PRIMARY KEY AUTOINCREMENT, "name" TEXT, "score" INTEGER);
CREATE TABLE "team" ("id" INTEGER PRIMARY KEY AUTOINCREMENT);
player
1,'Arthur',500
2,'Barbara',1000
team
""")
}
}
}