182 lines
8.5 KiB
Swift
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)
|
|
}
|
|
}
|