101 lines
3.5 KiB
Swift
101 lines
3.5 KiB
Swift
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 struct CatalogA: StorageKeyCatalog {
|
|
var allKeys: [AnyStorageKey] {
|
|
[.key(TestRegistryKey(name: "key.a", owner: "ModuleA"))]
|
|
}
|
|
}
|
|
|
|
private struct CatalogB: StorageKeyCatalog {
|
|
var allKeys: [AnyStorageKey] {
|
|
[.key(TestRegistryKey(name: "key.b", owner: "ModuleB"))]
|
|
}
|
|
}
|
|
|
|
private struct CatalogCollision: StorageKeyCatalog {
|
|
var allKeys: [AnyStorageKey] {
|
|
[.key(TestRegistryKey(name: "key.a", owner: "ModuleCollision"))]
|
|
}
|
|
}
|
|
|
|
@Suite(.serialized)
|
|
struct ModularRegistryTests {
|
|
|
|
@Test func testAdditiveRegistration() async throws {
|
|
let router = StorageRouter(keychain: MockKeychainHelper())
|
|
|
|
try await router.registerCatalog(CatalogA())
|
|
#expect(await router.allRegisteredEntries().count == 1)
|
|
#expect(await router.allRegisteredEntries().contains { $0.descriptor.name == "key.a" })
|
|
|
|
try await router.registerCatalog(CatalogB())
|
|
#expect(await router.allRegisteredEntries().count == 2)
|
|
#expect(await router.allRegisteredEntries().contains { $0.descriptor.name == "key.b" })
|
|
}
|
|
|
|
@Test func testCollisionDetectionAcrossCatalogs() async throws {
|
|
let router = StorageRouter(keychain: MockKeychainHelper())
|
|
|
|
try await router.registerCatalog(CatalogA())
|
|
|
|
await #expect(throws: StorageError.self) {
|
|
try await router.registerCatalog(CatalogCollision())
|
|
}
|
|
}
|
|
|
|
@Test func testGlobalAuditReport() async throws {
|
|
let router = StorageRouter(keychain: MockKeychainHelper())
|
|
|
|
try await router.registerCatalog(CatalogA())
|
|
try await router.registerCatalog(CatalogB())
|
|
|
|
// Note: StorageAuditReport.renderGlobalRegistry() uses the shared router.
|
|
// For testing isolation, we should probably add a parameter to it or
|
|
// rely on the shared instance if we can reset it.
|
|
// Since StorageRouter is a singleton-heavy actor, we use renderText directly on the router's entries.
|
|
|
|
let entries = await router.allRegisteredEntries()
|
|
let report = StorageAuditReport.renderText(entries)
|
|
|
|
#expect(report.contains("key.a"))
|
|
#expect(report.contains("key.b"))
|
|
#expect(report.contains("catalog=CatalogA"))
|
|
#expect(report.contains("catalog=CatalogB"))
|
|
#expect(report.contains("ModuleA"))
|
|
#expect(report.contains("ModuleB"))
|
|
}
|
|
|
|
@Test func testGlobalAuditReportGrouped() async throws {
|
|
let router = StorageRouter(keychain: MockKeychainHelper())
|
|
|
|
try await router.registerCatalog(CatalogA())
|
|
try await router.registerCatalog(CatalogB())
|
|
|
|
let catalogs = await router.allRegisteredCatalogs()
|
|
|
|
#expect(catalogs.count == 2)
|
|
#expect(catalogs["CatalogA"] != nil)
|
|
#expect(catalogs["CatalogB"] != nil)
|
|
}
|
|
}
|