847 lines · 38.2 KB · Swift
RawDownload
import Foundationimport 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 `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)

Lines 1–500 of 847.