//go:build integration package inventory import ( "testing" "time" ) func TestAWalksMomentsAreKeptAndItsRestsReportRead(t *testing.T) { inv := ForTest(t) ctx := t.Context() p := walkOf(t, recordedWalk) p.Revision, p.Epoch = 0, 0 if err := inv.SavePlan(ctx, &p); err != nil { t.Fatal(err) } back, err := inv.PlanByID(ctx, p.ID) if err != nil || back.Times == nil || back.Times.Class != ClassCore || back.Times.WindowClosed == nil || !back.Times.WindowClosed.Equal(*p.Times.WindowClosed) { t.Fatalf("the walk's moments were not kept: %v %+v", err, back.Times) } if back.Delivery.Merges[0].Merged.IsZero() { t.Fatal("a merge's time was not kept") } sent := time.Now().UTC().Add(-time.Minute).Truncate(time.Millisecond) if _, ok, err := inv.FirstAppliedAfter(ctx, "ace", SentDeclaration{}, sent); err != nil || ok { t.Fatalf("no report yet: %v %v", ok, err) } for _, d := range []Duration{ {Kind: DurationApply, Subject: "ace", Node: "ace", Ref: "old@1", Started: sent.Add(-time.Hour), Took: time.Second, Detail: OutcomeApplied}, {Kind: DurationApply, Subject: "ace", Node: "ace", Ref: "d1@2", Started: sent.Add(-time.Second), Took: 12 * time.Second, Detail: OutcomeApplied}, } { if err := inv.RecordDuration(ctx, d); err != nil { t.Fatal(err) } } r, ok, err := inv.FirstAppliedAfter(ctx, "ace", SentDeclaration{}, sent) if err != nil || !ok || r.Outcome != OutcomeApplied || !r.At.Equal(sent.Add(11*time.Second)) { t.Fatalf("the report after the send: %+v %v %v", r, ok, err) } if anyKept, total, err := inv.WalkPhasesKept(ctx, p.ID); err != nil || anyKept || total { t.Fatalf("nothing kept yet: %v %v %v", anyKept, total, err) } if err := inv.RecordDuration(ctx, Duration{Kind: DurationWalkPhase, Subject: "core/total", Ref: p.ID + "/total", Started: sent, Took: time.Minute}); err != nil { t.Fatal(err) } if anyKept, total, err := inv.WalkPhasesKept(ctx, p.ID); err != nil || !anyKept || !total { t.Fatalf("the total kept: %v %v %v", anyKept, total, err) } } func TestALateReportIsSilentNotTheEnd(t *testing.T) { sent := time.Date(2026, 10, 10, 18, 0, 0, 0, time.UTC) p := walkOf(t, recordedWalk) p.Modules["mesh-delivery"].SentAt = &sent p.Modules["mesh-delivery"].Rest = map[string]SentDeclaration{"laptop": {Digest: "d"}, "server": {Digest: "e"}} w := p.WalkPhases(sent.Add(3*time.Hour), func(node string, _ SentDeclaration, _ time.Time) (AppliedReport, bool) { if node == "server" { return AppliedReport{At: sent.Add(20 * time.Second), Outcome: OutcomeApplied}, true } return AppliedReport{At: sent.Add(2 * time.Hour), Outcome: OutcomeApplied}, true }) if len(w.Silent) != 1 || w.Silent[0] != "laptop" || w.End == nil || !w.End.Equal(sent.Add(20*time.Second)) { t.Fatalf("a late report: silent %v, end %v", w.Silent, w.End) } inv := ForTest(t) ctx := t.Context() if err := inv.RecordDuration(ctx, Duration{Kind: DurationApply, Subject: "laptop", Node: "laptop", Ref: "late@1", Started: sent.Add(time.Hour), Took: time.Second, Detail: OutcomeApplied}); err != nil { t.Fatal(err) } if _, ok, err := inv.FirstAppliedAfter(ctx, "laptop", SentDeclaration{}, sent); err != nil || ok { t.Fatalf("a send past the bound read as the walk's: %v %v", ok, err) } }