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

324 lines
13 KiB
Swift

import XCTest
@testable import CodexBarCore
final class AugmentStatusProbeTests: XCTestCase {
private func failingProbe() throws -> AugmentStatusProbe {
try AugmentStatusProbe(baseURL: XCTUnwrap(URL(string: "http://127.0.0.1:1")), timeout: 0.1)
}
@MainActor
func test_sessionKeepaliveStartLogsActualIntervals() {
var messages: [String] = []
let keepalive = AugmentSessionKeepalive { message in
messages.append(message)
}
keepalive.start()
defer { keepalive.stop() }
XCTAssertTrue(messages.contains { $0.contains("Check interval: 60s (1 minute)") })
XCTAssertTrue(messages.contains { $0.contains("Refresh buffer: 300s (5 minutes before expiry)") })
XCTAssertTrue(messages.contains { $0.contains("Min refresh interval: 60s (1 minute)") })
XCTAssertFalse(messages.contains { $0.contains("every 5 minutes") })
XCTAssertFalse(messages.contains { $0.contains("2 minutes") })
}
func test_debugRawProbe_returnsFormattedOutput() async throws {
// Given: A probe instance
let probe = try self.failingProbe()
// When: We call debugRawProbe
let output = await probe.debugRawProbe(cookieHeaderOverride: "session=test")
// Then: The output should contain expected debug information
XCTAssertTrue(output.contains("=== Augment Debug Probe @"), "Should contain debug header")
XCTAssertTrue(
output.contains("Probe Success") || output.contains("Probe Failed"),
"Should contain probe result status")
}
func test_latestDumps_initiallyEmpty() async {
// Note: This test may fail if other tests have already run and captured dumps
// The ring buffer is shared across all tests in the process
// When: We request latest dumps
let dumps = await AugmentStatusProbe.latestDumps()
// Then: Should either be empty or contain previous test dumps
// We just verify it returns a non-empty string
XCTAssertFalse(dumps.isEmpty, "Should return a string (either empty message or dumps)")
}
func test_debugRawProbe_capturesFailureInDumps() async throws {
// Given: A probe with an invalid base URL that will fail
let invalidProbe = try self.failingProbe()
// When: We call debugRawProbe which should fail
let output = await invalidProbe.debugRawProbe(cookieHeaderOverride: "session=test")
// Then: The output should indicate failure
XCTAssertTrue(output.contains("Probe Failed"), "Should contain failure message")
// And: The failure should be captured in dumps
let dumps = await AugmentStatusProbe.latestDumps()
XCTAssertNotEqual(dumps, "No Augment probe dumps captured yet.", "Should have captured the failure")
XCTAssertTrue(dumps.contains("Probe Failed"), "Dumps should contain the failure")
}
func test_latestDumps_maintainsRingBuffer() async throws {
// Given: Multiple failed probes to fill the ring buffer
let invalidProbe = try self.failingProbe()
// When: We generate more than 5 dumps (the ring buffer size)
for _ in 1...7 {
_ = await invalidProbe.debugRawProbe(cookieHeaderOverride: "session=test")
// Small delay to ensure different timestamps
try await Task.sleep(nanoseconds: 100_000_000) // 0.1 seconds
}
// Then: The dumps should only contain the most recent 5
let dumps = await AugmentStatusProbe.latestDumps()
let separatorCount = dumps.components(separatedBy: "\n\n---\n\n").count
XCTAssertLessThanOrEqual(separatorCount, 5, "Should maintain at most 5 dumps in ring buffer")
}
func test_debugRawProbe_includesTimestamp() async throws {
// Given: A probe instance
let probe = try self.failingProbe()
// When: We call debugRawProbe
let output = await probe.debugRawProbe(cookieHeaderOverride: "session=test")
// Then: The output should include an ISO8601 timestamp
XCTAssertTrue(output.contains("@"), "Should contain timestamp marker")
XCTAssertTrue(output.contains("==="), "Should contain debug header markers")
}
func test_debugRawProbe_includesCreditsBalance() async throws {
// Given: A probe instance
let probe = try self.failingProbe()
// When: We call debugRawProbe
let output = await probe.debugRawProbe(cookieHeaderOverride: "session=test")
// Then: The output should mention credits balance (either in success or failure)
XCTAssertTrue(
output.contains("Credits Balance") || output.contains("Probe Failed"),
"Should contain credits information or failure message")
}
func test_creditsLimit_prefersUsageUnitsAvailable() throws {
let response = try JSONDecoder().decode(AugmentCreditsResponse.self, from: Data("""
{
"usageUnitsRemaining": 15,
"usageUnitsConsumedThisBillingCycle": 10,
"usageUnitsAvailable": 100,
"usageBalanceStatus": "active"
}
""".utf8))
XCTAssertEqual(response.creditsLimit, 100)
}
func test_creditsLimit_fallsBackToRemainingPlusConsumedWhenAvailableMissing() throws {
let response = try JSONDecoder().decode(AugmentCreditsResponse.self, from: Data("""
{
"usageUnitsRemaining": 15,
"usageUnitsConsumedThisBillingCycle": 10,
"usageBalanceStatus": "active"
}
""".utf8))
XCTAssertEqual(response.creditsLimit, 25)
}
func test_creditsLimit_ignoresZeroAvailableValue() throws {
let response = try JSONDecoder().decode(AugmentCreditsResponse.self, from: Data("""
{
"usageUnitsRemaining": 15,
"usageUnitsConsumedThisBillingCycle": 10,
"usageUnitsAvailable": 0,
"usageBalanceStatus": "active"
}
""".utf8))
XCTAssertEqual(response.creditsLimit, 25)
}
// MARK: - Cookie Domain Filtering Tests
func test_cookieDomainMatching_exactMatch() throws {
// Given: A session with a cookie that has exact domain match
let cookie = try XCTUnwrap(HTTPCookie(properties: [
.domain: "app.augmentcode.com",
.path: "/",
.name: "session",
.value: "test123",
]))
let session = AugmentCookieImporter.SessionInfo(
cookies: [cookie],
sourceLabel: "Test")
let targetURL = try XCTUnwrap(URL(string: "https://app.augmentcode.com/api/credits"))
// When: We get the cookie header for the target URL
let cookieHeader = session.cookieHeader(for: targetURL)
// Then: It should include the cookie
XCTAssertEqual(cookieHeader, "session=test123", "Cookie with exact domain should match")
}
func test_cookieDomainMatching_parentDomain() throws {
// Given: A session with a cookie that has parent domain
let cookie = try XCTUnwrap(HTTPCookie(properties: [
.domain: "augmentcode.com",
.path: "/",
.name: "session",
.value: "test123",
]))
let session = AugmentCookieImporter.SessionInfo(
cookies: [cookie],
sourceLabel: "Test")
let targetURL = try XCTUnwrap(URL(string: "https://app.augmentcode.com/api/credits"))
// When: We get the cookie header for the target URL
let cookieHeader = session.cookieHeader(for: targetURL)
// Then: It should include the cookie (parent domain matches subdomain)
XCTAssertEqual(cookieHeader, "session=test123", "Cookie with parent domain should match subdomain")
}
func test_cookieDomainMatching_wildcardDomain() throws {
// Given: A session with a cookie that has wildcard domain
let cookie = try XCTUnwrap(HTTPCookie(properties: [
.domain: ".augmentcode.com",
.path: "/",
.name: "session",
.value: "test123",
]))
let session = AugmentCookieImporter.SessionInfo(
cookies: [cookie],
sourceLabel: "Test")
let targetURL = try XCTUnwrap(URL(string: "https://app.augmentcode.com/api/credits"))
// When: We get the cookie header for the target URL
let cookieHeader = session.cookieHeader(for: targetURL)
// Then: It should include the cookie
XCTAssertEqual(cookieHeader, "session=test123", "Cookie with wildcard domain should match")
}
func test_cookieDomainMatching_wrongDomain() throws {
// Given: A session with a cookie from a different subdomain
let cookie = try XCTUnwrap(HTTPCookie(properties: [
.domain: "auth.augmentcode.com",
.path: "/",
.name: "auth_token",
.value: "test123",
]))
let session = AugmentCookieImporter.SessionInfo(
cookies: [cookie],
sourceLabel: "Test")
let targetURL = try XCTUnwrap(URL(string: "https://app.augmentcode.com/api/credits"))
// When: We get the cookie header for the target URL
let cookieHeader = session.cookieHeader(for: targetURL)
// Then: It should NOT include the cookie
XCTAssertTrue(cookieHeader.isEmpty, "Cookie from different subdomain should not match")
}
func test_cookieDomainMatching_differentBaseDomain() throws {
// Given: A session with a cookie from a completely different domain
let cookie = try XCTUnwrap(HTTPCookie(properties: [
.domain: "example.com",
.path: "/",
.name: "session",
.value: "test123",
]))
let session = AugmentCookieImporter.SessionInfo(
cookies: [cookie],
sourceLabel: "Test")
let targetURL = try XCTUnwrap(URL(string: "https://app.augmentcode.com/api/credits"))
// When: We get the cookie header for the target URL
let cookieHeader = session.cookieHeader(for: targetURL)
// Then: It should NOT include the cookie
XCTAssertTrue(cookieHeader.isEmpty, "Cookie from different base domain should not match")
}
func test_cookieHeader_filtersCorrectly() throws {
// Given: A session with multiple cookies from different domains
let cookies = try [
XCTUnwrap(HTTPCookie(properties: [
.domain: "app.augmentcode.com",
.path: "/",
.name: "session",
.value: "valid1",
])),
XCTUnwrap(HTTPCookie(properties: [
.domain: ".augmentcode.com",
.path: "/",
.name: "_session",
.value: "valid2",
])),
XCTUnwrap(HTTPCookie(properties: [
.domain: "auth.augmentcode.com",
.path: "/",
.name: "auth_token",
.value: "invalid1",
])),
XCTUnwrap(HTTPCookie(properties: [
.domain: "billing.augmentcode.com",
.path: "/",
.name: "billing_session",
.value: "invalid2",
])),
]
let session = AugmentCookieImporter.SessionInfo(
cookies: cookies,
sourceLabel: "Test")
let targetURL = try XCTUnwrap(URL(string: "https://app.augmentcode.com/api/credits"))
// When: We get the cookie header for the target URL
let cookieHeader = session.cookieHeader(for: targetURL)
// Then: It should only include cookies valid for app.augmentcode.com
XCTAssertTrue(cookieHeader.contains("session=valid1"), "Should include exact domain match")
XCTAssertTrue(cookieHeader.contains("_session=valid2"), "Should include wildcard domain match")
XCTAssertFalse(cookieHeader.contains("auth_token"), "Should NOT include auth subdomain cookie")
XCTAssertFalse(cookieHeader.contains("billing_session"), "Should NOT include billing subdomain cookie")
}
func test_cookieHeader_emptyWhenNoCookiesMatch() throws {
// Given: A session with cookies that don't match the target domain
let cookies = try [
XCTUnwrap(HTTPCookie(properties: [
.domain: "auth.augmentcode.com",
.path: "/",
.name: "auth_token",
.value: "test",
])),
XCTUnwrap(HTTPCookie(properties: [
.domain: "example.com",
.path: "/",
.name: "other",
.value: "test",
])),
]
let session = AugmentCookieImporter.SessionInfo(
cookies: cookies,
sourceLabel: "Test")
let targetURL = try XCTUnwrap(URL(string: "https://app.augmentcode.com/api/credits"))
// When: We get the cookie header for the target URL
let cookieHeader = session.cookieHeader(for: targetURL)
// Then: It should be empty
XCTAssertTrue(cookieHeader.isEmpty, "Should return empty string when no cookies match")
}
}