86 lines
3.5 KiB
Swift
86 lines
3.5 KiB
Swift
import XCTest
|
|
@testable import Rosetta
|
|
|
|
@MainActor
|
|
final class MigrationHarnessTests: XCTestCase {
|
|
private var ctx: DBTestContext!
|
|
|
|
override func setUpWithError() throws {
|
|
ctx = DBTestContext()
|
|
}
|
|
|
|
override func tearDownWithError() throws {
|
|
ctx.teardown()
|
|
ctx = nil
|
|
}
|
|
|
|
func testLegacySyncOnlyMigrationReconcilesWithoutSQLiteUpsertSyntaxFailure() async throws {
|
|
try await ctx.bootstrap()
|
|
|
|
DatabaseManager.shared.close()
|
|
let sqlite = try ctx.openSQLite()
|
|
let rerunMigrations = DatabaseManager.migrationIdentifiers.dropFirst(3)
|
|
let deleteList = rerunMigrations.map { "'\($0)'" }.joined(separator: ",")
|
|
try sqlite.execute("DELETE FROM grdb_migrations WHERE identifier IN (\(deleteList))")
|
|
try sqlite.execute("DROP TABLE IF EXISTS accounts_sync_times")
|
|
try sqlite.execute("DELETE FROM sync_cursors")
|
|
try sqlite.execute("INSERT INTO sync_cursors(account, timestamp) VALUES ('\(ctx.account)', 1234567890123)")
|
|
|
|
try DatabaseManager.shared.bootstrap(accountPublicKey: ctx.account)
|
|
let cursor = DatabaseManager.shared.loadSyncCursor(account: ctx.account)
|
|
XCTAssertEqual(cursor, 1_234_567_890_123)
|
|
}
|
|
|
|
func testPartialReconcileBackfillsNullIds() async throws {
|
|
try await ctx.bootstrap()
|
|
DatabaseManager.shared.saveSyncCursor(account: ctx.account, timestamp: 9_001)
|
|
|
|
DatabaseManager.shared.close()
|
|
let sqlite = try ctx.openSQLite()
|
|
try sqlite.execute("UPDATE accounts_sync_times SET id = NULL WHERE account = '\(ctx.account)'")
|
|
try sqlite.execute("DELETE FROM grdb_migrations WHERE identifier = '\(DatabaseManager.migrationV7SyncCursorReconcile)'")
|
|
|
|
try DatabaseManager.shared.bootstrap(accountPublicKey: ctx.account)
|
|
|
|
let check = try ctx.openSQLite()
|
|
let rows = try check.query(
|
|
"SELECT id, last_sync FROM accounts_sync_times WHERE account = ? LIMIT 1",
|
|
[.text(ctx.account)]
|
|
)
|
|
XCTAssertEqual(rows.count, 1)
|
|
XCTAssertNotEqual(rows.first?["id"], "")
|
|
XCTAssertNotEqual(rows.first?["id"], "0")
|
|
XCTAssertEqual(rows.first?["last_sync"], "9001")
|
|
}
|
|
|
|
func testMonotonicSyncCursorNeverDecreases() async throws {
|
|
try await ctx.bootstrap()
|
|
|
|
DatabaseManager.shared.saveSyncCursor(account: ctx.account, timestamp: 1_700_000_005_000)
|
|
DatabaseManager.shared.saveSyncCursor(account: ctx.account, timestamp: 1_700_000_004_999)
|
|
DatabaseManager.shared.saveSyncCursor(account: ctx.account, timestamp: 1_700_000_006_500)
|
|
|
|
XCTAssertEqual(DatabaseManager.shared.loadSyncCursor(account: ctx.account), 1_700_000_006_500)
|
|
}
|
|
|
|
func testCompatibilityMirrorWritesAccountsSyncTimesAndSyncCursors() async throws {
|
|
try await ctx.bootstrap()
|
|
DatabaseManager.shared.saveSyncCursor(account: ctx.account, timestamp: 77_777)
|
|
|
|
let sqlite = try ctx.openSQLite()
|
|
let accountsRows = try sqlite.query(
|
|
"SELECT last_sync, id FROM accounts_sync_times WHERE account = ? LIMIT 1",
|
|
[.text(ctx.account)]
|
|
)
|
|
let legacyRows = try sqlite.query(
|
|
"SELECT timestamp FROM sync_cursors WHERE account = ? LIMIT 1",
|
|
[.text(ctx.account)]
|
|
)
|
|
|
|
XCTAssertEqual(accountsRows.first?["last_sync"], "77777")
|
|
XCTAssertNotEqual(accountsRows.first?["id"], "")
|
|
XCTAssertNotEqual(accountsRows.first?["id"], "0")
|
|
XCTAssertEqual(legacyRows.first?["timestamp"], "77777")
|
|
}
|
|
}
|