fixed tests
Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
b30cc0da19
commit
b1bf6020f3
@ -4,20 +4,18 @@ import Testing
|
||||
|
||||
@Suite struct AnyStorageKeyTests {
|
||||
|
||||
private struct StringKey: StorageKey {
|
||||
typealias Value = String
|
||||
let name: String
|
||||
let domain: StorageDomain = .userDefaults(suite: nil)
|
||||
let security: SecurityPolicy = .none
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "Test"
|
||||
let description: String = "Test"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
private func makeStringKey(name: String) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: .userDefaults(suite: nil),
|
||||
security: .none,
|
||||
owner: "Test",
|
||||
description: "Test"
|
||||
)
|
||||
}
|
||||
|
||||
@Test func anyStorageKeyCapturesDescriptor() {
|
||||
let key = StringKey(name: "test.key")
|
||||
let key = makeStringKey(name: "test.key")
|
||||
let anyKey = AnyStorageKey.key(key)
|
||||
|
||||
#expect(anyKey.descriptor.name == "test.key")
|
||||
@ -27,7 +25,7 @@ import Testing
|
||||
|
||||
@Test func anyStorageKeyTriggersMigration() async throws {
|
||||
let router = StorageRouter(keychain: MockKeychainHelper())
|
||||
let key = StringKey(name: "test.key")
|
||||
let key = makeStringKey(name: "test.key")
|
||||
let anyKey = AnyStorageKey.key(key)
|
||||
|
||||
// This will call router.forceMigration(for: key)
|
||||
|
||||
@ -7,31 +7,35 @@ import Testing
|
||||
private struct AuditCatalog: StorageKeyCatalog {
|
||||
var allKeys: [AnyStorageKey] {
|
||||
[
|
||||
.key(TestKey(name: "k1", domain: .userDefaults(suite: nil))),
|
||||
.key(TestKey(name: "k2", domain: .keychain(service: "s"), security: .keychain(accessibility: .afterFirstUnlock, accessControl: .userPresence))),
|
||||
.key(TestKey(name: "k3", domain: .fileSystem(directory: .documents))),
|
||||
.key(TestKey(name: "k4", domain: .encryptedFileSystem(directory: .caches))),
|
||||
.key(TestKey(name: "k5", domain: .appGroupUserDefaults(identifier: "ig"), security: .encrypted(.recommended)))
|
||||
.key(AuditTests.makeTestKey(name: "k1", domain: .userDefaults(suite: nil))),
|
||||
.key(AuditTests.makeTestKey(
|
||||
name: "k2",
|
||||
domain: .keychain(service: "s"),
|
||||
security: .keychain(accessibility: .afterFirstUnlock, accessControl: .userPresence)
|
||||
)),
|
||||
.key(AuditTests.makeTestKey(name: "k3", domain: .fileSystem(directory: .documents))),
|
||||
.key(AuditTests.makeTestKey(name: "k4", domain: .encryptedFileSystem(directory: .caches))),
|
||||
.key(AuditTests.makeTestKey(
|
||||
name: "k5",
|
||||
domain: .appGroupUserDefaults(identifier: "ig"),
|
||||
security: .encrypted(.recommended)
|
||||
))
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
private struct TestKey: StorageKey {
|
||||
typealias Value = String
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "Audit"
|
||||
let description: String = "Desc"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
|
||||
init(name: String, domain: StorageDomain, security: SecurityPolicy = .none) {
|
||||
self.name = name
|
||||
self.domain = domain
|
||||
self.security = security
|
||||
}
|
||||
private static func makeTestKey(
|
||||
name: String,
|
||||
domain: StorageDomain,
|
||||
security: SecurityPolicy = .none
|
||||
) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: domain,
|
||||
security: security,
|
||||
owner: "Audit",
|
||||
description: "Desc"
|
||||
)
|
||||
}
|
||||
|
||||
@Test func renderCatalogText() {
|
||||
|
||||
@ -2,40 +2,24 @@ import Foundation
|
||||
import Testing
|
||||
@testable import LocalData
|
||||
|
||||
private struct TestUserDefaultsKey: StorageKey {
|
||||
typealias Value = String
|
||||
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy = .none
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "LocalDataTests"
|
||||
let description: String = "Test-only key for user defaults round-trip."
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
|
||||
init(name: String, suiteName: String) {
|
||||
self.name = name
|
||||
self.domain = .userDefaults(suite: suiteName)
|
||||
}
|
||||
private func makeUserDefaultsKey(name: String, suiteName: String) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: .userDefaults(suite: suiteName),
|
||||
security: .none,
|
||||
owner: "LocalDataTests",
|
||||
description: "Test-only key for user defaults round-trip."
|
||||
)
|
||||
}
|
||||
|
||||
private struct TestFileKey: StorageKey {
|
||||
typealias Value = String
|
||||
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy = .none
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "LocalDataTests"
|
||||
let description: String = "Test-only key for file system round-trip."
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
|
||||
init(name: String, directory: URL) {
|
||||
self.name = name
|
||||
self.domain = .fileSystem(directory: .custom(directory))
|
||||
}
|
||||
private func makeFileKey(name: String, directory: URL) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: .fileSystem(directory: .custom(directory)),
|
||||
security: .none,
|
||||
owner: "LocalDataTests",
|
||||
description: "Test-only key for file system round-trip."
|
||||
)
|
||||
}
|
||||
|
||||
@Suite(.serialized)
|
||||
@ -50,7 +34,7 @@ struct LocalDataTests {
|
||||
}
|
||||
}
|
||||
|
||||
let key = TestUserDefaultsKey(name: "test.string", suiteName: suiteName)
|
||||
let key = makeUserDefaultsKey(name: "test.string", suiteName: suiteName)
|
||||
let storedValue = "1.0.0"
|
||||
|
||||
try await router.set(storedValue, for: key)
|
||||
@ -72,7 +56,7 @@ struct LocalDataTests {
|
||||
try? FileManager.default.removeItem(at: tempDirectory)
|
||||
}
|
||||
|
||||
let key = TestFileKey(name: "test.json", directory: tempDirectory)
|
||||
let key = makeFileKey(name: "test.json", directory: tempDirectory)
|
||||
let storedValue = "payload"
|
||||
|
||||
try await router.set(storedValue, for: key)
|
||||
|
||||
@ -2,72 +2,65 @@ import Foundation
|
||||
import Testing
|
||||
@testable import LocalData
|
||||
|
||||
private struct LegacyStringKey: StorageKey {
|
||||
typealias Value = String
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy = .none
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "Legacy"
|
||||
let description: String = "Legacy string key"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
private func makeLegacyStringKey(name: String, domain: StorageDomain) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: domain,
|
||||
security: .none,
|
||||
owner: "Legacy",
|
||||
description: "Legacy string key"
|
||||
)
|
||||
}
|
||||
|
||||
private struct ModernStringKey: StorageKey {
|
||||
typealias Value = String
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy = .none
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "Modern"
|
||||
let description: String = "Modern string key"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
let legacyKey: AnyStorageKey?
|
||||
|
||||
var migration: AnyStorageMigration? {
|
||||
guard let legacyKey else { return nil }
|
||||
return AnyStorageMigration(
|
||||
SimpleLegacyMigration(destinationKey: self, sourceKey: legacyKey)
|
||||
)
|
||||
}
|
||||
private func makeModernStringKey(
|
||||
name: String,
|
||||
domain: StorageDomain,
|
||||
legacyKey: AnyStorageKey?
|
||||
) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: domain,
|
||||
security: .none,
|
||||
owner: "Modern",
|
||||
description: "Modern string key",
|
||||
migration: { destinationKey in
|
||||
guard let legacyKey else { return nil }
|
||||
return AnyStorageMigration(
|
||||
SimpleLegacyMigration(destinationKey: destinationKey, sourceKey: legacyKey)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private struct PhoneOnlyKey: StorageKey {
|
||||
typealias Value = String
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy = .none
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "PhoneOnly"
|
||||
let description: String = "Phone-only key"
|
||||
let availability: PlatformAvailability = .phoneOnly
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
private func makePhoneOnlyKey(name: String, domain: StorageDomain) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: domain,
|
||||
security: .none,
|
||||
owner: "PhoneOnly",
|
||||
description: "Phone-only key",
|
||||
availability: .phoneOnly
|
||||
)
|
||||
}
|
||||
|
||||
private struct SourceStringKey: StorageKey {
|
||||
typealias Value = String
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy = .none
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "Source"
|
||||
let description: String = "Source key"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
private func makeSourceStringKey(name: String, domain: StorageDomain) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: domain,
|
||||
security: .none,
|
||||
owner: "Source",
|
||||
description: "Source key"
|
||||
)
|
||||
}
|
||||
|
||||
private struct DestinationIntKey: StorageKey {
|
||||
typealias Value = Int
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy = .none
|
||||
let serializer: Serializer<Int> = .json
|
||||
let owner: String = "Destination"
|
||||
let description: String = "Destination int key"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
private func makeDestinationIntKey(name: String, domain: StorageDomain) -> StorageKey<Int> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: domain,
|
||||
security: .none,
|
||||
owner: "Destination",
|
||||
description: "Destination int key"
|
||||
)
|
||||
}
|
||||
|
||||
@Suite(.serialized)
|
||||
@ -85,8 +78,8 @@ struct MigrationAdditionalTests {
|
||||
}
|
||||
|
||||
@Test func migrationHistoryTrackingTest() async throws {
|
||||
let legacyKey = LegacyStringKey(name: "legacy.history", domain: .userDefaults(suite: nil))
|
||||
let modernKey = ModernStringKey(
|
||||
let legacyKey = makeLegacyStringKey(name: "legacy.history", domain: .userDefaults(suite: nil))
|
||||
let modernKey = makeModernStringKey(
|
||||
name: "modern.history",
|
||||
domain: .userDefaults(suite: nil),
|
||||
legacyKey: .key(legacyKey)
|
||||
@ -95,13 +88,13 @@ struct MigrationAdditionalTests {
|
||||
try await router.set("history", for: legacyKey)
|
||||
_ = try await router.forceMigration(for: modernKey)
|
||||
|
||||
let history = router.migrationHistory(for: modernKey)
|
||||
let history = await router.migrationHistory(for: modernKey)
|
||||
#expect(history != nil)
|
||||
}
|
||||
|
||||
@Test func migrationFailureKeepsSourceTest() async throws {
|
||||
let sourceKey = SourceStringKey(name: "legacy.rollback", domain: .userDefaults(suite: nil))
|
||||
let destinationKey = DestinationIntKey(name: "modern.rollback", domain: .userDefaults(suite: nil))
|
||||
let sourceKey = makeSourceStringKey(name: "legacy.rollback", domain: .userDefaults(suite: nil))
|
||||
let destinationKey = makeDestinationIntKey(name: "modern.rollback", domain: .userDefaults(suite: nil))
|
||||
|
||||
try await router.set("not-a-number", for: sourceKey)
|
||||
|
||||
@ -119,8 +112,8 @@ struct MigrationAdditionalTests {
|
||||
}
|
||||
|
||||
@Test func watchAvailabilityBlocksMigrationTest() async throws {
|
||||
let legacyKey = LegacyStringKey(name: "legacy.watch", domain: .userDefaults(suite: nil))
|
||||
let destinationKey = PhoneOnlyKey(name: "modern.watch", domain: .userDefaults(suite: nil))
|
||||
let legacyKey = makeLegacyStringKey(name: "legacy.watch", domain: .userDefaults(suite: nil))
|
||||
let destinationKey = makePhoneOnlyKey(name: "modern.watch", domain: .userDefaults(suite: nil))
|
||||
|
||||
let migration = SimpleLegacyMigration(destinationKey: destinationKey, sourceKey: .key(legacyKey))
|
||||
let deviceInfo = DeviceInfo(
|
||||
@ -136,8 +129,8 @@ struct MigrationAdditionalTests {
|
||||
}
|
||||
|
||||
@Test func largeDataMigrationTest() async throws {
|
||||
let legacyKey = LegacyStringKey(name: "legacy.large", domain: .userDefaults(suite: nil))
|
||||
let modernKey = ModernStringKey(
|
||||
let legacyKey = makeLegacyStringKey(name: "legacy.large", domain: .userDefaults(suite: nil))
|
||||
let modernKey = makeModernStringKey(
|
||||
name: "modern.large",
|
||||
domain: .userDefaults(suite: nil),
|
||||
legacyKey: .key(legacyKey)
|
||||
@ -155,8 +148,8 @@ struct MigrationAdditionalTests {
|
||||
}
|
||||
|
||||
@Test func typeErasureMigrationTest() async throws {
|
||||
let legacyKey = LegacyStringKey(name: "legacy.erased", domain: .userDefaults(suite: nil))
|
||||
let modernKey = ModernStringKey(
|
||||
let legacyKey = makeLegacyStringKey(name: "legacy.erased", domain: .userDefaults(suite: nil))
|
||||
let modernKey = makeModernStringKey(
|
||||
name: "modern.erased",
|
||||
domain: .userDefaults(suite: nil),
|
||||
legacyKey: .key(legacyKey)
|
||||
|
||||
@ -2,36 +2,34 @@ import Foundation
|
||||
import Testing
|
||||
@testable import LocalData
|
||||
|
||||
private struct LegacyIntegrationKey: StorageKey {
|
||||
typealias Value = String
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy = .none
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "Legacy"
|
||||
let description: String = "Legacy integration key"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
private func makeLegacyIntegrationKey(name: String, domain: StorageDomain) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: domain,
|
||||
security: .none,
|
||||
owner: "Legacy",
|
||||
description: "Legacy integration key"
|
||||
)
|
||||
}
|
||||
|
||||
private struct ModernIntegrationKey: StorageKey {
|
||||
typealias Value = String
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy = .keychain(accessibility: .afterFirstUnlock, accessControl: .none)
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "Modern"
|
||||
let description: String = "Modern integration key"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
let legacyKey: AnyStorageKey?
|
||||
|
||||
var migration: AnyStorageMigration? {
|
||||
guard let legacyKey else { return nil }
|
||||
return AnyStorageMigration(
|
||||
SimpleLegacyMigration(destinationKey: self, sourceKey: legacyKey)
|
||||
)
|
||||
}
|
||||
private func makeModernIntegrationKey(
|
||||
name: String,
|
||||
domain: StorageDomain,
|
||||
legacyKey: AnyStorageKey?
|
||||
) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: domain,
|
||||
security: .keychain(accessibility: .afterFirstUnlock, accessControl: .none),
|
||||
owner: "Modern",
|
||||
description: "Modern integration key",
|
||||
migration: { destinationKey in
|
||||
guard let legacyKey else { return nil }
|
||||
return AnyStorageMigration(
|
||||
SimpleLegacyMigration(destinationKey: destinationKey, sourceKey: legacyKey)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private struct IntegrationCatalog: StorageKeyCatalog {
|
||||
@ -53,8 +51,8 @@ struct MigrationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test func endToEndMigrationTest() async throws {
|
||||
let legacyKey = LegacyIntegrationKey(name: "legacy.integration", domain: .userDefaults(suite: nil))
|
||||
let modernKey = ModernIntegrationKey(
|
||||
let legacyKey = makeLegacyIntegrationKey(name: "legacy.integration", domain: .userDefaults(suite: nil))
|
||||
let modernKey = makeModernIntegrationKey(
|
||||
name: "modern.integration",
|
||||
domain: .keychain(service: "test.migration"),
|
||||
legacyKey: .key(legacyKey)
|
||||
@ -69,8 +67,8 @@ struct MigrationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test func migrationRegistrationTest() async throws {
|
||||
let legacyKey = LegacyIntegrationKey(name: "legacy.catalog", domain: .userDefaults(suite: nil))
|
||||
let modernKey = ModernIntegrationKey(
|
||||
let legacyKey = makeLegacyIntegrationKey(name: "legacy.catalog", domain: .userDefaults(suite: nil))
|
||||
let modernKey = makeModernIntegrationKey(
|
||||
name: "modern.catalog",
|
||||
domain: .keychain(service: "test.migration"),
|
||||
legacyKey: .key(legacyKey)
|
||||
@ -86,8 +84,8 @@ struct MigrationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test func concurrentMigrationTest() async throws {
|
||||
let legacyKey = LegacyIntegrationKey(name: "legacy.concurrent", domain: .userDefaults(suite: nil))
|
||||
let modernKey = ModernIntegrationKey(
|
||||
let legacyKey = makeLegacyIntegrationKey(name: "legacy.concurrent", domain: .userDefaults(suite: nil))
|
||||
let modernKey = makeModernIntegrationKey(
|
||||
name: "modern.concurrent",
|
||||
domain: .keychain(service: "test.migration"),
|
||||
legacyKey: .key(legacyKey)
|
||||
@ -105,7 +103,7 @@ struct MigrationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test func migrationFailureResultTest() async throws {
|
||||
let destinationKey = ModernIntegrationKey(
|
||||
let destinationKey = makeModernIntegrationKey(
|
||||
name: "modern.failure",
|
||||
domain: .userDefaults(suite: nil),
|
||||
legacyKey: nil
|
||||
|
||||
@ -2,52 +2,44 @@ import Foundation
|
||||
import Testing
|
||||
@testable import LocalData
|
||||
|
||||
private struct LegacyStringKey: StorageKey {
|
||||
typealias Value = String
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy = .none
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "Legacy"
|
||||
let description: String = "Legacy key"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
private func makeLegacyStringKey(name: String, domain: StorageDomain) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: domain,
|
||||
security: .none,
|
||||
owner: "Legacy",
|
||||
description: "Legacy key"
|
||||
)
|
||||
}
|
||||
|
||||
private struct DestinationStringKey: StorageKey {
|
||||
typealias Value = String
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy = .keychain(accessibility: .afterFirstUnlock, accessControl: .none)
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "Destination"
|
||||
let description: String = "Destination key"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
private func makeDestinationStringKey(name: String, domain: StorageDomain) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: domain,
|
||||
security: .keychain(accessibility: .afterFirstUnlock, accessControl: .none),
|
||||
owner: "Destination",
|
||||
description: "Destination key"
|
||||
)
|
||||
}
|
||||
|
||||
private struct SourceStringKey: StorageKey {
|
||||
typealias Value = String
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy = .none
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "Source"
|
||||
let description: String = "Source key"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
private func makeSourceStringKey(name: String, domain: StorageDomain) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: domain,
|
||||
security: .none,
|
||||
owner: "Source",
|
||||
description: "Source key"
|
||||
)
|
||||
}
|
||||
|
||||
private struct DestinationIntKey: StorageKey {
|
||||
typealias Value = Int
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy = .none
|
||||
let serializer: Serializer<Int> = .json
|
||||
let owner: String = "Destination"
|
||||
let description: String = "Destination int key"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
private func makeDestinationIntKey(name: String, domain: StorageDomain) -> StorageKey<Int> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: domain,
|
||||
security: .none,
|
||||
owner: "Destination",
|
||||
description: "Destination int key"
|
||||
)
|
||||
}
|
||||
|
||||
@Suite(.serialized)
|
||||
@ -65,8 +57,11 @@ struct MigrationProtocolTests {
|
||||
}
|
||||
|
||||
@Test func simpleLegacyMigrationTest() async throws {
|
||||
let legacyKey = LegacyStringKey(name: "legacy.simple", domain: .userDefaults(suite: nil))
|
||||
let destinationKey = DestinationStringKey(name: "modern.simple", domain: .keychain(service: "test.migration"))
|
||||
let legacyKey = makeLegacyStringKey(name: "legacy.simple", domain: .userDefaults(suite: nil))
|
||||
let destinationKey = makeDestinationStringKey(
|
||||
name: "modern.simple",
|
||||
domain: .keychain(service: "test.migration")
|
||||
)
|
||||
try await router.set("value", for: legacyKey)
|
||||
|
||||
let migration = SimpleLegacyMigration(destinationKey: destinationKey, sourceKey: .key(legacyKey))
|
||||
@ -83,8 +78,11 @@ struct MigrationProtocolTests {
|
||||
}
|
||||
|
||||
@Test func conditionalMigrationTest() async throws {
|
||||
let legacyKey = LegacyStringKey(name: "legacy.conditional", domain: .userDefaults(suite: nil))
|
||||
let destinationKey = DestinationStringKey(name: "modern.conditional", domain: .keychain(service: "test.migration"))
|
||||
let legacyKey = makeLegacyStringKey(name: "legacy.conditional", domain: .userDefaults(suite: nil))
|
||||
let destinationKey = makeDestinationStringKey(
|
||||
name: "modern.conditional",
|
||||
domain: .keychain(service: "test.migration")
|
||||
)
|
||||
try await router.set("value", for: legacyKey)
|
||||
|
||||
let fallback = AnyStorageMigration(
|
||||
@ -105,8 +103,8 @@ struct MigrationProtocolTests {
|
||||
}
|
||||
|
||||
@Test func transformingMigrationTest() async throws {
|
||||
let sourceKey = SourceStringKey(name: "legacy.transform", domain: .userDefaults(suite: nil))
|
||||
let destinationKey = DestinationIntKey(name: "modern.transform", domain: .userDefaults(suite: nil))
|
||||
let sourceKey = makeSourceStringKey(name: "legacy.transform", domain: .userDefaults(suite: nil))
|
||||
let destinationKey = makeDestinationIntKey(name: "modern.transform", domain: .userDefaults(suite: nil))
|
||||
try await router.set("42", for: sourceKey)
|
||||
|
||||
let migration = DefaultTransformingMigration(
|
||||
@ -127,9 +125,9 @@ struct MigrationProtocolTests {
|
||||
}
|
||||
|
||||
@Test func aggregatingMigrationTest() async throws {
|
||||
let sourceKeyA = SourceStringKey(name: "legacy.aggregate.a", domain: .userDefaults(suite: nil))
|
||||
let sourceKeyB = SourceStringKey(name: "legacy.aggregate.b", domain: .userDefaults(suite: nil))
|
||||
let destinationKey = DestinationStringKey(name: "modern.aggregate", domain: .userDefaults(suite: nil))
|
||||
let sourceKeyA = makeSourceStringKey(name: "legacy.aggregate.a", domain: .userDefaults(suite: nil))
|
||||
let sourceKeyB = makeSourceStringKey(name: "legacy.aggregate.b", domain: .userDefaults(suite: nil))
|
||||
let destinationKey = makeDestinationStringKey(name: "modern.aggregate", domain: .userDefaults(suite: nil))
|
||||
|
||||
try await router.set("alpha", for: sourceKeyA)
|
||||
try await router.set("beta", for: sourceKeyB)
|
||||
@ -151,7 +149,7 @@ struct MigrationProtocolTests {
|
||||
}
|
||||
|
||||
@Test func migrationErrorHandlingTest() async throws {
|
||||
let destinationKey = DestinationStringKey(name: "modern.error", domain: .userDefaults(suite: nil))
|
||||
let destinationKey = makeDestinationStringKey(name: "modern.error", domain: .userDefaults(suite: nil))
|
||||
let migration = FailingMigration(destinationKey: destinationKey, error: .transformationFailed("Failed"))
|
||||
let result = try await migration.migrate(using: router, context: MigrationContext())
|
||||
|
||||
|
||||
@ -2,42 +2,34 @@ import Foundation
|
||||
import Testing
|
||||
@testable import LocalData
|
||||
|
||||
private struct LegacyKey: StorageKey {
|
||||
typealias Value = String
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy = .none
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "Legacy"
|
||||
let description: String = "Legacy key"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
private func makeLegacyKey(name: String, domain: StorageDomain) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: domain,
|
||||
security: .none,
|
||||
owner: "Legacy",
|
||||
description: "Legacy key"
|
||||
)
|
||||
}
|
||||
|
||||
private struct ModernKey: StorageKey {
|
||||
typealias Value = String
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy = .keychain(accessibility: .afterFirstUnlock, accessControl: .none)
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "Modern"
|
||||
let description: String = "Modern key"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
let legacyKey: AnyStorageKey?
|
||||
|
||||
init(name: String, domain: StorageDomain, legacyKey: AnyStorageKey?) {
|
||||
self.name = name
|
||||
self.domain = domain
|
||||
self.legacyKey = legacyKey
|
||||
}
|
||||
|
||||
var migration: AnyStorageMigration? {
|
||||
guard let legacyKey else { return nil }
|
||||
return AnyStorageMigration(
|
||||
SimpleLegacyMigration(destinationKey: self, sourceKey: legacyKey)
|
||||
)
|
||||
}
|
||||
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)
|
||||
@ -65,7 +57,7 @@ struct MigrationTests {
|
||||
}
|
||||
|
||||
// 1. Setup legacy data manually in UserDefaults
|
||||
let legacyKey = LegacyKey(name: legacyName, domain: .userDefaults(suite: suiteName))
|
||||
let legacyKey = makeLegacyKey(name: legacyName, domain: .userDefaults(suite: suiteName))
|
||||
try await router.set(secretValue, for: legacyKey)
|
||||
|
||||
// Verify it exists in legacy location
|
||||
@ -73,7 +65,7 @@ struct MigrationTests {
|
||||
#expect(existsInLegacy == true)
|
||||
|
||||
// 2. Setup modern key with legacy source
|
||||
let modernKey = ModernKey(
|
||||
let modernKey = makeModernKey(
|
||||
name: modernName,
|
||||
domain: .keychain(service: "test.migration"),
|
||||
legacyKey: .key(legacyKey)
|
||||
@ -104,11 +96,11 @@ struct MigrationTests {
|
||||
}
|
||||
|
||||
// 1. Setup legacy data
|
||||
let legacyKey = LegacyKey(name: legacyName, domain: .userDefaults(suite: suiteName))
|
||||
let legacyKey = makeLegacyKey(name: legacyName, domain: .userDefaults(suite: suiteName))
|
||||
try await router.set(value, for: legacyKey)
|
||||
|
||||
// 2. Setup modern key
|
||||
let modernKey = ModernKey(
|
||||
let modernKey = makeModernKey(
|
||||
name: modernName,
|
||||
domain: .userDefaults(suite: suiteName),
|
||||
legacyKey: .key(legacyKey)
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
import Foundation
|
||||
@testable import LocalData
|
||||
|
||||
struct MockMigration<Destination: StorageKey>: StorageMigration {
|
||||
typealias DestinationKey = Destination
|
||||
|
||||
let destinationKey: Destination
|
||||
struct MockMigration<Value: Codable & Sendable>: StorageMigration {
|
||||
let destinationKey: StorageKey<Value>
|
||||
let shouldSucceed: Bool
|
||||
let shouldMigrateResult: Bool
|
||||
let migrationDelay: TimeInterval
|
||||
@ -28,10 +26,8 @@ struct MockMigration<Destination: StorageKey>: StorageMigration {
|
||||
}
|
||||
}
|
||||
|
||||
struct FailingMigration<Destination: StorageKey>: StorageMigration {
|
||||
typealias DestinationKey = Destination
|
||||
|
||||
let destinationKey: Destination
|
||||
struct FailingMigration<Value: Codable & Sendable>: StorageMigration {
|
||||
let destinationKey: StorageKey<Value>
|
||||
let error: MigrationError
|
||||
|
||||
func shouldMigrate(using router: StorageRouter, context: MigrationContext) async throws -> Bool { true }
|
||||
|
||||
@ -2,39 +2,35 @@ import Foundation
|
||||
import Testing
|
||||
@testable import LocalData
|
||||
|
||||
private struct TestRegistryKey: StorageKey {
|
||||
typealias Value = String
|
||||
let name: String
|
||||
let domain: StorageDomain = .userDefaults(suite: nil)
|
||||
let security: SecurityPolicy = .none
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String
|
||||
let description: String
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
|
||||
init(name: String, owner: String = "Test", description: String = "Test") {
|
||||
self.name = name
|
||||
self.owner = owner
|
||||
self.description = description
|
||||
}
|
||||
private func makeRegistryKey(
|
||||
name: String,
|
||||
owner: String = "Test",
|
||||
description: String = "Test"
|
||||
) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: .userDefaults(suite: nil),
|
||||
security: .none,
|
||||
owner: owner,
|
||||
description: description
|
||||
)
|
||||
}
|
||||
|
||||
private struct CatalogA: StorageKeyCatalog {
|
||||
var allKeys: [AnyStorageKey] {
|
||||
[.key(TestRegistryKey(name: "key.a", owner: "ModuleA"))]
|
||||
[.key(makeRegistryKey(name: "key.a", owner: "ModuleA"))]
|
||||
}
|
||||
}
|
||||
|
||||
private struct CatalogB: StorageKeyCatalog {
|
||||
var allKeys: [AnyStorageKey] {
|
||||
[.key(TestRegistryKey(name: "key.b", owner: "ModuleB"))]
|
||||
[.key(makeRegistryKey(name: "key.b", owner: "ModuleB"))]
|
||||
}
|
||||
}
|
||||
|
||||
private struct CatalogCollision: StorageKeyCatalog {
|
||||
var allKeys: [AnyStorageKey] {
|
||||
[.key(TestRegistryKey(name: "key.a", owner: "ModuleCollision"))]
|
||||
[.key(makeRegistryKey(name: "key.a", owner: "ModuleCollision"))]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,26 +16,22 @@ import Testing
|
||||
)
|
||||
}
|
||||
|
||||
private struct DomainKey: StorageKey {
|
||||
typealias Value = String
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "DomainTests"
|
||||
let description: String = "Domain test key"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
|
||||
init(name: String, domain: StorageDomain, security: SecurityPolicy = .none) {
|
||||
self.name = name
|
||||
self.domain = domain
|
||||
self.security = security
|
||||
}
|
||||
private func makeDomainKey(
|
||||
name: String,
|
||||
domain: StorageDomain,
|
||||
security: SecurityPolicy = .none
|
||||
) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: domain,
|
||||
security: security,
|
||||
owner: "DomainTests",
|
||||
description: "Domain test key"
|
||||
)
|
||||
}
|
||||
|
||||
@Test func domainUserDefaults() async throws {
|
||||
let key = DomainKey(name: "defaults.key", domain: .userDefaults(suite: nil))
|
||||
let key = makeDomainKey(name: "defaults.key", domain: .userDefaults(suite: nil))
|
||||
try await router.set("value", for: key)
|
||||
#expect(try await router.get(key) == "value")
|
||||
try await router.remove(key)
|
||||
@ -46,14 +42,14 @@ import Testing
|
||||
// We use a mock configuration to avoid requiring a real app group
|
||||
await router.updateStorageConfiguration(StorageConfiguration(defaultAppGroupIdentifier: "group.test"))
|
||||
|
||||
let key = DomainKey(name: "appgroup.defaults.key", domain: .appGroupUserDefaults(identifier: "group.test"))
|
||||
let key = makeDomainKey(name: "appgroup.defaults.key", domain: .appGroupUserDefaults(identifier: "group.test"))
|
||||
try await router.set("value", for: key)
|
||||
#expect(try await router.get(key) == "value")
|
||||
try await router.remove(key)
|
||||
}
|
||||
|
||||
@Test func domainKeychain() async throws {
|
||||
let key = DomainKey(
|
||||
let key = makeDomainKey(
|
||||
name: "keychain.key",
|
||||
domain: .keychain(service: "test"),
|
||||
security: .keychain(accessibility: .afterFirstUnlock, accessControl: .none)
|
||||
@ -64,14 +60,14 @@ import Testing
|
||||
}
|
||||
|
||||
@Test func domainFileSystem() async throws {
|
||||
let key = DomainKey(name: "file.key", domain: .fileSystem(directory: .documents))
|
||||
let key = makeDomainKey(name: "file.key", domain: .fileSystem(directory: .documents))
|
||||
try await router.set("value", for: key)
|
||||
#expect(try await router.get(key) == "value")
|
||||
try await router.remove(key)
|
||||
}
|
||||
|
||||
@Test func domainEncryptedFileSystem() async throws {
|
||||
let key = DomainKey(name: "encfile.key", domain: .encryptedFileSystem(directory: .documents))
|
||||
let key = makeDomainKey(name: "encfile.key", domain: .encryptedFileSystem(directory: .documents))
|
||||
try await router.set("value", for: key)
|
||||
#expect(try await router.get(key) == "value")
|
||||
try await router.remove(key)
|
||||
@ -80,7 +76,10 @@ import Testing
|
||||
@Test func domainAppGroupFileSystem() async throws {
|
||||
// App blocks usually fail or return nil in tests, but we exercise the path
|
||||
await router.updateStorageConfiguration(StorageConfiguration(defaultAppGroupIdentifier: "group.test"))
|
||||
let key = DomainKey(name: "appgroup.file.key", domain: .appGroupFileSystem(identifier: "group.test", directory: .documents))
|
||||
let key = makeDomainKey(
|
||||
name: "appgroup.file.key",
|
||||
domain: .appGroupFileSystem(identifier: "group.test", directory: .documents)
|
||||
)
|
||||
|
||||
do {
|
||||
try await router.set("value", for: key)
|
||||
@ -94,7 +93,7 @@ import Testing
|
||||
@Test func resolutionFailureService() async throws {
|
||||
// Clear default service
|
||||
await router.updateStorageConfiguration(StorageConfiguration(defaultKeychainService: nil))
|
||||
let key = DomainKey(
|
||||
let key = makeDomainKey(
|
||||
name: "bad.service.key",
|
||||
domain: .keychain(service: nil),
|
||||
security: .keychain(accessibility: .afterFirstUnlock, accessControl: .none)
|
||||
@ -108,7 +107,7 @@ import Testing
|
||||
@Test func resolutionFailureIdentifier() async throws {
|
||||
// Clear default identifier
|
||||
await router.updateStorageConfiguration(StorageConfiguration(defaultAppGroupIdentifier: nil))
|
||||
let key = DomainKey(name: "bad.id.key", domain: .appGroupUserDefaults(identifier: nil))
|
||||
let key = makeDomainKey(name: "bad.id.key", domain: .appGroupUserDefaults(identifier: nil))
|
||||
|
||||
await #expect(throws: StorageError.invalidAppGroupIdentifier("none")) {
|
||||
try await router.set("value", for: key)
|
||||
|
||||
@ -2,21 +2,19 @@ import Foundation
|
||||
import Testing
|
||||
@testable import LocalData
|
||||
|
||||
private struct MockKey: StorageKey {
|
||||
typealias Value = String
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy = .none
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "ErrorTests"
|
||||
let description: String = "Test key"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
private func makeMockKey(name: String, domain: StorageDomain) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: domain,
|
||||
security: .none,
|
||||
owner: "ErrorTests",
|
||||
description: "Test key"
|
||||
)
|
||||
}
|
||||
|
||||
private struct PartialCatalog: StorageKeyCatalog {
|
||||
var allKeys: [AnyStorageKey] {
|
||||
[.key(MockKey(name: "registered.key", domain: .userDefaults(suite: nil)))]
|
||||
[.key(makeMockKey(name: "registered.key", domain: .userDefaults(suite: nil)))]
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,7 +35,7 @@ struct RouterErrorTests {
|
||||
@Test func unregisteredKeyThrows() async throws {
|
||||
try await router.registerCatalog(PartialCatalog())
|
||||
|
||||
let badKey = MockKey(name: "unregistered.key", domain: .userDefaults(suite: nil))
|
||||
let badKey = makeMockKey(name: "unregistered.key", domain: .userDefaults(suite: nil))
|
||||
|
||||
await #expect(throws: StorageError.unregisteredKey("unregistered.key")) {
|
||||
try await router.set("value", for: badKey)
|
||||
@ -51,7 +49,7 @@ struct RouterErrorTests {
|
||||
defaultAppGroupIdentifier: nil
|
||||
))
|
||||
|
||||
let appGroupKey = MockKey(name: "appgroup.key", domain: .appGroupUserDefaults(identifier: nil))
|
||||
let appGroupKey = makeMockKey(name: "appgroup.key", domain: .appGroupUserDefaults(identifier: nil))
|
||||
|
||||
await #expect(throws: StorageError.invalidAppGroupIdentifier("none")) {
|
||||
try await router.set("value", for: appGroupKey)
|
||||
@ -65,7 +63,7 @@ struct RouterErrorTests {
|
||||
defaultAppGroupIdentifier: "test"
|
||||
))
|
||||
|
||||
let _ = MockKey(name: "keychain.key", domain: .keychain(service: nil))
|
||||
let _ = makeMockKey(name: "keychain.key", domain: .keychain(service: nil))
|
||||
|
||||
// Note: Keychain security policy must match keychain domain in descriptor
|
||||
// but descriptor is usually created from key.
|
||||
|
||||
@ -17,20 +17,22 @@ import Security
|
||||
)
|
||||
}
|
||||
|
||||
private struct SecurityKey: StorageKey {
|
||||
typealias Value = String
|
||||
let name: String
|
||||
let domain: StorageDomain
|
||||
let security: SecurityPolicy
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "SecurityTests"
|
||||
let description: String = "Security test key"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
private func makeSecurityKey(
|
||||
name: String,
|
||||
domain: StorageDomain,
|
||||
security: SecurityPolicy
|
||||
) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: domain,
|
||||
security: security,
|
||||
owner: "SecurityTests",
|
||||
description: "Security test key"
|
||||
)
|
||||
}
|
||||
|
||||
@Test func applySecurityNone() async throws {
|
||||
let key = SecurityKey(name: "none.key", domain: .userDefaults(suite: nil), security: .none)
|
||||
let key = makeSecurityKey(name: "none.key", domain: .userDefaults(suite: nil), security: .none)
|
||||
let value = "test-value"
|
||||
|
||||
try await router.set(value, for: key)
|
||||
@ -39,7 +41,7 @@ import Security
|
||||
}
|
||||
|
||||
@Test func applySecurityEncryptedAES() async throws {
|
||||
let key = SecurityKey(
|
||||
let key = makeSecurityKey(
|
||||
name: "aes.key",
|
||||
domain: .userDefaults(suite: nil),
|
||||
security: .encrypted(.aes256(keyDerivation: .hkdf()))
|
||||
@ -52,7 +54,7 @@ import Security
|
||||
}
|
||||
|
||||
@Test func applySecurityEncryptedChaCha() async throws {
|
||||
let key = SecurityKey(
|
||||
let key = makeSecurityKey(
|
||||
name: "chacha.key",
|
||||
domain: .userDefaults(suite: nil),
|
||||
security: .encrypted(.chacha20Poly1305(keyDerivation: .hkdf()))
|
||||
@ -65,7 +67,7 @@ import Security
|
||||
}
|
||||
|
||||
@Test func applySecurityKeychain() async throws {
|
||||
let key = SecurityKey(
|
||||
let key = makeSecurityKey(
|
||||
name: "keychain.key",
|
||||
domain: .keychain(service: "test-service"),
|
||||
security: .keychain(accessibility: .afterFirstUnlock, accessControl: .none)
|
||||
@ -78,7 +80,7 @@ import Security
|
||||
}
|
||||
|
||||
@Test func applySecurityPBKDF2() async throws {
|
||||
let key = SecurityKey(
|
||||
let key = makeSecurityKey(
|
||||
name: "pbkdf2.key",
|
||||
domain: .userDefaults(suite: nil),
|
||||
security: .encrypted(.aes256(keyDerivation: .pbkdf2()))
|
||||
|
||||
@ -4,22 +4,14 @@ import Testing
|
||||
|
||||
// MARK: - Test Keys
|
||||
|
||||
private struct TestCatalogKey: StorageKey {
|
||||
typealias Value = String
|
||||
|
||||
let name: String
|
||||
let domain: StorageDomain = .userDefaults(suite: nil)
|
||||
let security: SecurityPolicy = .none
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "CatalogTests"
|
||||
let description: String
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
|
||||
init(name: String, description: String = "Test key") {
|
||||
self.name = name
|
||||
self.description = description
|
||||
}
|
||||
private func makeCatalogKey(name: String, description: String = "Test key") -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: .userDefaults(suite: nil),
|
||||
security: .none,
|
||||
owner: "CatalogTests",
|
||||
description: description
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Test Catalogs
|
||||
@ -27,8 +19,8 @@ private struct TestCatalogKey: StorageKey {
|
||||
private struct ValidCatalog: StorageKeyCatalog {
|
||||
var allKeys: [AnyStorageKey] {
|
||||
[
|
||||
.key(TestCatalogKey(name: "valid.key1", description: "First test key")),
|
||||
.key(TestCatalogKey(name: "valid.key2", description: "Second test key"))
|
||||
.key(makeCatalogKey(name: "valid.key1", description: "First test key")),
|
||||
.key(makeCatalogKey(name: "valid.key2", description: "Second test key"))
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -36,8 +28,8 @@ private struct ValidCatalog: StorageKeyCatalog {
|
||||
private struct DuplicateNameCatalog: StorageKeyCatalog {
|
||||
var allKeys: [AnyStorageKey] {
|
||||
[
|
||||
.key(TestCatalogKey(name: "duplicate.name", description: "First instance")),
|
||||
.key(TestCatalogKey(name: "duplicate.name", description: "Second instance"))
|
||||
.key(makeCatalogKey(name: "duplicate.name", description: "First instance")),
|
||||
.key(makeCatalogKey(name: "duplicate.name", description: "Second instance"))
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -49,7 +41,7 @@ private struct EmptyCatalog: StorageKeyCatalog {
|
||||
private struct MissingDescriptionCatalog: StorageKeyCatalog {
|
||||
var allKeys: [AnyStorageKey] {
|
||||
[
|
||||
.key(TestCatalogKey(name: "missing.desc", description: " "))
|
||||
.key(makeCatalogKey(name: "missing.desc", description: " "))
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -78,7 +70,7 @@ struct StorageCatalogTests {
|
||||
}
|
||||
|
||||
@Test func descriptorCapturesKeyMetadata() {
|
||||
let key = TestCatalogKey(name: "metadata.test", description: "Metadata test key")
|
||||
let key = makeCatalogKey(name: "metadata.test", description: "Metadata test key")
|
||||
let anyKey = AnyStorageKey.key(key)
|
||||
let descriptor = anyKey.descriptor
|
||||
|
||||
|
||||
@ -4,19 +4,13 @@ import Testing
|
||||
|
||||
@Suite struct StorageKeyDefaultsTests {
|
||||
|
||||
private struct MinimalKey: StorageKey {
|
||||
typealias Value = Int
|
||||
let name: String = "minimal.key"
|
||||
let domain: StorageDomain = .userDefaults(suite: nil)
|
||||
let serializer: Serializer<Int> = .json
|
||||
let owner: String = "Test"
|
||||
let description: String = "Test"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .never
|
||||
}
|
||||
|
||||
@Test func defaultSecurityPolicyIsRecommended() {
|
||||
let key = MinimalKey()
|
||||
let key = StorageKey<Int>(
|
||||
name: "minimal.key",
|
||||
domain: .userDefaults(suite: nil),
|
||||
owner: "Test",
|
||||
description: "Test"
|
||||
)
|
||||
// This exercises the default implementation in StorageKey+Defaults.swift
|
||||
#expect(key.security == .recommended)
|
||||
}
|
||||
|
||||
@ -16,21 +16,20 @@ struct SyncIntegrationTests {
|
||||
)
|
||||
}
|
||||
|
||||
private struct SyncKey: StorageKey {
|
||||
typealias Value = String
|
||||
let name: String
|
||||
let domain: StorageDomain = .userDefaults(suite: nil)
|
||||
let security: SecurityPolicy = .none
|
||||
let serializer: Serializer<String> = .json
|
||||
let owner: String = "SyncTests"
|
||||
let description: String = "Sync key"
|
||||
let availability: PlatformAvailability = .all
|
||||
let syncPolicy: SyncPolicy = .automaticSmall
|
||||
private static func makeSyncKey(name: String) -> StorageKey<String> {
|
||||
StorageKey(
|
||||
name: name,
|
||||
domain: .userDefaults(suite: nil),
|
||||
security: .none,
|
||||
owner: "SyncTests",
|
||||
description: "Sync key",
|
||||
syncPolicy: .automaticSmall
|
||||
)
|
||||
}
|
||||
|
||||
private struct SyncCatalog: StorageKeyCatalog {
|
||||
var allKeys: [AnyStorageKey] {
|
||||
[.key(SyncKey(name: "sync.test.key"))]
|
||||
[.key(SyncIntegrationTests.makeSyncKey(name: "sync.test.key"))]
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,7 +45,7 @@ struct SyncIntegrationTests {
|
||||
try await router.updateFromSync(keyName: keyName, data: data)
|
||||
|
||||
// 3. Verify it was stored in the local domain
|
||||
let retrieved: String? = try await router.get(SyncKey(name: keyName))
|
||||
let retrieved: String? = try await router.get(Self.makeSyncKey(name: keyName))
|
||||
#expect(retrieved == expectedValue)
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"configurations" : [
|
||||
{
|
||||
"id" : "D2951487-F388-4A07-A1E8-3A4B179619B9",
|
||||
"id" : "CB38B4BA-86AE-457E-B74C-31A492DEB330",
|
||||
"name" : "Configuration 1",
|
||||
"options" : {
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user