mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-24 22:45:19 +00:00
Isolate tests from the developer's real login keychain (#1413)
* Isolate tests from the developer's real login keychain Every test run prompted for the login keychain password (repeatedly, since the xctest runner's code signature changes each build, so "Always Allow" can never stick) and silently deleted the developer's real Nostr identity via panic-mode tests. Two holes let tests reach the real keychain: - NostrIdentityBridge() defaulted to the real KeychainManager. Tests inject mocks, but app-side constructions with no injection point (LocationNotesManager's static bridge, GeohashPresenceService, BoardManager, AppRuntime) read the real chat.bitchat.nostr item when exercised under test. - clearAllAssociations() used raw SecItem* calls that bypassed the injected keychain entirely, so panicClearAllData tests wiped the real Nostr identity items on every run. Fix: centralize FavoritesPersistenceService's test-guarded in-memory default as KeychainManager.makeDefault() and use it for all default keychain parameters, and add deleteAll(service:) to KeychainManagerProtocol so clearAllAssociations() goes through the injected keychain like every other operation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Share one in-memory test keychain per process (Codex P2) A fresh store per makeDefault() call diverges from production, where separate default-constructed bridges share chat.bitchat.nostr — BoardManager's publish and NIP-09 delete paths would derive different geohash identities under test. PreviewKeychainManager gains a lock since the shared instance is reached from arbitrary threads. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: jack <jackjackbits@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
jack
Claude Fable 5
parent
4baeaab717
commit
d499c3e415
@@ -34,6 +34,8 @@ public protocol KeychainManagerProtocol {
|
||||
func load(key: String, service: String) -> Data?
|
||||
/// Delete data from a custom service
|
||||
func delete(key: String, service: String)
|
||||
/// Delete every item stored under a custom service
|
||||
func deleteAll(service: String)
|
||||
}
|
||||
|
||||
// MARK: - Keychain Error Types
|
||||
|
||||
@@ -85,6 +85,10 @@ final class MockKeychain: KeychainManagerProtocol {
|
||||
func delete(key: String, service: String) {
|
||||
serviceStorage[service]?.removeValue(forKey: key)
|
||||
}
|
||||
|
||||
func deleteAll(service: String) {
|
||||
serviceStorage.removeValue(forKey: service)
|
||||
}
|
||||
}
|
||||
|
||||
/// Typealias for backwards compatibility with tests using MockKeychainHelper
|
||||
@@ -198,4 +202,8 @@ final class TrackingMockKeychain: KeychainManagerProtocol {
|
||||
func delete(key: String, service: String) {
|
||||
serviceStorage[service]?.removeValue(forKey: key)
|
||||
}
|
||||
|
||||
func deleteAll(service: String) {
|
||||
serviceStorage.removeValue(forKey: service)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user