Files
2026-07-13 12:22:33 +08:00

932 lines
42 KiB
Swift

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<T>(_ 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()
}
}
}