1148 lines · 63.5 KB · Swift
RawDownload
import Foundationimport Testing@testable import CodexBar@testable import CodexBarCore struct ClaudeResilienceTests {    @Test    func `suppresses single flake when prior data exists`() {        var gate = ConsecutiveFailureGate()        let firstFailure = gate.shouldSurfaceError(onFailureWithPriorData: true)        let secondFailure = gate.shouldSurfaceError(onFailureWithPriorData: true)        #expect(firstFailure == false)        #expect(secondFailure == true)    }     @Test    func `surfaces failure without prior data`() {        var gate = ConsecutiveFailureGate()        let shouldSurface = gate.shouldSurfaceError(onFailureWithPriorData: false)        #expect(shouldSurface)    }     @Test    func `resets after success`() {        var gate = ConsecutiveFailureGate()        _ = gate.shouldSurfaceError(onFailureWithPriorData: true)        gate.recordSuccess()        let shouldSurface = gate.shouldSurfaceError(onFailureWithPriorData: true)        #expect(shouldSurface == false)    }     @Test    func `timeout keeps prior Claude snapshot without surfacing repeated failure`() async throws {        try await ClaudeOAuthCredentialsStore.withIsolatedCredentialsFileTrackingForTesting {            let tempDir = FileManager.default.temporaryDirectory                .appendingPathComponent(UUID().uuidString, isDirectory: true)            try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)            let fileURL = tempDir.appendingPathComponent("missing-credentials.json")             try await ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(fileURL) {                let (store, prior) = try await MainActor.run {                    let settings = Self.makeSettingsStore(suite: "ClaudeResilienceTests-timeout-cache")                    settings.refreshFrequency = .manual                    settings.statusChecksEnabled = false                    settings.claudeUsageDataSource = .cli                     let metadata = ProviderRegistry.shared.metadata                    for provider in UsageProvider.allCases {                        try settings.setProviderEnabled(                            provider: provider,                            metadata: #require(metadata[provider]),                            enabled: provider == .claude)                    }                     let store = UsageStore(                        fetcher: UsageFetcher(environment: [:]),                        browserDetection: BrowserDetection(cacheTTL: 0),                        settings: settings,                        startupBehavior: .testing,                        environmentBase: [:])                    let prior = UsageSnapshot(                        primary: RateWindow(usedPercent: 12, windowMinutes: 300, resetsAt: nil, resetDescription: nil),                        secondary: RateWindow(                            usedPercent: 34,                            windowMinutes: 10080,                            resetsAt: nil,                            resetDescription: nil),                        updatedAt: Date(timeIntervalSince1970: 1_800_000_000),                        identity: ProviderIdentitySnapshot(                            providerID: .claude,                            accountEmail: "claude@example.com",                            accountOrganization: nil,                            loginMethod: "Pro"))                    store._setSnapshotForTesting(prior, provider: .claude)                     let baseSpec = try #require(store.providerSpecs[.claude])                    let descriptor = ProviderDescriptor(                        id: .claude,                        metadata: baseSpec.descriptor.metadata,                        branding: baseSpec.descriptor.branding,                        tokenCost: baseSpec.descriptor.tokenCost,                        fetchPlan: ProviderFetchPlan(                            sourceModes: [.cli],                            pipeline: ProviderFetchPipeline { _ in [TimeoutFetchStrategy()] }),                        cli: baseSpec.descriptor.cli)                    store.providerSpecs[.claude] = ProviderSpec(                        style: baseSpec.style,                        isEnabled: baseSpec.isEnabled,                        descriptor: descriptor,                        makeFetchContext: baseSpec.makeFetchContext)                    return (store, prior)                }                 await store.refreshProvider(.claude)                let firstResult = await MainActor.run {                    (                        updatedAt: store.snapshot(for: .claude)?.updatedAt,                        hasError: store.error(for: .claude) != nil)                }                 #expect(firstResult.updatedAt == prior.updatedAt)                #expect(!firstResult.hasError)                 await store.refreshProvider(.claude)                let secondResult = await MainActor.run {                    (                        updatedAt: store.snapshot(for: .claude)?.updatedAt,                        hasError: store.error(for: .claude) != nil)                }                 #expect(secondResult.updatedAt == prior.updatedAt)                #expect(!secondResult.hasError)            }        }    }     @Test    func `repeated non probe transient failure still surfaces`() async throws {        try await ClaudeOAuthCredentialsStore.withIsolatedCredentialsFileTrackingForTesting {            let tempDir = FileManager.default.temporaryDirectory                .appendingPathComponent(UUID().uuidString, isDirectory: true)            try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)            let fileURL = tempDir.appendingPathComponent("missing-credentials.json")             try await ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(fileURL) {                let (store, prior) = try await MainActor.run {                    let settings = Self.makeSettingsStore(suite: "ClaudeResilienceTests-network-cache")                    settings.refreshFrequency = .manual                    settings.statusChecksEnabled = false                    settings.claudeUsageDataSource = .cli                     let metadata = ProviderRegistry.shared.metadata                    for provider in UsageProvider.allCases {                        try settings.setProviderEnabled(                            provider: provider,                            metadata: #require(metadata[provider]),                            enabled: provider == .claude)                    }                     let store = UsageStore(                        fetcher: UsageFetcher(environment: [:]),                        browserDetection: BrowserDetection(cacheTTL: 0),                        settings: settings,                        startupBehavior: .testing,                        environmentBase: [:])                    let prior = UsageSnapshot(                        primary: RateWindow(usedPercent: 12, windowMinutes: 300, resetsAt: nil, resetDescription: nil),                        secondary: nil,                        updatedAt: Date(timeIntervalSince1970: 1_800_000_000),                        identity: ProviderIdentitySnapshot(                            providerID: .claude,                            accountEmail: "claude@example.com",                            accountOrganization: nil,                            loginMethod: "Pro"))                    store._setSnapshotForTesting(prior, provider: .claude)                     let baseSpec = try #require(store.providerSpecs[.claude])                    let descriptor = ProviderDescriptor(                        id: .claude,                        metadata: baseSpec.descriptor.metadata,                        branding: baseSpec.descriptor.branding,                        tokenCost: baseSpec.descriptor.tokenCost,                        fetchPlan: ProviderFetchPlan(                            sourceModes: [.cli],                            pipeline: ProviderFetchPipeline { _ in [NetworkLostFetchStrategy()] }),                        cli: baseSpec.descriptor.cli)                    store.providerSpecs[.claude] = ProviderSpec(                        style: baseSpec.style,                        isEnabled: baseSpec.isEnabled,                        descriptor: descriptor,                        makeFetchContext: baseSpec.makeFetchContext)                    return (store, prior)                }                 await store.refreshProvider(.claude)                let firstResult = await MainActor.run {                    (                        updatedAt: store.snapshot(for: .claude)?.updatedAt,                        hasError: store.error(for: .claude) != nil)                }                 #expect(firstResult.updatedAt == prior.updatedAt)                #expect(!firstResult.hasError)                 await store.refreshProvider(.claude)                let secondResult = await MainActor.run {                    (                        updatedAt: store.snapshot(for: .claude)?.updatedAt,                        hasError: store.error(for: .claude) != nil)                }                 #expect(secondResult.updatedAt == prior.updatedAt)                #expect(secondResult.hasError)            }        }    }     @Test    func `credentials change clears prior Claude snapshot for non transient failure`() async throws {        try await KeychainCacheStore.withServiceOverrideForTesting("com.steipete.codexbar.cache.tests.\(UUID())") {            KeychainCacheStore.setTestStoreForTesting(true)            defer { KeychainCacheStore.setTestStoreForTesting(false) }             try await ClaudeOAuthCredentialsStore.withIsolatedCredentialsFileTrackingForTesting {                let tempDir = FileManager.default.temporaryDirectory                    .appendingPathComponent(UUID().uuidString, isDirectory: true)                try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)                let fileURL = tempDir.appendingPathComponent("credentials.json")                try Data("{}".utf8).write(to: fileURL)                 try await ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(fileURL) {                    #expect(ClaudeOAuthCredentialsStore.invalidateCacheIfCredentialsFileChanged())                     let store = try await MainActor.run {                        let settings = Self.makeSettingsStore(suite: "ClaudeResilienceTests-auth-change")                        settings.refreshFrequency = .manual                        settings.statusChecksEnabled = false                        settings.claudeUsageDataSource = .cli                         let metadata = ProviderRegistry.shared.metadata                        for provider in UsageProvider.allCases {                            try settings.setProviderEnabled(                                provider: provider,                                metadata: #require(metadata[provider]),                                enabled: provider == .claude)                        }                         let store = UsageStore(                            fetcher: UsageFetcher(environment: [:]),                            browserDetection: BrowserDetection(cacheTTL: 0),                            settings: settings,                            startupBehavior: .testing,                            environmentBase: [:])                        let prior = UsageSnapshot(                            primary: RateWindow(                                usedPercent: 12,                                windowMinutes: 300,                                resetsAt: nil,                                resetDescription: nil),                            secondary: nil,                            updatedAt: Date(timeIntervalSince1970: 1_800_000_000),                            identity: ProviderIdentitySnapshot(                                providerID: .claude,                                accountEmail: "old@example.com",                                accountOrganization: nil,                                loginMethod: "Pro"))                        store._setSnapshotForTesting(prior, provider: .claude)                         let baseSpec = try #require(store.providerSpecs[.claude])                        let descriptor = ProviderDescriptor(                            id: .claude,                            metadata: baseSpec.descriptor.metadata,                            branding: baseSpec.descriptor.branding,                            tokenCost: baseSpec.descriptor.tokenCost,                            fetchPlan: ProviderFetchPlan(                                sourceModes: [.cli],                                pipeline: ProviderFetchPipeline { _ in                                    [AuthFailureFetchStrategy(credentialsFileURL: fileURL)]                                }),                            cli: baseSpec.descriptor.cli)                        store.providerSpecs[.claude] = ProviderSpec(                            style: baseSpec.style,                            isEnabled: baseSpec.isEnabled,                            descriptor: descriptor,                            makeFetchContext: baseSpec.makeFetchContext)                        return store                    }                     await store.refreshProvider(.claude)                    let result = await MainActor.run {                        (                            hasSnapshot: store.snapshot(for: .claude) != nil,                            hasError: store.error(for: .claude) != nil)                    }                     #expect(!result.hasSnapshot)                    #expect(result.hasError)                }            }        }    }     @Test    func `credentials change clears prior Claude snapshot for transient failure`() async throws {        try await KeychainCacheStore.withServiceOverrideForTesting("com.steipete.codexbar.cache.tests.\(UUID())") {            KeychainCacheStore.setTestStoreForTesting(true)            defer { KeychainCacheStore.setTestStoreForTesting(false) }             try await ClaudeOAuthCredentialsStore.withIsolatedCredentialsFileTrackingForTesting {                let tempDir = FileManager.default.temporaryDirectory                    .appendingPathComponent(UUID().uuidString, isDirectory: true)                try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)                let fileURL = tempDir.appendingPathComponent("credentials.json")                try Data("{}".utf8).write(to: fileURL)                 try await ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(fileURL) {                    #expect(ClaudeOAuthCredentialsStore.invalidateCacheIfCredentialsFileChanged())                     let store = try await MainActor.run {                        let settings = Self.makeSettingsStore(suite: "ClaudeResilienceTests-transient-auth-change")                        settings.refreshFrequency = .manual                        settings.statusChecksEnabled = false                        settings.claudeUsageDataSource = .cli                         let metadata = ProviderRegistry.shared.metadata                        for provider in UsageProvider.allCases {                            try settings.setProviderEnabled(                                provider: provider,                                metadata: #require(metadata[provider]),                                enabled: provider == .claude)                        }                         let store = UsageStore(                            fetcher: UsageFetcher(environment: [:]),                            browserDetection: BrowserDetection(cacheTTL: 0),                            settings: settings,                            startupBehavior: .testing,                            environmentBase: [:])                        let prior = UsageSnapshot(                            primary: RateWindow(                                usedPercent: 12,                                windowMinutes: 300,                                resetsAt: nil,                                resetDescription: nil),                            secondary: nil,                            updatedAt: Date(timeIntervalSince1970: 1_800_000_000),                            identity: ProviderIdentitySnapshot(                                providerID: .claude,                                accountEmail: "old@example.com",                                accountOrganization: nil,                                loginMethod: "Pro"))                        store._setSnapshotForTesting(prior, provider: .claude)                         let baseSpec = try #require(store.providerSpecs[.claude])                        let descriptor = ProviderDescriptor(                            id: .claude,                            metadata: baseSpec.descriptor.metadata,                            branding: baseSpec.descriptor.branding,                            tokenCost: baseSpec.descriptor.tokenCost,                            fetchPlan: ProviderFetchPlan(                                sourceModes: [.cli],                                pipeline: ProviderFetchPipeline { _ in                                    [TransientFailureAfterCredentialSwapFetchStrategy(credentialsFileURL: fileURL)]                                }),                            cli: baseSpec.descriptor.cli)                        store.providerSpecs[.claude] = ProviderSpec(                            style: baseSpec.style,                            isEnabled: baseSpec.isEnabled,                            descriptor: descriptor,                            makeFetchContext: baseSpec.makeFetchContext)                        return store                    }                     await store.refreshProvider(.claude)                    let result = await MainActor.run {                        (                            hasSnapshot: store.snapshot(for: .claude) != nil,                            hasError: store.error(for: .claude) != nil)                    }                     #expect(!result.hasSnapshot)                    #expect(result.hasError)                }            }        }    }     @Test    func `keychain change clears prior Claude snapshot for transient failure`() async throws {        try await KeychainCacheStore.withServiceOverrideForTesting("com.steipete.codexbar.cache.tests.\(UUID())") {            KeychainCacheStore.setTestStoreForTesting(true)            defer { KeychainCacheStore.setTestStoreForTesting(false) }             let storedFingerprint = ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint(                modifiedAt: 1,                createdAt: 1,                persistentRefHash: "old")            let currentFingerprint = ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint(                modifiedAt: 2,                createdAt: 1,                persistentRefHash: "new")            let fingerprintStore = ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprintStore(                fingerprint: storedFingerprint)             try await ClaudeOAuthCredentialsStore.withClaudeKeychainFingerprintStoreOverrideForTesting(                fingerprintStore)            {                try await ClaudeOAuthKeychainPromptPreference.withTaskOverrideForTesting(.always) {                    try await ClaudeOAuthCredentialsStore.withKeychainAccessOverrideForTesting(false) {                        try await KeychainAccessGate.withTaskOverrideForTesting(false) {                            try await ClaudeOAuthKeychainAccessGate.withShouldAllowPromptOverrideForTesting(true) {                                try await ClaudeOAuthCredentialsStore.withClaudeKeychainOverridesForTesting(                                    data: nil,                                    fingerprint: currentFingerprint)                                {                                    try await ClaudeOAuthCredentialsStore                                        .withIsolatedCredentialsFileTrackingForTesting {                                            let tempDir = FileManager.default.temporaryDirectory                                                .appendingPathComponent(UUID().uuidString, isDirectory: true)                                            try FileManager.default.createDirectory(                                                at: tempDir,                                                withIntermediateDirectories: true)                                            let fileURL = tempDir.appendingPathComponent("missing-credentials.json")                                             try await ClaudeOAuthCredentialsStore                                                .withCredentialsURLOverrideForTesting(fileURL) {                                                    let store = try await MainActor.run {                                                        let settings = Self.makeSettingsStore(                                                            suite: "ClaudeResilienceTests-keychain-auth-change")                                                        settings.refreshFrequency = .manual                                                        settings.statusChecksEnabled = false                                                        settings.claudeUsageDataSource = .cli                                                         let metadata = ProviderRegistry.shared.metadata                                                        for provider in UsageProvider.allCases {                                                            try settings.setProviderEnabled(                                                                provider: provider,                                                                metadata: #require(metadata[provider]),                                                                enabled: provider == .claude)                                                        }                                                         let store = UsageStore(                                                            fetcher: UsageFetcher(environment: [:]),                                                            browserDetection: BrowserDetection(cacheTTL: 0),                                                            settings: settings,                                                            startupBehavior: .testing,                                                            environmentBase: [:])                                                        let prior = UsageSnapshot(                                                            primary: RateWindow(                                                                usedPercent: 12,                                                                windowMinutes: 300,                                                                resetsAt: nil,                                                                resetDescription: nil),                                                            secondary: nil,                                                            updatedAt: Date(timeIntervalSince1970: 1_800_000_000),                                                            identity: ProviderIdentitySnapshot(                                                                providerID: .claude,                                                                accountEmail: "old@example.com",                                                                accountOrganization: nil,                                                                loginMethod: "Pro"))                                                        store._setSnapshotForTesting(prior, provider: .claude)                                                         let baseSpec = try #require(store.providerSpecs[.claude])                                                        let descriptor = ProviderDescriptor(                                                            id: .claude,                                                            metadata: baseSpec.descriptor.metadata,                                                            branding: baseSpec.descriptor.branding,                                                            tokenCost: baseSpec.descriptor.tokenCost,                                                            fetchPlan: ProviderFetchPlan(                                                                sourceModes: [.cli],                                                                pipeline: ProviderFetchPipeline { _ in                                                                    [TimeoutFetchStrategy()]                                                                }),                                                            cli: baseSpec.descriptor.cli)                                                        store.providerSpecs[.claude] = ProviderSpec(                                                            style: baseSpec.style,                                                            isEnabled: baseSpec.isEnabled,                                                            descriptor: descriptor,                                                            makeFetchContext: baseSpec.makeFetchContext)                                                        return store                                                    }                                                     await store.refreshProvider(.claude)                                                    let result = await MainActor.run {                                                        (                                                            hasSnapshot: store.snapshot(for: .claude) != nil,                                                            hasError: store.error(for: .claude) != nil)                                                    }                                                     #expect(!result.hasSnapshot)                                                    #expect(result.hasError)                                                }                                        }                                }                            }                        }                    }                }            }        }    }     @Test    func `keychain removal clears prior Claude snapshot for transient failure`() async throws {        try await KeychainCacheStore.withServiceOverrideForTesting("com.steipete.codexbar.cache.tests.\(UUID())") {            KeychainCacheStore.setTestStoreForTesting(true)            defer { KeychainCacheStore.setTestStoreForTesting(false) }             let storedFingerprint = ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint(                modifiedAt: 1,                createdAt: 1,                persistentRefHash: "old")            let fingerprintStore = ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprintStore(                fingerprint: storedFingerprint)            let keychainStore = ClaudeOAuthCredentialsStore.ClaudeKeychainOverrideStore(data: nil, fingerprint: nil)             try await ClaudeOAuthCredentialsStore.withClaudeKeychainFingerprintStoreOverrideForTesting(                fingerprintStore)            {                try await ClaudeOAuthKeychainPromptPreference.withTaskOverrideForTesting(.always) {

Lines 1–500 of 1148.