carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package status
2
3import (
4 "context"
5 "encoding/json"
6 "errors"
7 "fmt"
8 "os"
9 "path/filepath"
10 "testing"
11 "time"
12
13 "github.com/carlosframework/platform/internal/release"
14)
15
16// listOnly hides the store's ModLister, as a store that cannot say when an
17// object was written does.
18type listOnly struct{ release.Store }
19
20// refusesListMod has a ListMod that always refuses, as the claim's
21// boundary stores answer when the store they wrap has none.
22type refusesListMod struct{ release.Store }
23
24func (refusesListMod) ListMod(context.Context, string) ([]release.KeyMod, error) {
25 return nil, errors.New("required contract unavailable")
26}
27
28// T2 (region HA plan 2b): 250 reports of boxes a group replaced long ago
29// do not hide the two boxes running now. The old reports are dropped from
30// the listing before any read and before the key cap, and the reading is
31// complete.
32func TestStaleReportsDoNotHideLiveBoxes(t *testing.T) {
33 ctx := context.Background()
34 root := t.TempDir()
35 s := release.NewDirStore(root)
36 now := time.Now()
37 put := func(label string, at time.Time) {
38 raw, _ := json.Marshal(Box{Label: label, GeneratedAt: at})
39 key := "status/boxes/" + label + ".json"
40 if _, err := s.Put(ctx, key, raw, ""); err != nil {
41 t.Fatal(err)
42 }
43 if err := os.Chtimes(filepath.Join(root, filepath.FromSlash(key)), at, at); err != nil {
44 t.Fatal(err)
45 }
46 }
47 for i := 0; i < 250; i++ {
48 put(fmt.Sprintf("g-%020d", i), now.Add(-48*time.Hour))
49 }
50 put("g-live-one", now.Add(-time.Minute))
51 put("g-live-two", now.Add(-2*time.Minute))
52 // A report written an hour ago that says it is old: still listed (the
53 // listing only drops what is plainly history) and judged stale by its
54 // readers, as before.
55 put("g-quiet", now.Add(-time.Hour))
56
57 boxes, complete, err := LoadBoxesComplete(ctx, s)
58 if err != nil || !complete {
59 t.Fatalf("complete %v, err %v", complete, err)
60 }
61 var labels []string
62 for _, b := range boxes {
63 labels = append(labels, b.Label)
64 }
65 if fmt.Sprint(labels) != "[g-live-one g-live-two g-quiet]" {
66 t.Fatalf("boxes %v", labels)
67 }
68 if !BoxStale(boxes[2], now, SnapshotPeriod) {
69 t.Fatal("an old report read as fresh")
70 }
71 // A store with no write times is listed whole, as before: the cap
72 // applies to all 253, and the reading says it is incomplete.
73 if _, complete, err := LoadBoxesComplete(ctx, listOnly{s}); err != nil || complete {
74 t.Fatalf("listed whole: complete %v, err %v", complete, err)
75 }
76 // A store whose ListMod refuses is listed whole too: the horizon is an
77 // optimisation, so its failure never fails the read (the move door read
78 // the fleet through the claim's boundary stores and answered 409 when
79 // it did).
80 if _, complete, err := LoadBoxesComplete(ctx, refusesListMod{s}); err != nil || complete {
81 t.Fatalf("refused ListMod listed whole: complete %v, err %v", complete, err)
82 }
83}
84