51 lines
1.7 KiB
Go
51 lines
1.7 KiB
Go
package store
|
|
|
|
import "testing"
|
|
|
|
// TestCheckpointUsageForBookReturnsInsertionOrder pins the ordering the re-payment projection reads
|
|
// generation membership from (pipeline/reprice.go). Checkpoints are append-only for the life of a book,
|
|
// so telling this run's calls from a superseded run's is possible only by WHEN each was written.
|
|
// `attempt` cannot do it — it restarts at 0 every run — which is exactly what this fixture makes visible:
|
|
// the attempt numbers run 0,1,0,1 while the insertion order is g1a0, g1a1, g2a0, g2a1.
|
|
func TestCheckpointUsageForBookReturnsInsertionOrder(t *testing.T) {
|
|
s, _ := openTemp(t)
|
|
job := mustSnapshotAndJob(t, s)
|
|
|
|
for _, cp := range []struct {
|
|
hash string
|
|
attempt int
|
|
cost float64
|
|
}{
|
|
{"g1a0", 0, 0.01}, {"g1a1", 1, 0.02}, // generation 1
|
|
{"g2a0", 0, 0.03}, {"g2a1", 1, 0.04}, // generation 2, written later, attempts restart
|
|
} {
|
|
res, _, err := s.Reserve("book", cp.cost, Ceilings{BookUSD: 100, DayUSD: 100})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := s.SettleWithCheckpoint(res, cp.cost, Checkpoint{
|
|
RequestHash: cp.hash, JobID: job.ID, ChunkIdx: 0, Attempt: cp.attempt, Stage: "draft",
|
|
Role: "translator", ModelRequested: "m", ModelActual: "m", UsageJSON: "{}", CostUSD: cp.cost,
|
|
}, nil); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
rows, err := s.CheckpointUsageForBook("book")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var got []float64
|
|
for _, r := range rows {
|
|
got = append(got, r.CostUSD)
|
|
}
|
|
want := []float64{0.01, 0.02, 0.03, 0.04} // ordering by `attempt` would give 0.01, 0.03, 0.02, 0.04
|
|
if len(got) != len(want) {
|
|
t.Fatalf("got %d rows, want %d", len(got), len(want))
|
|
}
|
|
for i := range want {
|
|
if got[i] != want[i] {
|
|
t.Fatalf("checkpoint order = %v, want insertion order %v", got, want)
|
|
}
|
|
}
|
|
}
|