LocalData/Tests/LocalDataTests/RouterDomainTests.swift

118 lines
4.8 KiB
Swift

import Foundation
import Testing
@testable import LocalData
@Suite struct RouterDomainTests {
private let router: StorageRouter
private let mockKeychain = MockKeychainHelper()
init() {
let testBaseURL = FileManager.default.temporaryDirectory.appending(path: "RouterDomainTests-\(UUID().uuidString)")
router = StorageRouter(
keychain: mockKeychain,
encryption: EncryptionHelper(keychain: mockKeychain),
file: FileStorageHelper(configuration: FileStorageConfiguration(baseURL: testBaseURL)),
defaults: UserDefaultsHelper(defaults: UserDefaults(suiteName: "RouterDomainTests-\(UUID().uuidString)")!)
)
}
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
}
}
@Test func domainUserDefaults() async throws {
let key = DomainKey(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)
#expect(await (try? router.exists(key)) == false)
}
@Test func domainAppGroupUserDefaults() async throws {
// 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"))
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(
name: "keychain.key",
domain: .keychain(service: "test"),
security: .keychain(accessibility: .afterFirstUnlock, accessControl: .none)
)
try await router.set("value", for: key)
#expect(try await router.get(key) == "value")
try await router.remove(key)
}
@Test func domainFileSystem() async throws {
let key = DomainKey(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))
try await router.set("value", for: key)
#expect(try await router.get(key) == "value")
try await router.remove(key)
}
@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))
do {
try await router.set("value", for: key)
#expect(try await router.get(key) == "value")
try await router.remove(key)
} catch StorageError.invalidAppGroupIdentifier {
// Path covered
}
}
@Test func resolutionFailureService() async throws {
// Clear default service
await router.updateStorageConfiguration(StorageConfiguration(defaultKeychainService: nil))
let key = DomainKey(
name: "bad.service.key",
domain: .keychain(service: nil),
security: .keychain(accessibility: .afterFirstUnlock, accessControl: .none)
)
await #expect(throws: StorageError.keychainError(errSecBadReq)) {
try await router.set("value", for: key)
}
}
@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))
await #expect(throws: StorageError.invalidAppGroupIdentifier("none")) {
try await router.set("value", for: key)
}
}
}