package runs import ( "testing" "time" "textmachine/platform/internal/ingest" "textmachine/platform/internal/money" "textmachine/platform/internal/runner" ) // ⛔ THE BUYER IS TOLD THAT THE FIGURES ARE BEHIND, THROUGH THE SURFACE THAT CARRIES THE FIGURES. // // A parked or quarantined projection leaves a paying run's bar standing while the run goes on // spending, and until this field the operator had four carriers for it and the buyer none (unified // backlog row 399). ⚠ The screen does not merely freeze: the repair channel keeps refreshing the // ESTIMATE of such an attempt while the bar cannot move, so a client reading both shows a moving // estimate over a standing bar. // // ⚠ BOTH STATES ARE HERE BECAUSE THE FIELD ANSWERS FOR BOTH, and a field named «the figures are // behind» that went quiet on the quarantine would lie over half of its own population. The control // row is what keeps the pin from passing over a field hard-wired to true. func TestARunWhoseProjectionIsNotFollowingItSaysSoToTheBuyer(t *testing.T) { for _, tc := range []struct { name string set string want bool }{ {"the journal continued under another stream id", `parked_at = now()`, true}, {"the stream cannot be materialised at all", `quarantine_reason = 'a gap in the stream'`, true}, {"the projection is keeping up", `parked_at = null`, false}, } { t.Run(tc.name, func(t *testing.T) { f := newFixture(t, "10", 500) run, err := f.svc.Start(f.ctx, StartRequest{UserID: "u1", BookID: f.bookID(t), Chapters: order(10)}) if err != nil { t.Fatal(err) } if err := f.svc.Spawn(f.ctx, run.ID); err != nil { t.Fatal(err) } live := f.live(t) if _, err := f.store.Pool().Exec(f.ctx, `update run_attempts set `+tc.set+` where id = $1`, live.AttemptID); err != nil { t.Fatal(err) } // The read path a client is served from, not the column: what the buyer is told is the // question, and three different reads share one shape (pgstore.runRow). got, err := f.store.ReadRun(f.ctx, "u1", run.ID) if err != nil { t.Fatal(err) } if got.ProgressLagging != tc.want { t.Errorf("progress_lagging is %v, want %v", got.ProgressLagging, tc.want) } // ⚠ The premise of the whole field: the run is LIVE while this is said. A field that only // ever came out true on a finished run would describe nothing a buyer is watching. if got.Status != "translating" { t.Errorf("the run is %q, so this fixture no longer measures a live run's screen", got.Status) } }) } } // ⚠ AND THE FACT IS THE LIVE ATTEMPT'S, not the run's history: a park that ENDED with an earlier // attempt says nothing about the figures a buyer is watching now, and reporting it would tell them // their screen is behind while it is perfectly current. func TestAParkAnEarlierAttemptEndedWithIsNotReportedAsTodaysLag(t *testing.T) { f := newFixture(t, "10", 500) run, err := f.svc.Start(f.ctx, StartRequest{UserID: "u1", BookID: f.bookID(t), Chapters: order(100)}) if err != nil { t.Fatal(err) } if err := f.svc.Spawn(f.ctx, run.ID); err != nil { t.Fatal(err) } first := f.live(t) // The attempt is replaced the ordinary way: its unit is gone, nothing was spent, and the run comes // back with a second attempt whose projection has never parked. f.engine.set(ingest.StatusReport{TotalUnits: 100, Done: 0, Spend: usd(0), Reserved: usd(0)}, nil) f.runner.alive = false f.svc.Now = func() time.Time { return f.now.Add(time.Hour) } if err := f.svc.Sweep(f.ctx); err != nil { t.Fatal(err) } if live := f.live(t); live.AttemptNo != 2 { t.Fatalf("attempt %d: this test needs the parked attempt to be the PREVIOUS one", live.AttemptNo) } // ⛔ THE PARK IS SET AFTER THE SWEEP, AND THAT ORDER IS THE FIXTURE'S WHOLE VALIDITY. Set before // it, the mark does not survive: the same pass drains a journal this fixture never wrote, reaches // the verdict «not parked» and clears the column (reconcile.drainJournal → MarkParked). So a park // planted earlier is simply gone by the time anything reads it, and the test would measure an // empty scenario. Found by this pack's own mutation campaign: the planting that removes the // live-attempt condition from the read survived the first edition of this test, green. if _, err := f.store.Pool().Exec(f.ctx, `update run_attempts set parked_at = now() where id = $1`, first.AttemptID); err != nil { t.Fatal(err) } // The premise, asserted rather than assumed: the ENDED attempt really does carry a park now. var ended bool var parked *time.Time if err := f.store.Pool().QueryRow(f.ctx, `select ended_at is not null, parked_at from run_attempts where id = $1`, first.AttemptID). Scan(&ended, &parked); err != nil { t.Fatal(err) } if !ended || parked == nil { t.Fatalf("the previous attempt reads ended=%v parked=%v: without both this test cannot tell a "+ "history from today's lag", ended, parked) } got, err := f.store.ReadRun(f.ctx, "u1", run.ID) if err != nil { t.Fatal(err) } if got.ProgressLagging { t.Error("a park the previous attempt ended with is reported as today's lag") } } // ⛔ WHAT A RESUME IS PERMISSION FOR IS VISIBLE WITH THE RUN IT APPLIES TO. // // The consent is granted by the user's own resume of a corrected book and was, until this field, // recorded nowhere a person could read: measured once at 78× the work actually re-bought (unified // backlog row 416). This does not CAP it — the figure to cap against does not exist on this side of // the seam — it makes the figure and its provenance sayable: it is the run's own hold. // // The control is the same fixture without a correction: no consent stands, and the field says so // rather than showing a zero that reads as «consent to nothing». func TestTheConsentAResumeGrantedIsVisibleWithItsRun(t *testing.T) { for _, tc := range []struct { name string corrected bool }{ {"a resume over a corrected bank", true}, {"a resume of an ordinary stopped run", false}, } { t.Run(tc.name, func(t *testing.T) { f := newFixture(t, "10", 500) runID := f.stoppedRun(t, StartRequest{UserID: "u1", BookID: f.bookID(t), Chapters: order(3)}, 0, runner.Marker{Result: "exit-code", Code: "exited", Status: "3", At: f.now.Add(time.Second)}) if tc.corrected { fake := &fakeBankApplier{ out: runner.BankApplyOutcome{ExitCode: 0, Exited: true, Report: okReport("apply"), Decoded: true}, } fake.out.Report.BookID = f.bookID(t) f.svc.Bank = fake if _, err := f.svc.ApplyBankCorrections(f.ctx, BankCorrectionsInput{ UserID: "u1", BookID: f.bookID(t), Preview: false, Decisions: []ingest.BankDecision{{Action: "decline", ID: "tm_1"}}, }); err != nil { t.Fatal(err) } } if _, err := f.svc.Resume(f.ctx, "u1", runID); err != nil { t.Fatal(err) } got, err := f.store.ReadRun(f.ctx, "u1", runID) if err != nil { t.Fatal(err) } want := money.MicroUSD(0) if tc.corrected { // The provenance, asserted as such: the run's OWN hold — what three chapters were // sold for — and not a projection of the re-purchase, which does not exist here. want = fixtureHold(3) } if got.RebillConsent != want { t.Errorf("the run is handed out with a consent of %s, want %s", got.RebillConsent.USD(), want.USD()) } }) } }