| 1 | package park |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "github.com/carlosframework/platform/internal/hostclaim" |
| 6 | "testing" |
| 7 | ) |
| 8 | |
| 9 | func TestPlan13ObserveRemoteBinding(t *testing.T) { |
| 10 | f := newFixture(t) |
| 11 | o, err := hostclaim.Read(t.Context(), f.e.Claims, f.w.Host) |
| 12 | if err != nil { |
| 13 | t.Fatal(err) |
| 14 | } |
| 15 | _, err = hostclaim.Update(t.Context(), f.e.Claims, o, func(c *hostclaim.Claim) error { c.Op.Intent = map[string]string{"home_region": "ie"}; return nil }) |
| 16 | if err != nil { |
| 17 | t.Fatal(err) |
| 18 | } |
| 19 | f.e.Region = "uk" |
| 20 | f.e.View = func(_ context.Context, o hostclaim.Observed) (View, error) { |
| 21 | return View{Region: "uk", HomeRegion: "ie", ClaimETag: o.ETag}, nil |
| 22 | } |
| 23 | _, v, err := f.e.observe(t.Context(), f.w, f.held, f.ob) |
| 24 | if err != nil { |
| 25 | t.Fatal(err) |
| 26 | } |
| 27 | if v.HomeRegion != "ie" || f.e.OwnsRegion(HomeRegion) { |
| 28 | t.Fatal("history binding lost or ownership widened") |
| 29 | } |
| 30 | c := &hostclaim.Claim{Holder: &hostclaim.Holder{Location: f.ob.Park.Location, Generation: "new", Admissions: []hostclaim.AdmissionRecord{{Generation: "new", Predecessor: "old", Region: "ie", PredecessorRegion: HomeRegion, Mode: "cold"}}}, Op: hostclaim.Op{Kind: hostclaim.KindServing}} |
| 31 | v.GenerationOf = func(Ref) (string, bool) { return "old", true } |
| 32 | v.Region = HomeRegion |
| 33 | v.AuthoritativeRegion = HomeRegion |
| 34 | v.MarkerKnown = true |
| 35 | v.MarkerGeneration = "old" |
| 36 | live, err := LiveGenerations(c, v, c.Holder.Location) |
| 37 | if err != nil || !live["old"] || !live["new"] { |
| 38 | t.Fatal(live, err) |
| 39 | } |
| 40 | } |
| 41 | func TestPlan13CompletedHomeParkCoversNamedPredecessor(t *testing.T) { |
| 42 | f := newFixture(t) |
| 43 | f.e.HomeRegion = "ie" |
| 44 | f.e.Region = HomeRegion |
| 45 | o, err := hostclaim.Read(t.Context(), f.e.Claims, f.w.Host) |
| 46 | if err != nil { |
| 47 | t.Fatal(err) |
| 48 | } |
| 49 | _, err = hostclaim.Update(t.Context(), f.e.Claims, o, func(c *hostclaim.Claim) error { |
| 50 | c.Obligations[0].Region = HomeRegion |
| 51 | c.Obligations[0].Owner = "region:" + HomeRegion |
| 52 | c.Holder.Generation = "next" |
| 53 | c.Holder.Admissions = []hostclaim.AdmissionRecord{{Generation: "next", Predecessor: "old", Region: "uk", PredecessorRegion: "ie", Mode: "cold"}, {Generation: "foreign", Predecessor: "old", Region: "fr", PredecessorRegion: "fr", Mode: "cold"}} |
| 54 | return nil |
| 55 | }) |
| 56 | if err != nil { |
| 57 | t.Fatal(err) |
| 58 | } |
| 59 | f.e.View = func(_ context.Context, o hostclaim.Observed) (View, error) { |
| 60 | return View{Region: HomeRegion, ClaimETag: o.ETag, AuthoritativeRegion: "uk", GenerationOf: func(Ref) (string, bool) { return "old", true }}, nil |
| 61 | } |
| 62 | f.b.Put("data", f.ob.Park.Location+"/g-old/0000/a", []byte("old")) |
| 63 | if err := f.e.Run(t.Context(), f.w); err != nil { |
| 64 | t.Fatal(err) |
| 65 | } |
| 66 | done, err := hostclaim.Read(t.Context(), f.e.Claims, f.w.Host) |
| 67 | if err != nil { |
| 68 | t.Fatal(err) |
| 69 | } |
| 70 | if len(done.Claim.Obligations) != 0 || !done.Claim.Holder.Admissions[0].Covered || done.Claim.Holder.Admissions[1].Covered { |
| 71 | t.Fatalf("coverage: %+v", done.Claim.Holder.Admissions) |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | func TestPlan13SweepRejectsConflictingHome(t *testing.T) { |
| 76 | f := newFixture(t) |
| 77 | f.e.HomeRegion = "ie" |
| 78 | o, err := hostclaim.Read(t.Context(), f.e.Claims, f.w.Host) |
| 79 | if err != nil { |
| 80 | t.Fatal(err) |
| 81 | } |
| 82 | _, err = hostclaim.Update(t.Context(), f.e.Claims, o, func(c *hostclaim.Claim) error { c.Op.Intent = map[string]string{"home_region": "uk"}; return nil }) |
| 83 | if err != nil { |
| 84 | t.Fatal(err) |
| 85 | } |
| 86 | if _, err = f.e.Sweep(t.Context(), f.w.Host, "", f.e.Now(), f.ob.Park.RequestLimit); err == nil { |
| 87 | t.Fatal("conflicting home binding accepted") |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | func TestPlan13SweepAbsentClaimRefuses(t *testing.T) { |
| 92 | f := newFixture(t) |
| 93 | f.e.View = func(context.Context, hostclaim.Observed) (View, error) { return View{}, nil } |
| 94 | if _, err := f.e.Sweep(t.Context(), "absent.example", "", f.e.Now(), f.ob.Park.RequestLimit); err == nil { |
| 95 | t.Fatal("absent claim accepted") |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | func TestPlan13ReturningWriterEmptyHomePark(t *testing.T) { |
| 100 | f := newFixture(t) |
| 101 | choreIn(t, f, HomeRegion) |
| 102 | f.e.HomeRegion = "ie" |
| 103 | engineIn(f, HomeRegion, HomeRegion) |
| 104 | o, err := hostclaim.Read(t.Context(), f.e.Claims, f.w.Host) |
| 105 | if err != nil { |
| 106 | t.Fatal(err) |
| 107 | } |
| 108 | o, err = hostclaim.Update(t.Context(), f.e.Claims, o, func(c *hostclaim.Claim) error { |
| 109 | c.Op = hostclaim.Op{ID: "op", Kind: hostclaim.KindRestoring, Phase: hostclaim.PhaseClaimed, Exec: "returner", Intent: map[string]string{"home_region": "ie"}} |
| 110 | c.Holder.Generation, c.Holder.Session, c.Holder.WriterBox = "old", 1, "target" |
| 111 | c.Holder.Admissions = []hostclaim.AdmissionRecord{{Generation: "old", Region: "ie", Session: 1, Box: "target", Mode: "cold"}} |
| 112 | return nil |
| 113 | }) |
| 114 | if err != nil { |
| 115 | t.Fatal(err) |
| 116 | } |
| 117 | o, err = hostclaim.Update(t.Context(), f.e.Claims, o, hostclaim.AdmitWriter(hostclaim.Admission{ObservedOpID: "op", ObservedPhase: hostclaim.PhaseClaimed, ObservedSession: 1, ObservedGeneration: "old", Region: "uk", Box: "returner", Mode: "cold", NewGeneration: "return"})) |
| 118 | if err != nil { |
| 119 | t.Fatal(err) |
| 120 | } |
| 121 | if !o.Claim.Holder.Admissions[1].Covered { |
| 122 | t.Fatal("returning predecessor uncovered") |
| 123 | } |
| 124 | if err := f.e.Run(t.Context(), f.w); err != nil { |
| 125 | t.Fatal(err) |
| 126 | } |
| 127 | done, err := hostclaim.Read(t.Context(), f.e.Claims, f.w.Host) |
| 128 | if err != nil { |
| 129 | t.Fatal(err) |
| 130 | } |
| 131 | if len(done.Claim.Obligations) != 0 || !done.Claim.Holder.Admissions[1].Covered || done.Claim.Holder.Admissions[1].PredecessorRegion != "ie" { |
| 132 | t.Fatal(done.Claim) |
| 133 | } |
| 134 | } |
| 135 | |