package hostclaim import ( "errors" "fmt" "reflect" "strings" "testing" "time" ) func TestPlan13BoundHomeMoveStartCleanup(t *testing.T) { for _, target := range []string{"@home", "ie"} { c := &Claim{Holder: &Holder{}, Op: Op{Kind: KindServing, Exec: "src"}, Obligations: []Obligation{{ID: "cleanup", Op: "old", Kind: "park-replica", Region: "ie", Owner: "region:ie"}}} before := append([]Obligation(nil), c.Obligations...) a := MoveAdmission{AppID: "app", AdmissionID: "move", SourceEnrollment: strings.Repeat("a", 32), TargetEnrollment: strings.Repeat("b", 32), HomeRegion: "ie"} if err := BeginAdmittedMove("move", "person", "src", "dst", target, time.Now(), a)(c); !errors.Is(err, ErrPendingChore) { t.Fatal("pending home cleanup allowed move", target, err) } if !reflect.DeepEqual(c.Obligations, before) || c.Op.Kind != KindServing { t.Fatal("refusal mutated claim") } } } func TestPlan13WholeLocationCoversHomeWithoutObjects(t *testing.T) { for _, release := range []bool{false, true} { for _, bound := range []bool{false, true} { c := probedLanding(t) home, region := "ie", "@home" if release { c = targetWroteLanding(t) home = "uk" c.Holder.Admissions = append(c.Holder.Admissions, AdmissionRecord{Region: "uk", PredecessorRegion: "uk", Session: 10, Box: "uk-box", Generation: "gen-r2", Predecessor: moveA, Mode: "cold"}) c.Holder.Session, c.Holder.Generation = 10, "gen-r2" if err := RollBack(moveA, rbA)(c); err != nil { t.Fatal(err) } c.Op.Intent["to"] = region } if bound { c.Op.Intent["home_region"] = home } n := 0 ids := func() string { n++; return fmt.Sprint("park", n) } var err error if release { err = TargetReleased(moveA, "uk-box", region, stoppedTarget, releaseScope(c), ids)(c) } else { src, lane := commitScopes(c) err = Commit(moveA, region, "ie-box", "uk", src, lane, ids)(c) } if err != nil { t.Fatal(err) } idx := 0 if release { idx = 1 } if c.Holder.Admissions[idx].Covered != bound { t.Fatalf("release=%v bound=%v: %+v", release, bound, c.Holder.Admissions) } if c.Holder.Admissions[idx].PredecessorRegion != home { t.Fatal("rewrote admission identity") } } } } func TestPlan13ReturningWriterHomeCoverage(t *testing.T) { for _, bound := range []bool{false, true} { c := targetWroteLanding(t) if err := RollBack(moveA, rbA)(c); err != nil { t.Fatal(err) } c.Op.Intent["to"] = "@home" if bound { c.Op.Intent["home_region"] = "uk" } n := 0 ids := func() string { n++; return fmt.Sprint("park", n) } if err := TargetReleased(moveA, "uk-box", "@home", stoppedTarget, releaseScope(c), ids)(c); err != nil { t.Fatal(err) } if err := ReturnToSource(moveA, "ie-box", false, ReturnFence{})(c); err != nil { t.Fatal(err) } h := c.Holder in := Admission{ObservedOpID: c.Op.ID, ObservedPhase: c.Op.Phase, ObservedSession: h.Session, ObservedGeneration: h.Generation, Box: c.Op.Exec, Mode: "cold", NewGeneration: "return", Region: "ie"} if err := AdmitWriter(in)(c); err != nil { t.Fatal(err) } last := c.Holder.Admissions[len(c.Holder.Admissions)-1] if last.Covered != bound || last.PredecessorRegion != "uk" { t.Fatalf("bound=%v: %+v", bound, last) } for _, ob := range append([]Obligation(nil), c.Obligations...) { if err := CompleteObligation(ob.Op, ob.ID)(c); err != nil { t.Fatal(err) } } if c.Holder.Admissions[len(c.Holder.Admissions)-1].Covered != bound { t.Fatal("empty cleanup lost coverage") } } } func TestPlan13RetainedHomeChoreBlocksLostTargetParked(t *testing.T) { for _, ob := range []Obligation{ {ID: "pending", Op: "move", Kind: "park-generation", Region: "ie", Owner: "region:ie"}, {ID: "pending", Op: "move", Kind: "park-generation", Region: "other", Owner: "region:ie"}, } { c := &Claim{Holder: &Holder{}, Op: Op{ID: "move", Kind: KindRestoring, Exec: "source", Intent: map[string]string{"target": "target", "to": "@home", "home_region": "ie"}}, Lost: []string{"target"}, Obligations: []Obligation{ob}} if LostMoveTargetParked(c, "@home") { t.Fatal("pending retained-name chore ignored", ob) } c.Obligations = nil if !LostMoveTargetParked(c, "ie") { t.Fatal("completed bound target refused") } } } func TestPlan13WarmAndPublishedHomeCoverage(t *testing.T) { for _, home := range []string{"ie", ""} { c := &Claim{Gen: 2, Holder: &Holder{Session: 2, Stamp: 2, Generation: "new", WriterBox: "box", Admissions: []AdmissionRecord{{Session: 2, Region: "ie", PredecessorRegion: "ie", Generation: "new", Predecessor: "old", Mode: "cold"}}}, Op: Op{Kind: KindServing, Exec: "box", Intent: map[string]string{"home_region": home}}} if err := PublishGeneration("", "", 2, "new", "@home", counter())(c); err != nil { t.Fatal(err) } if c.Holder.Admissions[0].Covered != (home != "") { t.Fatal("publication misses bound predecessor", home) } in := Admission{ObservedSession: 2, ObservedGeneration: "new", Box: "box", Mode: "warm", PredecessorCertified: true, Region: "@home"} if err := AdmitWriter(in)(c); (err == nil) != (home != "") { t.Fatal("warm admission", home, err) } } }