| 1 | package hostclaim |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "errors" |
| 6 | "reflect" |
| 7 | "testing" |
| 8 | "time" |
| 9 | |
| 10 | "github.com/carlosframework/platform/internal/release" |
| 11 | ) |
| 12 | |
| 13 | func TestAdoptAndDiscoveryCompletion(t *testing.T) { |
| 14 | ctx := context.Background() |
| 15 | s := release.NewDirStore(t.TempDir()) |
| 16 | nh := newHolder() |
| 17 | obs, err := Read(ctx, s, testHost) |
| 18 | if err != nil { |
| 19 | t.Fatal(err) |
| 20 | } |
| 21 | o, err := Update(ctx, s, obs, Adopt(nh, "adi-knitting", []string{"uk"}, []string{"b2"}, "op_adopt", counter())) |
| 22 | if err != nil { |
| 23 | t.Fatal(err) |
| 24 | } |
| 25 | c := o.Claim |
| 26 | if !reflect.DeepEqual(c.Touched.Regions, []string{"ie"}) || !reflect.DeepEqual(c.Touched.Boxes, []string{"adi-knitting"}) { |
| 27 | t.Fatalf("adopted touched locations = %+v", c.Touched) |
| 28 | } |
| 29 | if c.Holder.Location != "instances/"+testHost || c.Touched.Complete || c.Touched.DiscoveryOp != "op_adopt" || |
| 30 | c.Holder.Stamp != c.Gen || c.Op.Exec != "adi-knitting" || len(c.Obligations) != 2 { |
| 31 | t.Fatalf("adopt = %+v", c) |
| 32 | } |
| 33 | // A delete is refused while discovery chores are pending in its write set (CC11). |
| 34 | if _, err := Update(ctx, s, o, BeginDelete("op_d", "console", `"e"`, time.Now(), []string{"ie", "uk"}, []string{"adi-knitting", "b2"}, "")); !errors.Is(err, ErrPendingChore) { |
| 35 | t.Fatalf("delete during discovery = %v", err) |
| 36 | } |
| 37 | for _, ob := range c.Obligations { |
| 38 | if o, err = Update(ctx, s, o, CompleteObligation(ob.Op, ob.ID)); err != nil { |
| 39 | t.Fatal(err) |
| 40 | } |
| 41 | } |
| 42 | if !o.Claim.Touched.Complete || o.Claim.Touched.DiscoveryOp != "" { |
| 43 | t.Fatalf("discovery not completed: %+v", o.Claim.Touched) |
| 44 | } |
| 45 | if _, err := Update(ctx, s, o, Adopt(nh, "adi-knitting", nil, nil, "op_adopt2", counter())); !errors.Is(err, ErrWrongState) { |
| 46 | t.Fatalf("re-adopt = %v", err) |
| 47 | } |
| 48 | o, err = Update(ctx, s, o, BeginDelete("op_d", "console", `"e"`, time.Now(), []string{"ie", "uk"}, []string{"adi-knitting", "b2"}, "")) |
| 49 | if err != nil { |
| 50 | t.Fatal(err) |
| 51 | } |
| 52 | o, err = Update(ctx, s, o, ToParking("op_d", []string{"ie", "uk"}, []string{"adi-knitting", "b2"}, counter())) |
| 53 | if err != nil { |
| 54 | t.Fatal(err) |
| 55 | } |
| 56 | assertParkingTargets(t, o.Claim.Obligations, []Obligation{ |
| 57 | {ParkTarget: "instances/" + testHost, Op: "op_d", Kind: "park-replica", Region: "ie", Owner: "region:ie"}, |
| 58 | {Op: "op_d", Kind: "park-local", Box: "adi-knitting", Owner: "box:adi-knitting"}, |
| 59 | }) |
| 60 | } |
| 61 | |
| 62 | func TestAdoptRefusesEmptyEffectiveRegion(t *testing.T) { |
| 63 | ctx := context.Background() |
| 64 | s := release.NewDirStore(t.TempDir()) |
| 65 | nh := newHolder() |
| 66 | nh.Region = "" |
| 67 | obs, err := Read(ctx, s, testHost) |
| 68 | if err != nil { |
| 69 | t.Fatal(err) |
| 70 | } |
| 71 | if _, err := Update(ctx, s, obs, Adopt(nh, "B0", nil, nil, "op_adopt", counter())); !errors.Is(err, ErrWrongState) { |
| 72 | t.Errorf("empty effective region = %v, want ErrWrongState", err) |
| 73 | } |
| 74 | after, err := Read(ctx, s, testHost) |
| 75 | if err != nil || !after.Absent { |
| 76 | t.Fatalf("read after refused adopt = %+v, %v; want absent", after, err) |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | func TestAdoptWithoutDiscoveryTargets(t *testing.T) { |
| 81 | ctx := context.Background() |
| 82 | s := release.NewDirStore(t.TempDir()) |
| 83 | obs, err := Read(ctx, s, testHost) |
| 84 | if err != nil { |
| 85 | t.Fatal(err) |
| 86 | } |
| 87 | o, err := Update(ctx, s, obs, Adopt(newHolder(), "B0", nil, nil, "op_adopt", counter())) |
| 88 | if err != nil { |
| 89 | t.Fatal(err) |
| 90 | } |
| 91 | want := Touched{Complete: true, Regions: []string{"ie"}, Boxes: []string{"B0"}} |
| 92 | if !reflect.DeepEqual(o.Claim.Touched, want) || len(o.Claim.Obligations) != 0 { |
| 93 | t.Fatalf("adopt without discovery targets = %+v", o.Claim) |
| 94 | } |
| 95 | o, err = Update(ctx, s, o, BeginDelete("op_d", "console", `"e"`, time.Now(), nil, nil, "")) |
| 96 | if err != nil { |
| 97 | t.Fatal(err) |
| 98 | } |
| 99 | o, err = Update(ctx, s, o, ToParking("op_d", nil, nil, counter())) |
| 100 | if err != nil { |
| 101 | t.Fatal(err) |
| 102 | } |
| 103 | assertParkingTargets(t, o.Claim.Obligations, []Obligation{ |
| 104 | {ParkTarget: "instances/" + testHost, Op: "op_d", Kind: "park-replica", Region: "ie", Owner: "region:ie"}, |
| 105 | {Op: "op_d", Kind: "park-local", Box: "B0", Owner: "box:B0"}, |
| 106 | }) |
| 107 | } |
| 108 | |