import Commanderimport Foundationimport Testing#if canImport(Darwin)import Darwin#elseimport Glibc#endif@testable import CodexBarCLI@testable import CodexBarCore // Cache state-machine coverage is intentionally kept together for sequence readability.// swiftlint:disable:next type_body_lengthstruct CLIServeRouterTests { @Test func `termination monitor handles interactive and hangup signals`() { #expect(CLITerminationSignalMonitor.signalNumbers == [SIGINT, SIGTERM, SIGHUP]) } @Test func `local http parser accepts only loopback host headers`() throws { let allowedHosts = [ "localhost", "localhost.", "localhost:8080", "127.0.0.1", "127.0.0.1:8080", "[::1]", "[::1]:8080", ] for host in allowedHosts { let request = try Self.parsedRequest(host: host) #expect(request.host == host) #expect(request.path == "/usage") } } @Test func `local http parser rejects hostile missing and duplicate hosts`() { Self.expectParseFailure(raw: "GET /usage HTTP/1.1\r\n\r\n", .missingHost) Self.expectParseFailure(raw: "GET /usage HTTP/1.1\r\nHost: evil.test\r\n\r\n", .disallowedHost) Self.expectParseFailure(raw: "GET /usage HTTP/1.1\r\nHost: localhost, evil.test\r\n\r\n", .disallowedHost) Self.expectParseFailure(raw: "GET /usage HTTP/1.1\r\nHost: localhost:abc\r\n\r\n", .disallowedHost) Self.expectParseFailure( raw: "GET /usage HTTP/1.1\r\nHost: localhost\r\nHost: 127.0.0.1\r\n\r\n", .duplicateHost) } @Test func `routes health usage and cost endpoints`() throws { #expect(try CLIServeRouter.route(method: "GET", path: "/health", queryItems: [:]) == .health) #expect(try CLIServeRouter.route(method: "GET", path: "/usage", queryItems: [:]) == .usage(provider: nil)) #expect( try CLIServeRouter.route( method: "GET", path: "/usage", queryItems: ["provider": "claude"]) == .usage(provider: "claude")) #expect( try CLIServeRouter.route( method: "GET", path: "/cost", queryItems: ["provider": "codex"]) == .cost(provider: "codex")) } @Test func `rejects non get methods`() { do { _ = try CLIServeRouter.route(method: "POST", path: "/usage", queryItems: [:]) Issue.record("Expected methodNotAllowed") } catch let error as CLIServeRouteError { #expect(error == .methodNotAllowed) } catch { Issue.record("Unexpected error: \(error)") } } @Test func `rejects unknown paths`() { do { _ = try CLIServeRouter.route(method: "GET", path: "/missing", queryItems: [:]) Issue.record("Expected notFound") } catch let error as CLIServeRouteError { #expect(error == .notFound) } catch { Issue.record("Unexpected error: \(error)") } } @Test func `serve numeric options reject malformed values`() { #expect(CodexBarCLI.decodeServePort(from: ParsedValues( positional: [], options: ["port": ["abc"]], flags: [])) == nil) #expect(CodexBarCLI.decodeServePort(from: ParsedValues( positional: [], options: ["port": ["0"]], flags: [])) == nil) #expect(CodexBarCLI.decodeServePort(from: ParsedValues( positional: [], options: ["port": ["65536"]], flags: [])) == nil) #expect(CodexBarCLI.decodeServePort(from: ParsedValues( positional: [], options: [:], flags: [])) == 8080) #expect(CodexBarCLI.decodeServeRefreshInterval(from: ParsedValues( positional: [], options: ["refreshInterval": ["later"]], flags: [])) == nil) #expect(CodexBarCLI.decodeServeRefreshInterval(from: ParsedValues( positional: [], options: ["refreshInterval": ["-1"]], flags: [])) == nil) #expect(CodexBarCLI.decodeServeRefreshInterval(from: ParsedValues( positional: [], options: ["refreshInterval": ["inf"]], flags: [])) == nil) #expect(CodexBarCLI.decodeServeRefreshInterval(from: ParsedValues( positional: [], options: ["refreshInterval": ["86401"]], flags: [])) == 86401) #expect(CodexBarCLI.decodeServeRefreshInterval(from: ParsedValues( positional: [], options: ["refreshInterval": ["86400"]], flags: [])) == 86400) #expect(CodexBarCLI.decodeServeRefreshInterval(from: ParsedValues( positional: [], options: [:], flags: [])) == 60) #expect(CodexBarCLI.decodeServeRequestTimeout(from: ParsedValues( positional: [], options: ["requestTimeout": ["soon"]], flags: [])) == nil) #expect(CodexBarCLI.decodeServeRequestTimeout(from: ParsedValues( positional: [], options: ["requestTimeout": ["-0.5"]], flags: [])) == nil) #expect(CodexBarCLI.decodeServeRequestTimeout(from: ParsedValues( positional: [], options: ["requestTimeout": ["0"]], flags: [])) == 0) #expect(CodexBarCLI.decodeServeRequestTimeout(from: ParsedValues( positional: [], options: ["requestTimeout": ["12.5"]], flags: [])) == 12.5) #expect(CodexBarCLI.decodeServeRequestTimeout(from: ParsedValues( positional: [], options: [:], flags: [])) == 30) } @Test func `serve help documents request timeout option`() { let serve = CodexBarCLI.serveHelp(version: "0.0.0") let root = CodexBarCLI.rootHelp(version: "0.0.0") #expect(serve.contains("--request-timeout <seconds>")) #expect(serve.contains("codexbar serve --port 8080 --refresh-interval 60 --request-timeout 30")) #expect(root.contains("--request-timeout <seconds>")) } @Test func `serve config snapshot reflects provider changes`() throws { let store = testConfigStore(suiteName: "CLIServeRouterTests-serve-config-freshness-\(UUID().uuidString)") defer { try? store.deleteIfPresent() } var firstConfig = CodexBarConfig.makeDefault() firstConfig.setProviderConfig(ProviderConfig(id: .opencodego, enabled: false)) try store.save(firstConfig) let firstSnapshot = try CodexBarCLI.loadServeConfigSnapshot(configStore: store) var secondConfig = firstConfig secondConfig.setProviderConfig(ProviderConfig(id: .opencodego, enabled: true)) try store.save(secondConfig) let secondSnapshot = try CodexBarCLI.loadServeConfigSnapshot(configStore: store) #expect(!firstSnapshot.config.enabledProviders().contains(.opencodego)) #expect(secondSnapshot.config.enabledProviders().contains(.opencodego)) #expect(firstSnapshot.cacheToken != secondSnapshot.cacheToken) #expect( CodexBarCLI.serveCacheKey(kind: "usage", provider: nil, configToken: firstSnapshot.cacheToken) != CodexBarCLI.serveCacheKey(kind: "usage", provider: nil, configToken: secondSnapshot.cacheToken)) } @Test func `serve cache skips provider error payloads`() { let success = CLILocalHTTPResponse( status: .ok, body: Data(#"[{"provider":"codex","source":"local"}]"#.utf8)) let providerError = CLILocalHTTPResponse( status: .ok, body: Data(#"[{"provider":"codex","source":"local","error":{"message":"temporary"}}]"#.utf8)) let routeError = CLILocalHTTPResponse( status: .badRequest, body: Data(#"{"error":"bad request"}"#.utf8)) #expect(CodexBarCLI.shouldCacheServeResponse(success)) #expect(!CodexBarCLI.shouldCacheServeResponse(providerError)) #expect(!CodexBarCLI.shouldCacheServeResponse(routeError)) } @Test func `serve cache uses stable Codex account identities`() { let storedID = UUID() let firstProjection = Self.codexVisibleAccount( id: "email-shaped-id", workspaceAccountID: "workspace-1", authFingerprint: "auth-1", storedAccountID: storedID) let reshapedProjection = Self.codexVisibleAccount( id: "managed:\(storedID.uuidString)", workspaceAccountID: "workspace-1", authFingerprint: "auth-1", storedAccountID: storedID) let replacement = Self.codexVisibleAccount( id: "email-shaped-id", workspaceAccountID: "workspace-2", authFingerprint: "auth-2", storedAccountID: UUID()) let workspacePeer = Self.codexVisibleAccount( id: "workspace-peer", email: "other@example.com", workspaceAccountID: "workspace-1", authFingerprint: "auth-3", storedAccountID: UUID()) let ambiguous = Self.codexVisibleAccount( id: "email-only", workspaceAccountID: nil, authFingerprint: nil, storedAccountID: nil) let storedBeforeRefresh = Self.codexVisibleAccount( id: "stored-before", workspaceAccountID: nil, authFingerprint: "old-auth", storedAccountID: storedID) let storedAfterRefresh = Self.codexVisibleAccount( id: "stored-after", workspaceAccountID: nil, authFingerprint: "new-auth", storedAccountID: storedID) let firstKey = CodexBarCLI.usageCacheAccountKey( provider: .codex, account: nil, codexVisibleAccount: firstProjection) let reshapedKey = CodexBarCLI.usageCacheAccountKey( provider: .codex, account: nil, codexVisibleAccount: reshapedProjection) let replacementKey = CodexBarCLI.usageCacheAccountKey( provider: .codex, account: nil, codexVisibleAccount: replacement) let workspacePeerKey = CodexBarCLI.usageCacheAccountKey( provider: .codex, account: nil, codexVisibleAccount: workspacePeer) let storedBeforeKey = CodexBarCLI.usageCacheAccountKey( provider: .codex, account: nil, codexVisibleAccount: storedBeforeRefresh) let storedAfterKey = CodexBarCLI.usageCacheAccountKey( provider: .codex, account: nil, codexVisibleAccount: storedAfterRefresh) #expect(firstKey == reshapedKey) #expect(firstKey != replacementKey) #expect(firstKey != workspacePeerKey) #expect(storedBeforeKey == storedAfterKey) #expect(CodexBarCLI.usageCacheAccountKey( provider: .codex, account: nil, codexVisibleAccount: ambiguous) == nil) #expect(CodexBarCLI.usageCacheAccountKey( provider: .antigravity, account: nil, codexVisibleAccount: nil) == nil) } @Test func `serve cache coalesces concurrent cache misses`() async { let cache = CLIServeResponseCache() let counter = ServeTestCounter() let responses = await withTaskGroup(of: CLILocalHTTPResponse.self) { group -> [CLILocalHTTPResponse] in for _ in 0..<5 { group.addTask { await CodexBarCLI.cachedServeResponse( key: "usage:", cache: cache, refreshInterval: 60, requestTimeout: 1) { let call = await counter.increment() try? await Task.sleep(nanoseconds: 50_000_000) return Self.response("[{\"provider\":\"codex\",\"call\":\(call)}]") } } } var responses: [CLILocalHTTPResponse] = [] for await response in group { responses.append(response) } return responses } #expect(await counter.current() == 1) #expect(Set(responses.map(Self.bodyString)).count == 1) #expect(responses.allSatisfy { $0.status == .ok }) #expect(responses.allSatisfy { Self.bodyString($0).contains("\"call\":1") }) } @Test func `serve cache prunes expired config token entries`() async throws { let cache = CLIServeResponseCache() _ = await CodexBarCLI.cachedServeResponse( key: "usage::old-config", cache: cache, refreshInterval: 0.001) { Self.response(#"[{"provider":"codex","config":"old"}]"#) } #expect(await cache.cachedEntryCount() == 1) try await Task.sleep(nanoseconds: 20_000_000) _ = await CodexBarCLI.cachedServeResponse( key: "usage::new-config", cache: cache, refreshInterval: 60) { Self.response(#"[{"provider":"codex","config":"new"}]"#) } #expect(await cache.cachedEntryCount() == 1) } @Test func `serve cache does not cache timeouts and recovers on next success`() async { let cache = CLIServeResponseCache() let counter = ServeTestCounter() let timeout = await CodexBarCLI.cachedServeResponse( key: "usage:", cache: cache, refreshInterval: 60, requestTimeout: 0.01) { _ = await counter.increment() try? await Task.sleep(nanoseconds: 200_000_000) return Self.response("[{\"provider\":\"codex\",\"call\":1}]") } #expect(timeout.status == .gatewayTimeout) #expect(Self.bodyString(timeout).contains("request timed out")) let success = await CodexBarCLI.cachedServeResponse( key: "usage:", cache: cache, refreshInterval: 60, requestTimeout: 1) { let call = await counter.increment() return Self.response("[{\"provider\":\"codex\",\"call\":\(call)}]") } #expect(success.status == .ok) #expect(Self.bodyString(success).contains("\"call\":2")) let cached = await CodexBarCLI.cachedServeResponse( key: "usage:", cache: cache, refreshInterval: 60, requestTimeout: 1) { let call = await counter.increment() return Self.response("[{\"provider\":\"codex\",\"call\":\(call)}]") } #expect(cached.status == .ok) #expect(Self.bodyString(cached) == Self.bodyString(success)) #expect(await counter.current() == 2) } @Test func `serve cache resumes coalesced waiters on timeout`() async { let cache = CLIServeResponseCache() let counter = ServeTestCounter() let responses = await withTaskGroup(of: CLILocalHTTPResponse.self) { group -> [CLILocalHTTPResponse] in for _ in 0..<4 { group.addTask { await CodexBarCLI.cachedServeResponse( key: "usage:", cache: cache, refreshInterval: 60, requestTimeout: 0.01) { _ = await counter.increment() try? await Task.sleep(nanoseconds: 200_000_000) return Self.response("[{\"provider\":\"codex\"}]") } } } var responses: [CLILocalHTTPResponse] = [] for await response in group { responses.append(response) } return responses } #expect(await counter.current() == 1) #expect(responses.count == 4) #expect(responses.allSatisfy { $0.status == .gatewayTimeout }) #expect(responses.allSatisfy { Self.bodyString($0).contains("request timed out") }) } @Test func `serve cache serves last good payload when refresh fails`() async { let cache = CLIServeResponseCache() let counter = ServeTestCounter() let first = await CodexBarCLI.cachedServeResponse( key: "usage:antigravity", cache: cache, refreshInterval: 0.05, requestTimeout: 1) { let call = await counter.increment() return Self.response("[{\"provider\":\"antigravity\",\"call\":\(call)}]") } #expect(first.status == .ok) // Let the fresh cache entry expire so the next request re-fetches. try? await Task.sleep(nanoseconds: 100_000_000) let failed = await CodexBarCLI.cachedServeResponse( key: "usage:antigravity", cache: cache, refreshInterval: 0.05, requestTimeout: 1) { _ = await counter.increment() return Self.response( "[{\"provider\":\"antigravity\",\"error\":{\"message\":\"transient\"}}]") } // Transient failure is masked by the last good payload. #expect(failed.status == .ok) let failedRows = try? Self.jsonRows(failed) #expect(failedRows?.first?["call"] as? Int == 1) #expect(await counter.current() == 2) try? await Task.sleep(nanoseconds: 100_000_000) let recovered = await CodexBarCLI.cachedServeResponse( key: "usage:antigravity", cache: cache, refreshInterval: 0.05, requestTimeout: 1) { let call = await counter.increment() return Self.response("[{\"provider\":\"antigravity\",\"call\":\(call)}]") } #expect(recovered.status == .ok) #expect(Self.bodyString(recovered).contains("\"call\":3")) } @Test func `serve cache replaces only failed provider account rows`() async throws { let cache = CLIServeResponseCache() _ = await CodexBarCLI.cachedServeResponse( key: "usage:", cache: cache, refreshInterval: 0.05, requestTimeout: 1) { Self.response(""" [ {"provider":"codex","account":"personal","call":1}, {"provider":"antigravity","account":"work","call":1}, {"provider":"antigravity","account":"personal","call":1} ] """) } try? await Task.sleep(nanoseconds: 100_000_000) let refreshed = await CodexBarCLI.cachedServeResponse( key: "usage:", cache: cache,Lines 1–500 of 1329. Load more
import Commander import Foundation import Testing #if canImport(Darwin) import Darwin #else import Glibc #endif @testable import CodexBarCLI @testable import CodexBarCore // Cache state-machine coverage is intentionally kept together for sequence readability. // swiftlint:disable:next type_body_length struct CLIServeRouterTests { @Test func `termination monitor handles interactive and hangup signals`() { #expect(CLITerminationSignalMonitor.signalNumbers == [SIGINT, SIGTERM, SIGHUP]) } @Test func `local http parser accepts only loopback host headers`() throws { let allowedHosts = [ "localhost", "localhost.", "localhost:8080", "127.0.0.1", "127.0.0.1:8080", "[::1]", "[::1]:8080", ] for host in allowedHosts { let request = try Self.parsedRequest(host: host) #expect(request.host == host) #expect(request.path == "/usage") } } @Test func `local http parser rejects hostile missing and duplicate hosts`() { Self.expectParseFailure(raw: "GET /usage HTTP/1.1\r\n\r\n", .missingHost) Self.expectParseFailure(raw: "GET /usage HTTP/1.1\r\nHost: evil.test\r\n\r\n", .disallowedHost) Self.expectParseFailure(raw: "GET /usage HTTP/1.1\r\nHost: localhost, evil.test\r\n\r\n", .disallowedHost) Self.expectParseFailure(raw: "GET /usage HTTP/1.1\r\nHost: localhost:abc\r\n\r\n", .disallowedHost) Self.expectParseFailure( raw: "GET /usage HTTP/1.1\r\nHost: localhost\r\nHost: 127.0.0.1\r\n\r\n", .duplicateHost) } @Test func `routes health usage and cost endpoints`() throws { #expect(try CLIServeRouter.route(method: "GET", path: "/health", queryItems: [:]) == .health) #expect(try CLIServeRouter.route(method: "GET", path: "/usage", queryItems: [:]) == .usage(provider: nil)) #expect( try CLIServeRouter.route( method: "GET", path: "/usage", queryItems: ["provider": "claude"]) == .usage(provider: "claude")) #expect( try CLIServeRouter.route( method: "GET", path: "/cost", queryItems: ["provider": "codex"]) == .cost(provider: "codex")) } @Test func `rejects non get methods`() { do { _ = try CLIServeRouter.route(method: "POST", path: "/usage", queryItems: [:]) Issue.record("Expected methodNotAllowed") } catch let error as CLIServeRouteError { #expect(error == .methodNotAllowed) } catch { Issue.record("Unexpected error: \(error)") } } @Test func `rejects unknown paths`() { do { _ = try CLIServeRouter.route(method: "GET", path: "/missing", queryItems: [:]) Issue.record("Expected notFound") } catch let error as CLIServeRouteError { #expect(error == .notFound) } catch { Issue.record("Unexpected error: \(error)") } } @Test func `serve numeric options reject malformed values`() { #expect(CodexBarCLI.decodeServePort(from: ParsedValues( positional: [], options: ["port": ["abc"]], flags: [])) == nil) #expect(CodexBarCLI.decodeServePort(from: ParsedValues( positional: [], options: ["port": ["0"]], flags: [])) == nil) #expect(CodexBarCLI.decodeServePort(from: ParsedValues( positional: [], options: ["port": ["65536"]], flags: [])) == nil) #expect(CodexBarCLI.decodeServePort(from: ParsedValues( positional: [], options: [:], flags: [])) == 8080) #expect(CodexBarCLI.decodeServeRefreshInterval(from: ParsedValues( positional: [], options: ["refreshInterval": ["later"]], flags: [])) == nil) #expect(CodexBarCLI.decodeServeRefreshInterval(from: ParsedValues( positional: [], options: ["refreshInterval": ["-1"]], flags: [])) == nil) #expect(CodexBarCLI.decodeServeRefreshInterval(from: ParsedValues( positional: [], options: ["refreshInterval": ["inf"]], flags: [])) == nil) #expect(CodexBarCLI.decodeServeRefreshInterval(from: ParsedValues( positional: [], options: ["refreshInterval": ["86401"]], flags: [])) == 86401) #expect(CodexBarCLI.decodeServeRefreshInterval(from: ParsedValues( positional: [], options: ["refreshInterval": ["86400"]], flags: [])) == 86400) #expect(CodexBarCLI.decodeServeRefreshInterval(from: ParsedValues( positional: [], options: [:], flags: [])) == 60) #expect(CodexBarCLI.decodeServeRequestTimeout(from: ParsedValues( positional: [], options: ["requestTimeout": ["soon"]], flags: [])) == nil) #expect(CodexBarCLI.decodeServeRequestTimeout(from: ParsedValues( positional: [], options: ["requestTimeout": ["-0.5"]], flags: [])) == nil) #expect(CodexBarCLI.decodeServeRequestTimeout(from: ParsedValues( positional: [], options: ["requestTimeout": ["0"]], flags: [])) == 0) #expect(CodexBarCLI.decodeServeRequestTimeout(from: ParsedValues( positional: [], options: ["requestTimeout": ["12.5"]], flags: [])) == 12.5) #expect(CodexBarCLI.decodeServeRequestTimeout(from: ParsedValues( positional: [], options: [:], flags: [])) == 30) } @Test func `serve help documents request timeout option`() { let serve = CodexBarCLI.serveHelp(version: "0.0.0") let root = CodexBarCLI.rootHelp(version: "0.0.0") #expect(serve.contains("--request-timeout <seconds>")) #expect(serve.contains("codexbar serve --port 8080 --refresh-interval 60 --request-timeout 30")) #expect(root.contains("--request-timeout <seconds>")) } @Test func `serve config snapshot reflects provider changes`() throws { let store = testConfigStore(suiteName: "CLIServeRouterTests-serve-config-freshness-\(UUID().uuidString)") defer { try? store.deleteIfPresent() } var firstConfig = CodexBarConfig.makeDefault() firstConfig.setProviderConfig(ProviderConfig(id: .opencodego, enabled: false)) try store.save(firstConfig) let firstSnapshot = try CodexBarCLI.loadServeConfigSnapshot(configStore: store) var secondConfig = firstConfig secondConfig.setProviderConfig(ProviderConfig(id: .opencodego, enabled: true)) try store.save(secondConfig) let secondSnapshot = try CodexBarCLI.loadServeConfigSnapshot(configStore: store) #expect(!firstSnapshot.config.enabledProviders().contains(.opencodego)) #expect(secondSnapshot.config.enabledProviders().contains(.opencodego)) #expect(firstSnapshot.cacheToken != secondSnapshot.cacheToken) #expect( CodexBarCLI.serveCacheKey(kind: "usage", provider: nil, configToken: firstSnapshot.cacheToken) != CodexBarCLI.serveCacheKey(kind: "usage", provider: nil, configToken: secondSnapshot.cacheToken)) } @Test func `serve cache skips provider error payloads`() { let success = CLILocalHTTPResponse( status: .ok, body: Data(#"[{"provider":"codex","source":"local"}]"#.utf8)) let providerError = CLILocalHTTPResponse( status: .ok, body: Data(#"[{"provider":"codex","source":"local","error":{"message":"temporary"}}]"#.utf8)) let routeError = CLILocalHTTPResponse( status: .badRequest, body: Data(#"{"error":"bad request"}"#.utf8)) #expect(CodexBarCLI.shouldCacheServeResponse(success)) #expect(!CodexBarCLI.shouldCacheServeResponse(providerError)) #expect(!CodexBarCLI.shouldCacheServeResponse(routeError)) } @Test func `serve cache uses stable Codex account identities`() { let storedID = UUID() let firstProjection = Self.codexVisibleAccount( id: "email-shaped-id", workspaceAccountID: "workspace-1", authFingerprint: "auth-1", storedAccountID: storedID) let reshapedProjection = Self.codexVisibleAccount( id: "managed:\(storedID.uuidString)", workspaceAccountID: "workspace-1", authFingerprint: "auth-1", storedAccountID: storedID) let replacement = Self.codexVisibleAccount( id: "email-shaped-id", workspaceAccountID: "workspace-2", authFingerprint: "auth-2", storedAccountID: UUID()) let workspacePeer = Self.codexVisibleAccount( id: "workspace-peer", email: "other@example.com", workspaceAccountID: "workspace-1", authFingerprint: "auth-3", storedAccountID: UUID()) let ambiguous = Self.codexVisibleAccount( id: "email-only", workspaceAccountID: nil, authFingerprint: nil, storedAccountID: nil) let storedBeforeRefresh = Self.codexVisibleAccount( id: "stored-before", workspaceAccountID: nil, authFingerprint: "old-auth", storedAccountID: storedID) let storedAfterRefresh = Self.codexVisibleAccount( id: "stored-after", workspaceAccountID: nil, authFingerprint: "new-auth", storedAccountID: storedID) let firstKey = CodexBarCLI.usageCacheAccountKey( provider: .codex, account: nil, codexVisibleAccount: firstProjection) let reshapedKey = CodexBarCLI.usageCacheAccountKey( provider: .codex, account: nil, codexVisibleAccount: reshapedProjection) let replacementKey = CodexBarCLI.usageCacheAccountKey( provider: .codex, account: nil, codexVisibleAccount: replacement) let workspacePeerKey = CodexBarCLI.usageCacheAccountKey( provider: .codex, account: nil, codexVisibleAccount: workspacePeer) let storedBeforeKey = CodexBarCLI.usageCacheAccountKey( provider: .codex, account: nil, codexVisibleAccount: storedBeforeRefresh) let storedAfterKey = CodexBarCLI.usageCacheAccountKey( provider: .codex, account: nil, codexVisibleAccount: storedAfterRefresh) #expect(firstKey == reshapedKey) #expect(firstKey != replacementKey) #expect(firstKey != workspacePeerKey) #expect(storedBeforeKey == storedAfterKey) #expect(CodexBarCLI.usageCacheAccountKey( provider: .codex, account: nil, codexVisibleAccount: ambiguous) == nil) #expect(CodexBarCLI.usageCacheAccountKey( provider: .antigravity, account: nil, codexVisibleAccount: nil) == nil) } @Test func `serve cache coalesces concurrent cache misses`() async { let cache = CLIServeResponseCache() let counter = ServeTestCounter() let responses = await withTaskGroup(of: CLILocalHTTPResponse.self) { group -> [CLILocalHTTPResponse] in for _ in 0..<5 { group.addTask { await CodexBarCLI.cachedServeResponse( key: "usage:", cache: cache, refreshInterval: 60, requestTimeout: 1) { let call = await counter.increment() try? await Task.sleep(nanoseconds: 50_000_000) return Self.response("[{\"provider\":\"codex\",\"call\":\(call)}]") } } } var responses: [CLILocalHTTPResponse] = [] for await response in group { responses.append(response) } return responses } #expect(await counter.current() == 1) #expect(Set(responses.map(Self.bodyString)).count == 1) #expect(responses.allSatisfy { $0.status == .ok }) #expect(responses.allSatisfy { Self.bodyString($0).contains("\"call\":1") }) } @Test func `serve cache prunes expired config token entries`() async throws { let cache = CLIServeResponseCache() _ = await CodexBarCLI.cachedServeResponse( key: "usage::old-config", cache: cache, refreshInterval: 0.001) { Self.response(#"[{"provider":"codex","config":"old"}]"#) } #expect(await cache.cachedEntryCount() == 1) try await Task.sleep(nanoseconds: 20_000_000) _ = await CodexBarCLI.cachedServeResponse( key: "usage::new-config", cache: cache, refreshInterval: 60) { Self.response(#"[{"provider":"codex","config":"new"}]"#) } #expect(await cache.cachedEntryCount() == 1) } @Test func `serve cache does not cache timeouts and recovers on next success`() async { let cache = CLIServeResponseCache() let counter = ServeTestCounter() let timeout = await CodexBarCLI.cachedServeResponse( key: "usage:", cache: cache, refreshInterval: 60, requestTimeout: 0.01) { _ = await counter.increment() try? await Task.sleep(nanoseconds: 200_000_000) return Self.response("[{\"provider\":\"codex\",\"call\":1}]") } #expect(timeout.status == .gatewayTimeout) #expect(Self.bodyString(timeout).contains("request timed out")) let success = await CodexBarCLI.cachedServeResponse( key: "usage:", cache: cache, refreshInterval: 60, requestTimeout: 1) { let call = await counter.increment() return Self.response("[{\"provider\":\"codex\",\"call\":\(call)}]") } #expect(success.status == .ok) #expect(Self.bodyString(success).contains("\"call\":2")) let cached = await CodexBarCLI.cachedServeResponse( key: "usage:", cache: cache, refreshInterval: 60, requestTimeout: 1) { let call = await counter.increment() return Self.response("[{\"provider\":\"codex\",\"call\":\(call)}]") } #expect(cached.status == .ok) #expect(Self.bodyString(cached) == Self.bodyString(success)) #expect(await counter.current() == 2) } @Test func `serve cache resumes coalesced waiters on timeout`() async { let cache = CLIServeResponseCache() let counter = ServeTestCounter() let responses = await withTaskGroup(of: CLILocalHTTPResponse.self) { group -> [CLILocalHTTPResponse] in for _ in 0..<4 { group.addTask { await CodexBarCLI.cachedServeResponse( key: "usage:", cache: cache, refreshInterval: 60, requestTimeout: 0.01) { _ = await counter.increment() try? await Task.sleep(nanoseconds: 200_000_000) return Self.response("[{\"provider\":\"codex\"}]") } } } var responses: [CLILocalHTTPResponse] = [] for await response in group { responses.append(response) } return responses } #expect(await counter.current() == 1) #expect(responses.count == 4) #expect(responses.allSatisfy { $0.status == .gatewayTimeout }) #expect(responses.allSatisfy { Self.bodyString($0).contains("request timed out") }) } @Test func `serve cache serves last good payload when refresh fails`() async { let cache = CLIServeResponseCache() let counter = ServeTestCounter() let first = await CodexBarCLI.cachedServeResponse( key: "usage:antigravity", cache: cache, refreshInterval: 0.05, requestTimeout: 1) { let call = await counter.increment() return Self.response("[{\"provider\":\"antigravity\",\"call\":\(call)}]") } #expect(first.status == .ok) // Let the fresh cache entry expire so the next request re-fetches. try? await Task.sleep(nanoseconds: 100_000_000) let failed = await CodexBarCLI.cachedServeResponse( key: "usage:antigravity", cache: cache, refreshInterval: 0.05, requestTimeout: 1) { _ = await counter.increment() return Self.response( "[{\"provider\":\"antigravity\",\"error\":{\"message\":\"transient\"}}]") } // Transient failure is masked by the last good payload. #expect(failed.status == .ok) let failedRows = try? Self.jsonRows(failed) #expect(failedRows?.first?["call"] as? Int == 1) #expect(await counter.current() == 2) try? await Task.sleep(nanoseconds: 100_000_000) let recovered = await CodexBarCLI.cachedServeResponse( key: "usage:antigravity", cache: cache, refreshInterval: 0.05, requestTimeout: 1) { let call = await counter.increment() return Self.response("[{\"provider\":\"antigravity\",\"call\":\(call)}]") } #expect(recovered.status == .ok) #expect(Self.bodyString(recovered).contains("\"call\":3")) } @Test func `serve cache replaces only failed provider account rows`() async throws { let cache = CLIServeResponseCache() _ = await CodexBarCLI.cachedServeResponse( key: "usage:", cache: cache, refreshInterval: 0.05, requestTimeout: 1) { Self.response(""" [ {"provider":"codex","account":"personal","call":1}, {"provider":"antigravity","account":"work","call":1}, {"provider":"antigravity","account":"personal","call":1} ] """) } try? await Task.sleep(nanoseconds: 100_000_000) let refreshed = await CodexBarCLI.cachedServeResponse( key: "usage:", cache: cache,