carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package genselect
2
3import (
4 "context"
5 "errors"
6 "fmt"
7 "testing"
8
9 "github.com/carlosframework/platform/internal/hostclaim"
10)
11
12// GenerationMax is the loss boundary of one generation in a restore
13// (platform-1e's ruling on #236): the highest TXID of that exact generation
14// among the restore plan's selected files. It never lists the bucket; a
15// generation the plan does not contain is 0, every write in it lost.
16func TestGenerationMax(t *testing.T) {
17 ctx := context.Background()
18 t.Run("the plan's own generation is Select's maximum", func(t *testing.T) {
19 f := newFixture(t)
20 f.file("g0", 1, 1, 14)
21 f.file("g0", 0, 12, 14)
22 plan, err := Select(ctx, f.store, f.req)
23 if err != nil {
24 t.Fatal(err)
25 }
26 got, err := GenerationMax(plan, f.req.Holder.Location, "g0")
27 if err != nil || got != 14 || got != plan.MaxTXID {
28 t.Fatalf("GenerationMax %d %v, Select %d", got, err, plan.MaxTXID)
29 }
30 if got, err := GenerationMax(plan, f.req.Holder.Location+"/", "g0"); err != nil || got != 14 {
31 t.Fatalf("a trailing slash: %d %v", got, err)
32 }
33 })
34 t.Run("a generation the plan does not contain is 0", func(t *testing.T) {
35 f := newFixture(t)
36 f.file("g1", 0, 1, 99) // in the bucket, not in the restore
37 plan, err := Select(ctx, f.store, f.req)
38 if err != nil {
39 t.Fatal(err)
40 }
41 for _, gen := range []string{"g1", "t2", hostclaim.RootGeneration, ""} {
42 if got, err := GenerationMax(plan, f.req.Holder.Location, gen); err != nil || got != 0 {
43 t.Fatalf("%q: %d %v", gen, got, err)
44 }
45 }
46 })
47 t.Run("never a fresh listing", func(t *testing.T) {
48 f := newFixture(t)
49 plan, err := Select(ctx, f.store, f.req)
50 if err != nil {
51 t.Fatal(err)
52 }
53 f.file("g0", 0, 12, 40) // written after the selection
54 if got, err := GenerationMax(plan, f.req.Holder.Location, "g0"); err != nil || got != 11 {
55 t.Fatalf("%d %v", got, err)
56 }
57 })
58 t.Run("the legacy root spelling", func(t *testing.T) {
59 f := newFixture(t)
60 f.origin()
61 f.file(hostclaim.RootGeneration, 9, 1, 7)
62 f.file(hostclaim.RootGeneration, 0, 8, 8)
63 plan, err := Select(ctx, f.store, f.req)
64 if err != nil {
65 t.Fatal(err)
66 }
67 if plan.Generation != hostclaim.RootGeneration {
68 t.Fatalf("selected %q", plan.Generation)
69 }
70 for _, gen := range []string{hostclaim.RootGeneration, ""} {
71 if got, err := GenerationMax(plan, f.req.Holder.Location, gen); err != nil || got != 8 {
72 t.Fatalf("%q: %d %v", gen, got, err)
73 }
74 }
75 if got, err := GenerationMax(plan, f.req.Holder.Location, "g0"); err != nil || got != 0 {
76 t.Fatalf("a named generation under the origin: %d %v", got, err)
77 }
78 })
79 t.Run("a selected historical pinned version counts", func(t *testing.T) {
80 f := newFixture(t)
81 for _, key := range []string{f.pin.Key, f.req.Holder.Location + "/g-g0/0000/" + ltxName(11, 11)} {
82 f.b.BareDelete("data", key)
83 }
84 plan, err := Select(ctx, f.store, f.req)
85 if err != nil {
86 t.Fatal(err)
87 }
88 if plan.Root == nil || plan.Root.VersionID != f.pin.VersionID || plan.MaxTXID != 11 {
89 t.Fatalf("the selection is not the pinned historical root: %+v", plan)
90 }
91 if got, err := GenerationMax(plan, f.req.Holder.Location, "g0"); err != nil || got != 11 {
92 t.Fatalf("%d %v", got, err)
93 }
94 })
95 t.Run("refusals", func(t *testing.T) {
96 f := newFixture(t)
97 plan, err := Select(ctx, f.store, f.req)
98 if err != nil {
99 t.Fatal(err)
100 }
101 if _, err := GenerationMax(nil, f.req.Holder.Location, "g0"); !errors.Is(err, ErrInput) {
102 t.Fatalf("no plan: %v", err)
103 }
104 for name, in := range map[string][2]string{
105 "no location": {"", "g0"},
106 "a climbing path": {"instances/../h", "g0"},
107 "a nested gen": {f.req.Holder.Location, "g0/x"},
108 "a dot generation": {f.req.Holder.Location, ".."},
109 "an absolute path": {"/instances/h", "g0"},
110 "an empty element": {"instances//h", "g0"},
111 "a trailing double": {"instances/h//", "g0"},
112 } {
113 if _, err := GenerationMax(plan, in[0], in[1]); !errors.Is(err, ErrInput) {
114 t.Fatalf("%s: %v", name, err)
115 }
116 }
117 lying := *plan
118 lying.Files = append([]File(nil), plan.Files...)
119 lying.Files[0].MaxTXID = 99
120 if _, err := GenerationMax(&lying, f.req.Holder.Location, "g0"); !errors.Is(err, ErrInput) {
121 t.Fatalf("a file whose coordinates are not its key's: %v", err)
122 }
123 })
124}
125
126func ltxName(min, max uint64) string { return fmt.Sprintf("%016x-%016x.ltx", min, max) }
127