import Foundation import Testing @testable import CodexBarCore @Suite(.serialized) struct CookieHeaderCacheTests { private struct WrongEntry: Codable { let value: String } @Test func `stores and loads entry`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let provider: UsageProvider = .codex let storedAt = Date(timeIntervalSince1970: 0) CookieHeaderCache.store( provider: provider, cookieHeader: "auth=abc", sourceLabel: "Chrome", now: storedAt) let loaded = CookieHeaderCache.load(provider: provider) defer { CookieHeaderCache.clear(provider: provider) } #expect(loaded?.cookieHeader == "auth=abc") #expect(loaded?.sourceLabel == "Chrome") #expect(loaded?.storedAt == storedAt) } @Test func `conditional mutation does not overwrite or clear a newer entry`() { self.withIsolatedCookieCache { CookieHeaderCache.store( provider: .claude, cookieHeader: "sessionKey=sk-ant-initial", sourceLabel: "Chrome") let loaded = CookieHeaderCache.load(provider: .claude) #expect(loaded != nil) guard let initial = loaded else { return } let renewed = CookieHeaderCache.storeIfCurrent( provider: .claude, expected: initial, cookieHeader: "sessionKey=sk-ant-newer", sourceLabel: "Chrome") let staleStore = CookieHeaderCache.storeIfCurrent( provider: .claude, expected: initial, cookieHeader: "sessionKey=sk-ant-older", sourceLabel: "Chrome") let staleClear = CookieHeaderCache.clearIfCurrent(provider: .claude, expected: initial) #expect(renewed) #expect(!staleStore) #expect(!staleClear) #expect(CookieHeaderCache.load(provider: .claude)?.cookieHeader == "sessionKey=sk-ant-newer") } } @Test func `conditional clear failure still permits replacing the same entry`() { self.withIsolatedCookieCache { CookieHeaderCache.store( provider: .claude, cookieHeader: "sessionKey=sk-ant-stale", sourceLabel: "Chrome") let loaded = CookieHeaderCache.load(provider: .claude) #expect(loaded != nil) guard let stale = loaded else { return } let cleared = KeychainCacheStore.withClearFailureStatusOverrideForTesting(errSecInteractionNotAllowed) { CookieHeaderCache.clearIfCurrent(provider: .claude, expected: stale) } let replaced = CookieHeaderCache.storeIfCurrent( provider: .claude, expected: stale, cookieHeader: "sessionKey=sk-ant-fresh", sourceLabel: "Safari") #expect(!cleared) #expect(replaced) #expect(CookieHeaderCache.load(provider: .claude)?.cookieHeader == "sessionKey=sk-ant-fresh") } } @Test func `conditional mutation recognizes a legacy entry after migration failure`() { self.withIsolatedCookieCache { let legacy = CookieHeaderCache.Entry( cookieHeader: "sessionKey=sk-ant-legacy", storedAt: Date(timeIntervalSince1970: 1), sourceLabel: "Chrome") CookieHeaderCache.store(legacy, to: CookieHeaderCache.legacyURLForTesting(provider: .claude)) let loaded = KeychainCacheStore.withStoreFailureStatusOverrideForTesting(errSecInteractionNotAllowed) { CookieHeaderCache.load(provider: .claude) } #expect(loaded?.cookieHeader == legacy.cookieHeader) guard let loaded else { return } let cleared = CookieHeaderCache.clearIfCurrent(provider: .claude, expected: loaded) let replaced = CookieHeaderCache.storeIfCurrent( provider: .claude, expected: nil, cookieHeader: "sessionKey=sk-ant-fresh", sourceLabel: "Safari") #expect(cleared) #expect(replaced) #expect(CookieHeaderCache.load(provider: .claude)?.cookieHeader == "sessionKey=sk-ant-fresh") } } @Test func `stores separate codex entries per managed account scope`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let provider: UsageProvider = .codex let accountA = UUID() let accountB = UUID() CookieHeaderCache.store( provider: provider, scope: .managedAccount(accountA), cookieHeader: "auth=account-a", sourceLabel: "Chrome") CookieHeaderCache.store( provider: provider, scope: .managedAccount(accountB), cookieHeader: "auth=account-b", sourceLabel: "Safari") defer { CookieHeaderCache.clear(provider: provider, scope: .managedAccount(accountA)) CookieHeaderCache.clear(provider: provider, scope: .managedAccount(accountB)) } #expect(CookieHeaderCache.load(provider: provider, scope: .managedAccount(accountA))? .cookieHeader == "auth=account-a") #expect(CookieHeaderCache.load(provider: provider, scope: .managedAccount(accountB))? .cookieHeader == "auth=account-b") #expect(CookieHeaderCache.load(provider: provider)?.cookieHeader == nil) } @Test func `profile home scopes isolate same email sessions without exposing paths`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let provider: UsageProvider = .codex let profileA = CookieHeaderCache.Scope.profileHome("/tmp/codex-profile-a") let profileB = CookieHeaderCache.Scope.profileHome("/tmp/codex-profile-b") CookieHeaderCache.store( provider: provider, scope: profileA, cookieHeader: "auth=profile-a", sourceLabel: "Chrome") CookieHeaderCache.store( provider: provider, scope: profileB, cookieHeader: "auth=profile-b", sourceLabel: "Chrome") defer { CookieHeaderCache.clear(provider: provider, scope: profileA) CookieHeaderCache.clear(provider: provider, scope: profileB) } #expect(CookieHeaderCache.load(provider: provider, scope: profileA)?.cookieHeader == "auth=profile-a") #expect(CookieHeaderCache.load(provider: provider, scope: profileB)?.cookieHeader == "auth=profile-b") #expect(CookieHeaderCache.load(provider: provider) == nil) #expect(profileA.isolationIdentifier != profileB.isolationIdentifier) #expect(!profileA.isolationIdentifier.contains("codex-profile-a")) } @Test func `provider global scope remains available without managed account`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let provider: UsageProvider = .codex CookieHeaderCache.store( provider: provider, cookieHeader: "auth=system", sourceLabel: "Chrome") defer { CookieHeaderCache.clear(provider: provider) } #expect(CookieHeaderCache.load(provider: provider)?.cookieHeader == "auth=system") #expect(CookieHeaderCache.load(provider: provider, scope: .managedAccount(UUID())) == nil) } @Test func `claude cookie scopes isolate browser cache from managed accounts`() { self.withIsolatedCookieCache { let accountA = UUID() let accountB = UUID() CookieHeaderCache.store( provider: .claude, cookieHeader: "sessionKey=sk-ant-browser", sourceLabel: "Safari") CookieHeaderCache.store( provider: .claude, scope: .managedAccount(accountA), cookieHeader: "sessionKey=sk-ant-account-a", sourceLabel: "Chrome") CookieHeaderCache.store( provider: .claude, scope: .managedAccount(accountB), cookieHeader: "sessionKey=sk-ant-account-b", sourceLabel: "Edge") #expect(CookieHeaderCache.load(provider: .claude)?.cookieHeader == "sessionKey=sk-ant-browser") #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountA))? .cookieHeader == "sessionKey=sk-ant-account-a") #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountB))? .cookieHeader == "sessionKey=sk-ant-account-b") CookieHeaderCache.clear(provider: .claude) #expect(CookieHeaderCache.load(provider: .claude) == nil) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountA))? .cookieHeader == "sessionKey=sk-ant-account-a") #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountB))? .cookieHeader == "sessionKey=sk-ant-account-b") CookieHeaderCache.clear(provider: .claude, scope: .managedAccount(accountA)) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountA)) == nil) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountB))? .cookieHeader == "sessionKey=sk-ant-account-b") } } @Test func `claude unreadable managed store sentinel is isolated from account cookies`() { self.withIsolatedCookieCache { let accountID = UUID() CookieHeaderCache.store( provider: .claude, cookieHeader: "sessionKey=sk-ant-global", sourceLabel: "Safari") CookieHeaderCache.store( provider: .claude, scope: .managedAccount(accountID), cookieHeader: "sessionKey=sk-ant-account", sourceLabel: "Chrome") CookieHeaderCache.store( provider: .claude, scope: .managedStoreUnreadable, cookieHeader: "sessionKey=sk-ant-unreadable-store", sourceLabel: "Unreadable managed account store") CookieHeaderCache.clear(provider: .claude, scope: .managedAccount(accountID)) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(accountID)) == nil) #expect(CookieHeaderCache.load(provider: .claude)?.cookieHeader == "sessionKey=sk-ant-global") #expect(CookieHeaderCache.load(provider: .claude, scope: .managedStoreUnreadable)? .cookieHeader == "sessionKey=sk-ant-unreadable-store") CookieHeaderCache.clear(provider: .claude) #expect(CookieHeaderCache.load(provider: .claude) == nil) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedStoreUnreadable)? .cookieHeader == "sessionKey=sk-ant-unreadable-store") let cleared = CookieHeaderCache.clearAllScopesDetailed(provider: .claude) #expect(cleared == CookieHeaderCache.ClearSummary(clearedCount: 1, failedCount: 0)) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedStoreUnreadable) == nil) } } @Test func `claude clear all scopes does not remove other provider cookie caches`() { self.withIsolatedCookieCache { let claudeAccount = UUID() let codexAccount = UUID() CookieHeaderCache.store( provider: .claude, cookieHeader: "sessionKey=sk-ant-claude-global", sourceLabel: "Safari") CookieHeaderCache.store( provider: .claude, scope: .managedAccount(claudeAccount), cookieHeader: "sessionKey=sk-ant-claude-account", sourceLabel: "Chrome") CookieHeaderCache.store(provider: .codex, cookieHeader: "auth=codex-global", sourceLabel: "Chrome") CookieHeaderCache.store( provider: .codex, scope: .managedAccount(codexAccount), cookieHeader: "auth=codex-account", sourceLabel: "Safari") CookieHeaderCache.store(provider: .perplexity, cookieHeader: "pplx=web", sourceLabel: "Chrome") let cleared = CookieHeaderCache.clearAllScopesDetailed(provider: .claude) #expect(cleared == CookieHeaderCache.ClearSummary(clearedCount: 2, failedCount: 0)) #expect(CookieHeaderCache.load(provider: .claude) == nil) #expect(CookieHeaderCache.load(provider: .claude, scope: .managedAccount(claudeAccount)) == nil) #expect(CookieHeaderCache.load(provider: .codex)?.cookieHeader == "auth=codex-global") #expect(CookieHeaderCache.load(provider: .codex, scope: .managedAccount(codexAccount))? .cookieHeader == "auth=codex-account") #expect(CookieHeaderCache.load(provider: .perplexity)?.cookieHeader == "pplx=web") } } @Test func `migrates legacy file to keychain`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex let storedAt = Date(timeIntervalSince1970: 0) let entry = CookieHeaderCache.Entry( cookieHeader: "auth=legacy", storedAt: storedAt, sourceLabel: "Legacy") let legacyURL = legacyBase.appendingPathComponent("\(provider.rawValue)-cookie.json") CookieHeaderCache.store(entry, to: legacyURL) #expect(FileManager.default.fileExists(atPath: legacyURL.path) == true) let loaded = CookieHeaderCache.load(provider: provider) defer { CookieHeaderCache.clear(provider: provider) } #expect(loaded?.cookieHeader == "auth=legacy") #expect(loaded?.sourceLabel == "Legacy") #expect(loaded?.storedAt == storedAt) #expect(FileManager.default.fileExists(atPath: legacyURL.path) == false) let loadedAgain = CookieHeaderCache.load(provider: provider) #expect(loadedAgain?.cookieHeader == "auth=legacy") } @Test func `serialized load migrates legacy file to keychain`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex let legacyURL = legacyBase.appendingPathComponent("\(provider.rawValue)-cookie.json") CookieHeaderCache.store( CookieHeaderCache.Entry( cookieHeader: "auth=legacy", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Legacy"), to: legacyURL) let loaded = CookieHeaderCache.loadSerialized(provider: provider) defer { CookieHeaderCache.clear(provider: provider) } #expect(loaded?.cookieHeader == "auth=legacy") #expect(FileManager.default.fileExists(atPath: legacyURL.path) == false) #expect(CookieHeaderCache.load(provider: provider)?.cookieHeader == "auth=legacy") } #if os(macOS) @Test func `temporary keychain unavailability returns nil without migrating legacy file`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex let legacyURL = legacyBase.appendingPathComponent("\(provider.rawValue)-cookie.json") CookieHeaderCache.store( CookieHeaderCache.Entry( cookieHeader: "auth=legacy", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Legacy"), to: legacyURL) #expect(FileManager.default.fileExists(atPath: legacyURL.path) == true) let loaded = KeychainCacheStore.withLoadFailureStatusOverrideForTesting(errSecInteractionNotAllowed) { CookieHeaderCache.load(provider: provider) } #expect(loaded == nil) #expect(FileManager.default.fileExists(atPath: legacyURL.path) == true) switch KeychainCacheStore.load(key: .cookie(provider: provider), as: CookieHeaderCache.Entry.self) { case .missing: #expect(true) case .found, .temporarilyUnavailable, .invalid: #expect(Bool(false), "Expected temporary miss not to migrate legacy cache") } } #endif @Test func `invalid keychain cache is cleared`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex let key = KeychainCacheStore.Key.cookie(provider: provider) KeychainCacheStore.store(key: key, entry: WrongEntry(value: "not-a-cookie-entry")) #expect(CookieHeaderCache.load(provider: provider) == nil) switch KeychainCacheStore.load(key: key, as: CookieHeaderCache.Entry.self) { case .missing: #expect(true) case .found, .temporarilyUnavailable, .invalid: #expect(Bool(false), "Expected invalid cookie cache to be cleared") } } @Test func `clear all scopes removes global scoped invalid and legacy cookie entries`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex let accountID = UUID() CookieHeaderCache.store(provider: provider, cookieHeader: "auth=global", sourceLabel: "Chrome") CookieHeaderCache.store( provider: provider, scope: .managedAccount(accountID), cookieHeader: "auth=scoped", sourceLabel: "Chrome") KeychainCacheStore.store( key: .cookie(provider: provider, scopeIdentifier: "managed-store-unreadable"), entry: WrongEntry(value: "invalid")) CookieHeaderCache.store( CookieHeaderCache.Entry( cookieHeader: "auth=legacy", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Legacy"), to: CookieHeaderCache.legacyURLForTesting(provider: provider)) let cleared = CookieHeaderCache.clearAllScopesDetailed(provider: provider) #expect(cleared == CookieHeaderCache.ClearSummary(clearedCount: 4, failedCount: 0)) #expect(!CookieHeaderCache.hasKeychainEntryForTesting(provider: provider)) #expect(!CookieHeaderCache.hasKeychainEntryForTesting(provider: provider, scope: .managedAccount(accountID))) #expect(!CookieHeaderCache.hasKeychainEntryForTesting(provider: provider, scope: .managedStoreUnreadable)) #expect(!CookieHeaderCache.hasLegacyEntryForTesting(provider: provider)) } @Test func `loadForDisplay memoizes keychain lookups`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let provider: UsageProvider = .codex CookieHeaderCache.store(provider: provider, cookieHeader: "auth=abc", sourceLabel: "Chrome") #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=abc") // Remove the backing entry without going through CookieHeaderCache: the strict load // sees the change, the display path keeps serving the memoized snapshot. KeychainCacheStore.clear(key: .cookie(provider: provider)) #expect(CookieHeaderCache.load(provider: provider) == nil) #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=abc") } @Test func `loadForDisplay memoizes missing entries`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let provider: UsageProvider = .codex #expect(CookieHeaderCache.loadForDisplay(provider: provider) == nil) KeychainCacheStore.store( key: .cookie(provider: provider), entry: CookieHeaderCache.Entry( cookieHeader: "auth=behind-the-back", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Chrome")) defer { KeychainCacheStore.clear(key: .cookie(provider: provider)) } #expect(CookieHeaderCache.loadForDisplay(provider: provider) == nil) } @Test func `loadForDisplay migrates legacy cache asynchronously`() async throws { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex CookieHeaderCache.store( CookieHeaderCache.Entry( cookieHeader: "auth=legacy-display", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Legacy"), to: CookieHeaderCache.legacyURLForTesting(provider: provider)) #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=legacy-display") for _ in 0..<500 { if !CookieHeaderCache.hasLegacyEntryForTesting(provider: provider), CookieHeaderCache.hasKeychainEntryForTesting(provider: provider) { break } try await Task.sleep(for: .milliseconds(10)) } #expect(!CookieHeaderCache.hasLegacyEntryForTesting(provider: provider)) #expect(CookieHeaderCache.hasKeychainEntryForTesting(provider: provider)) CookieHeaderCache.clear(provider: provider) } @Test func `delayed legacy migration cannot restore a cleared cache`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex CookieHeaderCache.store( CookieHeaderCache.Entry( cookieHeader: "auth=legacy-display", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Legacy"), to: CookieHeaderCache.legacyURLForTesting(provider: provider)) CookieHeaderCache.clear(provider: provider) #expect(CookieHeaderCache.migrateLegacyEntryIfNeededForTesting(provider: provider) == nil) #expect(!CookieHeaderCache.hasLegacyEntryForTesting(provider: provider)) #expect(!CookieHeaderCache.hasKeychainEntryForTesting(provider: provider)) } @Test func `legacy URL override supports concurrent teardown reads`() { let legacyBases = [ FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true), FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true), ] defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } DispatchQueue.concurrentPerform(iterations: 5000) { index in if index.isMultiple(of: 3) { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBases[index % legacyBases.count]) } else if index.isMultiple(of: 5) { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } else { _ = CookieHeaderCache.legacyURLForTesting(provider: .codex) } } CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBases[0]) #expect( CookieHeaderCache.legacyURLForTesting(provider: .codex) == legacyBases[0].appendingPathComponent("codex-cookie.json")) } #if os(macOS) @Test func `loadForDisplay throttles temporary keychain unavailability then retries`() async throws { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } CookieHeaderCache.setDisplayUnavailableRetryIntervalOverrideForTesting(0.05) defer { CookieHeaderCache.setDisplayUnavailableRetryIntervalOverrideForTesting(nil) } let provider: UsageProvider = .codex KeychainCacheStore.store( key: .cookie(provider: provider), entry: CookieHeaderCache.Entry( cookieHeader: "auth=available-after-retry", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Chrome")) let unavailable = KeychainCacheStore.withLoadFailureStatusOverrideForTesting(errSecInteractionNotAllowed) { CookieHeaderCache.loadForDisplay(provider: provider) } #expect(unavailable == nil) #expect(CookieHeaderCache.loadForDisplay(provider: provider) == nil) try await Task.sleep(for: .milliseconds(60)) var retried: CookieHeaderCache.Entry? for _ in 0..<500 { retried = CookieHeaderCache.loadForDisplay(provider: provider) if retried != nil { break } try await Task.sleep(for: .milliseconds(10)) } #expect(retried?.cookieHeader == "auth=available-after-retry") } @Test func `temporary first display read returns a concurrent store`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let provider: UsageProvider = .codex _ = CookieHeaderCache.beginDisplayReadGenerationForTesting(provider: provider) CookieHeaderCache.store(provider: provider, cookieHeader: "auth=concurrent", sourceLabel: "Chrome") #expect(CookieHeaderCache.currentDisplayEntryForTesting(provider: provider)? .cookieHeader == "auth=concurrent") } @Test func `failed keychain mutations preserve the display snapshot`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let provider: UsageProvider = .codex CookieHeaderCache.store(provider: provider, cookieHeader: "auth=old", sourceLabel: "Chrome") #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=old") KeychainCacheStore.withStoreFailureStatusOverrideForTesting(errSecInteractionNotAllowed) { CookieHeaderCache.store(provider: provider, cookieHeader: "auth=new", sourceLabel: "Safari") } #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=old") let cleared = KeychainCacheStore.withClearFailureStatusOverrideForTesting(errSecInteractionNotAllowed) { CookieHeaderCache.clearDetailed(provider: provider) } #expect(cleared == CookieHeaderCache.ClearSummary(clearedCount: 0, failedCount: 1)) #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=old") #expect(CookieHeaderCache.load(provider: provider)?.cookieHeader == "auth=old") } @Test func `legacy removal invalidates a snapshot after failed keychain clear`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } KeychainCacheStore.withServiceOverrideForTesting("legacy-clear-\(UUID().uuidString)") { let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex CookieHeaderCache.store( CookieHeaderCache.Entry( cookieHeader: "auth=legacy", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Legacy"), to: CookieHeaderCache.legacyURLForTesting(provider: provider)) let displayed = KeychainCacheStore.withStoreFailureStatusOverrideForTesting(errSecInteractionNotAllowed) { CookieHeaderCache.loadForDisplay(provider: provider) } #expect(displayed?.cookieHeader == "auth=legacy") let cleared = KeychainCacheStore.withClearFailureStatusOverrideForTesting(errSecInteractionNotAllowed) { CookieHeaderCache.clearDetailed(provider: provider) } #expect(cleared == CookieHeaderCache.ClearSummary(clearedCount: 1, failedCount: 1)) #expect(!CookieHeaderCache.hasLegacyEntryForTesting(provider: provider)) #expect(CookieHeaderCache.loadForDisplay(provider: provider) == nil) } } @Test func `clear all reports keychain enumeration failure`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let summary = KeychainCacheStore.withKeysFailureStatusOverrideForTesting(errSecInteractionNotAllowed) { CookieHeaderCache.clearAllDetailed() } #expect(summary.failedCount >= 1) } @Test func `clear reports legacy file deletion failure`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } let provider: UsageProvider = .codex CookieHeaderCache.store( CookieHeaderCache.Entry( cookieHeader: "auth=legacy", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Legacy"), to: CookieHeaderCache.legacyURLForTesting(provider: provider)) let summary = CookieHeaderCache.withLegacyRemovalFailureForTesting { CookieHeaderCache.clearDetailed(provider: provider) } #expect(summary.failedCount == 1) #expect(CookieHeaderCache.hasLegacyEntryForTesting(provider: provider)) } #endif @Test func `store and clear update the display snapshot immediately`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let provider: UsageProvider = .codex CookieHeaderCache.store(provider: provider, cookieHeader: "auth=first", sourceLabel: "Chrome") #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=first") CookieHeaderCache.store(provider: provider, cookieHeader: "auth=second", sourceLabel: "Safari") #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=second") CookieHeaderCache.clear(provider: provider) #expect(CookieHeaderCache.loadForDisplay(provider: provider) == nil) } @Test func `stale refresh cannot overwrite a newer store`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let provider: UsageProvider = .codex CookieHeaderCache.store(provider: provider, cookieHeader: "auth=old", sourceLabel: "Chrome") #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=old") // A refresh scheduled now races with a store that lands before it commits. let staleGeneration = CookieHeaderCache.beginDisplayReadGenerationForTesting(provider: provider) let staleEntry = CookieHeaderCache.load(provider: provider) CookieHeaderCache.store(provider: provider, cookieHeader: "auth=new", sourceLabel: "Safari") let committed = CookieHeaderCache.commitDisplaySnapshotIfCurrentForTesting( provider: provider, entry: staleEntry, generation: staleGeneration) #expect(committed?.cookieHeader == "auth=new") #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=new") } @Test func `stale refresh cannot resurrect a cleared snapshot`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let provider: UsageProvider = .codex CookieHeaderCache.store(provider: provider, cookieHeader: "auth=secret", sourceLabel: "Chrome") #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=secret") let staleGeneration = CookieHeaderCache.beginDisplayReadGenerationForTesting(provider: provider) let staleEntry = CookieHeaderCache.load(provider: provider) CookieHeaderCache.clear(provider: provider) let committed = CookieHeaderCache.commitDisplaySnapshotIfCurrentForTesting( provider: provider, entry: staleEntry, generation: staleGeneration) #expect(committed == nil) #expect(CookieHeaderCache.loadForDisplay(provider: provider) == nil) } @Test func `stale refresh cannot survive clear all`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let provider: UsageProvider = .codex CookieHeaderCache.store(provider: provider, cookieHeader: "auth=secret", sourceLabel: "Chrome") #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=secret") let staleGeneration = CookieHeaderCache.beginDisplayReadGenerationForTesting(provider: provider) let staleEntry = CookieHeaderCache.load(provider: provider) CookieHeaderCache.clearAll() CookieHeaderCache.commitDisplaySnapshotIfCurrentForTesting( provider: provider, entry: staleEntry, generation: staleGeneration) #expect(CookieHeaderCache.loadForDisplay(provider: provider) == nil) } @Test func `clear all invalidates an in flight first display population`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } let provider: UsageProvider = .codex KeychainCacheStore.store( key: .cookie(provider: provider), entry: CookieHeaderCache.Entry( cookieHeader: "auth=secret", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Chrome")) // A first display load registers its key, then reads the Keychain outside the lock. let staleGeneration = CookieHeaderCache.beginDisplayReadGenerationForTesting(provider: provider) let staleEntry = CookieHeaderCache.load(provider: provider) CookieHeaderCache.clearAll() let committed = CookieHeaderCache.commitDisplaySnapshotIfCurrentForTesting( provider: provider, entry: staleEntry, generation: staleGeneration) #expect(committed == nil) #expect(CookieHeaderCache.loadForDisplay(provider: provider) == nil) } @Test func `stale display snapshot revalidates off the calling path`() async throws { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } CookieHeaderCache.setDisplayStalenessIntervalOverrideForTesting(0) defer { CookieHeaderCache.setDisplayStalenessIntervalOverrideForTesting(nil) } let provider: UsageProvider = .codex KeychainCacheStore.store( key: .cookie(provider: provider), entry: CookieHeaderCache.Entry( cookieHeader: "auth=old", storedAt: Date(timeIntervalSince1970: 0), sourceLabel: "Chrome")) #expect(CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=old") KeychainCacheStore.store( key: .cookie(provider: provider), entry: CookieHeaderCache.Entry( cookieHeader: "auth=new", storedAt: Date(timeIntervalSince1970: 1), sourceLabel: "Chrome")) // The stale lookup returns the old snapshot and schedules a revalidation. _ = CookieHeaderCache.loadForDisplay(provider: provider) var refreshed = false for _ in 0..<200 { if CookieHeaderCache.loadForDisplay(provider: provider)?.cookieHeader == "auth=new" { refreshed = true break } try await Task.sleep(nanoseconds: 10_000_000) } #expect(refreshed) } @Test func `clear all removes every provider cookie key without decoding entries`() { KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } KeychainCacheStore.withServiceOverrideForTesting("cookie-clear-all-\(UUID().uuidString)") { CookieHeaderCache.store(provider: .claude, cookieHeader: "auth=claude", sourceLabel: "Chrome") CookieHeaderCache.store( provider: .codex, scope: .managedAccount(UUID()), cookieHeader: "auth=codex", sourceLabel: "Chrome") KeychainCacheStore.store( key: .cookie(provider: .cursor), entry: WrongEntry(value: "invalid")) let cleared = CookieHeaderCache.clearAllDetailed() #expect(cleared.clearedCount >= 3) #expect(cleared.failedCount == 0) #expect(KeychainCacheStore.keys(category: "cookie").isEmpty) } } private func withIsolatedCookieCache(_ operation: () -> T) -> T { KeychainCacheStore.withServiceOverrideForTesting("cookie-isolation-\(UUID().uuidString)") { let legacyBase = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) CookieHeaderCache.setLegacyBaseURLOverrideForTesting(legacyBase) defer { CookieHeaderCache.setLegacyBaseURLOverrideForTesting(nil) } KeychainCacheStore.setTestStoreForTesting(true) defer { KeychainCacheStore.setTestStoreForTesting(false) } CookieHeaderCache.resetDisplayCacheForTesting() defer { CookieHeaderCache.resetDisplayCacheForTesting() } return operation() } } }