110 lines
4.5 KiB
Swift
110 lines
4.5 KiB
Swift
//
|
|
// Copyright 2022 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
//
|
|
|
|
import GRDB
|
|
import XCTest
|
|
|
|
@testable import SignalServiceKit
|
|
|
|
class GRDBSchemaMigratorTest: XCTestCase {
|
|
func testMigrateFromScratch() throws {
|
|
let databaseStorage = SDSDatabaseStorage(
|
|
databaseFileUrl: OWSFileSystem.temporaryFileUrl(),
|
|
delegate: DatabaseTestHelpers.TestSDSDatabaseStorageDelegate()
|
|
)
|
|
|
|
try GRDBSchemaMigrator.migrateDatabase(
|
|
databaseStorage: databaseStorage,
|
|
isMainDatabase: false
|
|
)
|
|
|
|
databaseStorage.read { transaction in
|
|
let db = transaction.unwrapGrdbRead.database
|
|
let sql = "SELECT name FROM sqlite_schema WHERE type IS 'table'"
|
|
let allTableNames = (try? String.fetchAll(db, sql: sql)) ?? []
|
|
|
|
XCTAssert(allTableNames.contains(TSThread.table.tableName))
|
|
}
|
|
}
|
|
|
|
private func keyedArchiverData(rootObject: Any) -> Data {
|
|
try! NSKeyedArchiver.archivedData(withRootObject: rootObject, requiringSecureCoding: true)
|
|
}
|
|
|
|
func testMigrateVoiceMessageDrafts() throws {
|
|
let collection = "DraftVoiceMessage"
|
|
|
|
let baseUrl = URL(fileURLWithPath: "/not/a/real/path", isDirectory: true)
|
|
let initialEntries: [(String, String, Data)] = [
|
|
(collection, "00000000-0000-4000-8000-000000000001", keyedArchiverData(rootObject: NSNumber(true))),
|
|
(collection, "00000000-0000-4000-8000-000000000002", keyedArchiverData(rootObject: NSNumber(true))),
|
|
(collection, "00000000-0000-4000-8000-000000000003", keyedArchiverData(rootObject: NSNumber(false))),
|
|
(collection, "00000000-0000-4000-8000-000000000004", keyedArchiverData(rootObject: [6, 7, 8, 9, 10])),
|
|
(collection, "abc1+/==", keyedArchiverData(rootObject: NSNumber(true))),
|
|
("UnrelatedCollection", "SomeKey", Data(count: 3))
|
|
]
|
|
|
|
// Set up the database with sample data that may have existed.
|
|
let databaseQueue = DatabaseQueue()
|
|
try databaseQueue.write { db in
|
|
// A snapshot of the key value store as it existed when this migration was
|
|
// added. If the key value store's schema is updated in the future, don't
|
|
// update this call site. It must remain as a snapshot.
|
|
try db.execute(
|
|
sql: "CREATE TABLE keyvalue (key TEXT NOT NULL, collection TEXT NOT NULL, value BLOB NOT NULL, PRIMARY KEY (key, collection))"
|
|
)
|
|
for (collection, key, value) in initialEntries {
|
|
try db.execute(
|
|
sql: "INSERT INTO keyvalue (collection, key, value) VALUES (?, ?, ?)",
|
|
arguments: [collection, key, value]
|
|
)
|
|
}
|
|
}
|
|
|
|
// Run the test.
|
|
var copyResults: [Result<Void, Error>] = [.success(()), .failure(CocoaError(.fileNoSuchFile)), .success(())]
|
|
var copyRequests = [(URL, URL)]()
|
|
let copyItem = { (src: URL, dst: URL) throws in
|
|
copyRequests.append((src, dst))
|
|
return try copyResults.removeFirst().get()
|
|
}
|
|
try databaseQueue.write { db in
|
|
let transaction = GRDBWriteTransaction(database: db)
|
|
defer { transaction.finalizeTransaction() }
|
|
try GRDBSchemaMigrator.migrateVoiceMessageDrafts(
|
|
transaction: transaction,
|
|
appSharedDataUrl: baseUrl,
|
|
copyItem: copyItem
|
|
)
|
|
}
|
|
|
|
// Validate the ending state.
|
|
let rows = try databaseQueue.read {
|
|
try Row.fetchAll($0, sql: "SELECT collection, key, value FROM keyvalue ORDER BY collection, key")
|
|
}
|
|
let migratedFilenames = Dictionary(uniqueKeysWithValues: copyRequests.map { ($0.0.lastPathComponent, $0.1.lastPathComponent) })
|
|
|
|
XCTAssertEqual(rows.count, 3)
|
|
|
|
XCTAssertEqual(rows[0]["collection"], collection)
|
|
XCTAssertEqual(rows[0]["key"], "00000000-0000-4000-8000-000000000001")
|
|
XCTAssertEqual(
|
|
rows[0]["value"],
|
|
keyedArchiverData(rootObject: migratedFilenames["00000000%2D0000%2D4000%2D8000%2D000000000001"]!)
|
|
)
|
|
|
|
XCTAssertEqual(rows[1]["collection"], collection)
|
|
XCTAssertEqual(rows[1]["key"], "abc1+/==")
|
|
XCTAssertEqual(
|
|
rows[1]["value"],
|
|
keyedArchiverData(rootObject: migratedFilenames["abc1%2B%2F%3D%3D"]!)
|
|
)
|
|
|
|
XCTAssertEqual(rows[2]["collection"], "UnrelatedCollection")
|
|
XCTAssertEqual(rows[2]["key"], "SomeKey")
|
|
XCTAssertEqual(rows[2]["value"], Data(count: 3))
|
|
}
|
|
}
|