Files
steipete--codexbar/Tests/CodexBarTests/Issue2037ScannerIntegrationTests.swift
2026-07-13 12:22:33 +08:00

182 lines
8.5 KiB
Swift

import Foundation
import Testing
@testable import CodexBarCore
struct Issue2037ScannerIntegrationTests {
/// Locks that `#1164` inherited-totals accounting matches parent-owns-prefix
/// scanner units for the sanitized ordinary fork family when the parent file
/// is present in the scan window. Missing-parent / interleaved Ultra shapes
/// need separate goldens.
@Test
func `archived fork family scanner matches parent-owns-prefix oracle`() throws {
let fixture = try Issue2037FixtureHarness.load(named: "archived-fork-33ce-3869")
let sanitized = try SanitizedForkFamilyFixture.load(named: "archived-fork-33ce-3869")
let oracle = sanitized.manifest.oracle
let prefixLength = try #require(sanitized.manifest.copiedPrefixes.first).length
let parentEvents = try sanitized.events(named: "parent")
let childEvents = try sanitized.events(named: "child")
let expectedScannerUnits = parentEvents.map(\.last.scannerUnits).reduce(0, +)
+ childEvents.dropFirst(prefixLength).map(\.last.scannerUnits).reduce(0, +)
let naiveScannerUnits = parentEvents.map(\.last.scannerUnits).reduce(0, +)
+ childEvents.map(\.last.scannerUnits).reduce(0, +)
let env = try CostUsageTestEnvironment()
defer { env.cleanup() }
try Issue2037FixtureHarness.install(fixture, into: env)
let since = try env.makeLocalNoon(year: 2030, month: 1, day: 1)
let until = try env.makeLocalNoon(year: 2030, month: 1, day: 2)
var options = CostUsageScanner.Options(
codexSessionsRoot: env.codexSessionsRoot,
cacheRoot: env.cacheRoot)
options.forceRescan = true
options.refreshMinIntervalSeconds = 0
let report = CostUsageScanner.loadDailyReport(
provider: .codex,
since: since,
until: until,
now: until,
options: options)
var scannedUnits = 0
var dayKeys: [String] = []
for day in report.data {
dayKeys.append(day.date)
scannedUnits += day.inputTokens ?? 0
scannedUnits += day.cacheReadTokens ?? 0
scannedUnits += day.outputTokens ?? 0
}
#expect(!report.data.isEmpty)
#expect(naiveScannerUnits > expectedScannerUnits)
#expect(oracle.naiveLastTokens > oracle.dedupedLastTokens)
#expect(
scannedUnits == expectedScannerUnits,
"""
scanned=\(scannedUnits) expectedDeduped=\(expectedScannerUnits) \
naive=\(naiveScannerUnits) days=\(dayKeys)
""")
}
/// Second parent-present golden from a local Sol/Terra-adjacent fork
/// (`4d90→52bf`). Parent is truncated to the copied prefix so `#1164`
/// inheritance has a clean resolved-fork baseline.
///
/// Scanner units follow `total_token_usage` deltas (not `sum(last)`): this
/// corpus has a flat-total row with non-zero `last` at parent ordinal 120.
@Test
func `live fork 4d90 family scanner matches parent-owns-prefix oracle`() throws {
let fixture = try Issue2037FixtureHarness.load(named: "live-fork-4d90-52bf")
let sanitized = try SanitizedForkFamilyFixture.load(named: "live-fork-4d90-52bf")
let scannerOracle = try #require(fixture.manifest.scannerOracle)
let prefixLength = try #require(sanitized.manifest.copiedPrefixes.first).length
let parentEvents = try sanitized.events(named: "parent")
let childEvents = try sanitized.events(named: "child")
let parentTotalUnits = try #require(parentEvents.last).total.scannerUnits
let prefixEndTotalUnits = try #require(childEvents.dropFirst(prefixLength - 1).first).total.scannerUnits
let childEndTotalUnits = try #require(childEvents.last).total.scannerUnits
let expectedScannerUnits = parentTotalUnits + max(0, childEndTotalUnits - prefixEndTotalUnits)
#expect(parentTotalUnits == prefixEndTotalUnits)
#expect(expectedScannerUnits == childEndTotalUnits)
#expect(expectedScannerUnits == scannerOracle.dedupedScannerUnits)
#expect(scannerOracle.naiveScannerUnits > scannerOracle.dedupedScannerUnits)
// Corpus anomaly: sum(last) overcounts vs total-delta scanner units.
#expect(parentEvents.map(\.last.scannerUnits).reduce(0, +) > parentTotalUnits)
let env = try CostUsageTestEnvironment()
defer { env.cleanup() }
try Issue2037FixtureHarness.install(fixture, into: env)
let since = try env.makeLocalNoon(year: 2030, month: 1, day: 1)
let until = try env.makeLocalNoon(year: 2030, month: 1, day: 2)
var options = CostUsageScanner.Options(
codexSessionsRoot: env.codexSessionsRoot,
cacheRoot: env.cacheRoot)
options.forceRescan = true
options.refreshMinIntervalSeconds = 0
let report = CostUsageScanner.loadDailyReport(
provider: .codex,
since: since,
until: until,
now: until,
options: options)
var scannedUnits = 0
var dayKeys: [String] = []
for day in report.data {
dayKeys.append(day.date)
scannedUnits += day.inputTokens ?? 0
scannedUnits += day.cacheReadTokens ?? 0
scannedUnits += day.outputTokens ?? 0
}
#expect(!report.data.isEmpty)
#expect(
scannedUnits == scannerOracle.dedupedScannerUnits,
"""
scanned=\(scannedUnits) expectedDeduped=\(scannerOracle.dedupedScannerUnits) \
naive=\(scannerOracle.naiveScannerUnits) days=\(dayKeys)
""")
}
@Test
func `missing parent equal counter siblings fail open`() throws {
let env = try CostUsageTestEnvironment()
defer { env.cleanup() }
let day = try env.makeLocalNoon(year: 2030, month: 7, day: 1)
let firstTimestamp = env.isoString(for: day)
let secondTimestamp = env.isoString(for: day.addingTimeInterval(3600))
func siblingContents(id: String, model: String, timestamp: String) -> String {
let metadata = "{\"type\":\"session_meta\",\"timestamp\":\"\(timestamp)\",\"payload\":{"
+ "\"id\":\"\(id)\",\"forked_from_id\":\"missing-parent\","
+ "\"timestamp\":\"\(timestamp)\"}}"
let context = "{\"type\":\"turn_context\",\"timestamp\":\"\(timestamp)\","
+ "\"payload\":{\"model\":\"\(model)\"}}"
let first = "{\"type\":\"event_msg\",\"timestamp\":\"\(timestamp)\",\"payload\":{"
+ "\"type\":\"token_count\",\"info\":{"
+ "\"last_token_usage\":{\"input_tokens\":10,\"cached_input_tokens\":0,"
+ "\"output_tokens\":0},\"total_token_usage\":{\"input_tokens\":10,"
+ "\"cached_input_tokens\":0,\"output_tokens\":0}}}}"
let second = "{\"type\":\"event_msg\",\"timestamp\":\"\(timestamp)\",\"payload\":{"
+ "\"type\":\"token_count\",\"info\":{"
+ "\"last_token_usage\":{\"input_tokens\":5,\"cached_input_tokens\":0,"
+ "\"output_tokens\":0},\"total_token_usage\":{\"input_tokens\":15,"
+ "\"cached_input_tokens\":0,\"output_tokens\":0}}}}"
return [metadata, context, first, second].joined(separator: "\n") + "\n"
}
_ = try env.writeCodexArchivedSessionFile(
filename: "sibling-a.jsonl",
contents: siblingContents(id: "sibling-a", model: "fixture-model-a", timestamp: firstTimestamp))
_ = try env.writeCodexArchivedSessionFile(
filename: "sibling-b.jsonl",
contents: siblingContents(id: "sibling-b", model: "fixture-model-b", timestamp: secondTimestamp))
var options = CostUsageScanner.Options(
codexSessionsRoot: env.codexSessionsRoot,
cacheRoot: env.cacheRoot)
options.forceRescan = true
options.refreshMinIntervalSeconds = 0
let report = CostUsageScanner.loadDailyReport(
provider: .codex,
since: day,
until: day,
now: day,
options: options)
let scannedUnits = report.data.reduce(0) { partial, row in
partial + (row.inputTokens ?? 0) + (row.cacheReadTokens ?? 0) + (row.outputTokens ?? 0)
}
// Each unresolved child skips its first cumulative snapshot, then independently bills
// five input tokens. Equal token vectors are not sufficient cross-file identity.
#expect(scannedUnits == 10)
}
}