package status import ( "context" "encoding/json" "errors" "fmt" "os" "path/filepath" "testing" "time" "github.com/carlosframework/platform/internal/release" ) // listOnly hides the store's ModLister, as a store that cannot say when an // object was written does. type listOnly struct{ release.Store } // refusesListMod has a ListMod that always refuses, as the claim's // boundary stores answer when the store they wrap has none. type refusesListMod struct{ release.Store } func (refusesListMod) ListMod(context.Context, string) ([]release.KeyMod, error) { return nil, errors.New("required contract unavailable") } // T2 (region HA plan 2b): 250 reports of boxes a group replaced long ago // do not hide the two boxes running now. The old reports are dropped from // the listing before any read and before the key cap, and the reading is // complete. func TestStaleReportsDoNotHideLiveBoxes(t *testing.T) { ctx := context.Background() root := t.TempDir() s := release.NewDirStore(root) now := time.Now() put := func(label string, at time.Time) { raw, _ := json.Marshal(Box{Label: label, GeneratedAt: at}) key := "status/boxes/" + label + ".json" if _, err := s.Put(ctx, key, raw, ""); err != nil { t.Fatal(err) } if err := os.Chtimes(filepath.Join(root, filepath.FromSlash(key)), at, at); err != nil { t.Fatal(err) } } for i := 0; i < 250; i++ { put(fmt.Sprintf("g-%020d", i), now.Add(-48*time.Hour)) } put("g-live-one", now.Add(-time.Minute)) put("g-live-two", now.Add(-2*time.Minute)) // A report written an hour ago that says it is old: still listed (the // listing only drops what is plainly history) and judged stale by its // readers, as before. put("g-quiet", now.Add(-time.Hour)) boxes, complete, err := LoadBoxesComplete(ctx, s) if err != nil || !complete { t.Fatalf("complete %v, err %v", complete, err) } var labels []string for _, b := range boxes { labels = append(labels, b.Label) } if fmt.Sprint(labels) != "[g-live-one g-live-two g-quiet]" { t.Fatalf("boxes %v", labels) } if !BoxStale(boxes[2], now, SnapshotPeriod) { t.Fatal("an old report read as fresh") } // A store with no write times is listed whole, as before: the cap // applies to all 253, and the reading says it is incomplete. if _, complete, err := LoadBoxesComplete(ctx, listOnly{s}); err != nil || complete { t.Fatalf("listed whole: complete %v, err %v", complete, err) } // A store whose ListMod refuses is listed whole too: the horizon is an // optimisation, so its failure never fails the read (the move door read // the fleet through the claim's boundary stores and answered 409 when // it did). if _, complete, err := LoadBoxesComplete(ctx, refusesListMod{s}); err != nil || complete { t.Fatalf("refused ListMod listed whole: complete %v, err %v", complete, err) } }