120 lines
4.0 KiB
Swift
120 lines
4.0 KiB
Swift
import Foundation
|
|
import Testing
|
|
@testable import LocalData
|
|
|
|
private func makeLegacyKey(name: String, domain: StorageDomain) -> StorageKey<String> {
|
|
StorageKey(
|
|
name: name,
|
|
domain: domain,
|
|
security: .none,
|
|
owner: "Legacy",
|
|
description: "Legacy key"
|
|
)
|
|
}
|
|
|
|
private func makeModernKey(
|
|
name: String,
|
|
domain: StorageDomain,
|
|
legacyKey: AnyStorageKey?
|
|
) -> StorageKey<String> {
|
|
StorageKey(
|
|
name: name,
|
|
domain: domain,
|
|
security: .keychain(accessibility: .afterFirstUnlock, accessControl: .none),
|
|
owner: "Modern",
|
|
description: "Modern key",
|
|
migration: { destinationKey in
|
|
guard let legacyKey else { return nil }
|
|
return AnyStorageMigration(
|
|
SimpleLegacyMigration(destinationKey: destinationKey, sourceKey: legacyKey)
|
|
)
|
|
}
|
|
)
|
|
}
|
|
|
|
@Suite(.serialized)
|
|
struct MigrationTests {
|
|
private let router: StorageRouter
|
|
|
|
init() {
|
|
let testBaseURL = FileManager.default.temporaryDirectory.appending(path: "MigrationTests-\(UUID().uuidString)")
|
|
router = StorageRouter(
|
|
keychain: MockKeychainHelper(),
|
|
encryption: EncryptionHelper(keychain: MockKeychainHelper()),
|
|
file: FileStorageHelper(configuration: FileStorageConfiguration(baseURL: testBaseURL)),
|
|
defaults: UserDefaultsHelper(defaults: UserDefaults(suiteName: "MigrationTests-\(UUID().uuidString)")!)
|
|
)
|
|
}
|
|
|
|
@Test func automaticMigrationFromUserDefaultsToKeychain() async throws {
|
|
let legacyName = "legacy.user.name"
|
|
let modernName = "user.name"
|
|
let suiteName = "MigrationTests.\(UUID().uuidString)"
|
|
let secretValue = "Matt Bruce"
|
|
|
|
defer {
|
|
UserDefaults().removePersistentDomain(forName: suiteName)
|
|
}
|
|
|
|
// 1. Setup legacy data manually in UserDefaults
|
|
let legacyKey = makeLegacyKey(name: legacyName, domain: .userDefaults(suite: suiteName))
|
|
try await router.set(secretValue, for: legacyKey)
|
|
|
|
// Verify it exists in legacy location
|
|
let existsInLegacy = try await router.exists(legacyKey)
|
|
#expect(existsInLegacy == true)
|
|
|
|
// 2. Setup modern key with legacy source
|
|
let modernKey = makeModernKey(
|
|
name: modernName,
|
|
domain: .keychain(service: "test.migration"),
|
|
legacyKey: .key(legacyKey)
|
|
)
|
|
|
|
// 3. Trigger automatic migration via GET
|
|
let migratedValue = try await router.get(modernKey)
|
|
#expect(migratedValue == secretValue)
|
|
|
|
// 4. Verify data moved
|
|
// Modern should now exist
|
|
let existsInModern = try await router.exists(modernKey)
|
|
#expect(existsInModern == true)
|
|
|
|
// Legacy should be gone
|
|
let existsInLegacyAfter = try await router.exists(legacyKey)
|
|
#expect(existsInLegacyAfter == false)
|
|
}
|
|
|
|
@Test func manualMigrationSweep() async throws {
|
|
let legacyName = "legacy.manual.key"
|
|
let modernName = "modern.manual.key"
|
|
let suiteName = "MigrationTests.Manual.\(UUID().uuidString)"
|
|
let value = "Manual Data"
|
|
|
|
defer {
|
|
UserDefaults().removePersistentDomain(forName: suiteName)
|
|
}
|
|
|
|
// 1. Setup legacy data
|
|
let legacyKey = makeLegacyKey(name: legacyName, domain: .userDefaults(suite: suiteName))
|
|
try await router.set(value, for: legacyKey)
|
|
|
|
// 2. Setup modern key
|
|
let modernKey = makeModernKey(
|
|
name: modernName,
|
|
domain: .userDefaults(suite: suiteName),
|
|
legacyKey: .key(legacyKey)
|
|
)
|
|
|
|
// 3. Trigger manual migration
|
|
_ = try await router.forceMigration(for: modernKey)
|
|
|
|
// 4. Verify
|
|
let hasModern = try await router.exists(modernKey)
|
|
#expect(hasModern == true)
|
|
|
|
let hasLegacy = try await router.exists(legacyKey)
|
|
#expect(hasLegacy == false)
|
|
}
|
|
}
|