package host import ( "errors" "strings" "testing" "time" "github.com/carlosframework/platform/internal/hostclaim" "github.com/carlosframework/platform/internal/moves" "github.com/carlosframework/platform/internal/park" "github.com/carlosframework/platform/internal/provision" ) // Home-region parks, part 1 (Paul, 2026-10-11): a move out of the home // placement finishes its cleanup on its source box. The home's placement // code is ""; its engine region is park.HomeRegion, mapped once where a // placement code becomes an engine region (park.PlacementRegion). // TestMoveFromHomeClosesThroughTheSourcePark: the whole move out of home, // through the real paths. The target commits through Plan 3's committed arm, // which queues the source's location park in HomeRegion; the source box, // whose placement is "", runs it through the real park engine and the real // park view seen from home, retiring the pre-move generation from its // bucket; and the move closes. func TestMoveFromHomeClosesThroughTheSourcePark(t *testing.T) { t.Parallel() h := newCloseHarness(t, fromHome) h.cfg.ParkView = movesParkView(MovesRecordsFrom(h.s), h.vs, "data-ie", park.HomeRegion) h.cfg.ParkAuthorize = allowParkAuthorize if rec := h.read(t, p1Host); rec.Move.From != "" || h.cfg.Region != "" { t.Fatalf("fixture: not a move out of home: from %q, source region %q", rec.Move.From, h.cfg.Region) } h.land(t) h.committedAndOpen(t) src := h.chore(t, park.HomeRegion, false) if src == nil || src.Owner != "region:"+park.HomeRegion || src.Park.Location != cutRoot { t.Fatalf("the commit queued the source's location park as %+v, want it in %s", src, park.HomeRegion) } for _, o := range h.claim(t).Obligations { if o.Region == "" || (o.Kind == "park-replica" && o.Region != park.HomeRegion && o.Region != "uk") { t.Fatalf("the commit queued %+v", o) } } // The target's probe recorded the home generation's region as home's, // and the commit's location park covered it. covered := false for _, a := range h.claim(t).Holder.Admissions { if a.Region == "uk" && a.Predecessor == "cur" { if a.PredecessorRegion != park.HomeRegion || !a.Covered { t.Fatalf("the probe's admission %+v: the home generation is not home's, or not covered", a) } covered = true } } if !covered { t.Fatalf("no admission retires the home generation: %+v", h.claim(t).Holder.Admissions) } h.clock.Advance(24 * time.Hour) h.land(t) if h.chore(t, "uk", true) != nil { t.Fatal("the staging park was not acknowledged") } h.notClosed(t, "the source has not parked") h.sourcePass(t) h.done(t) for k := range h.f.buckets["data-ie"] { if strings.HasPrefix(k, cutRoot+"/") { t.Fatalf("still at the home location: %s", k) } } pre := 0 for k := range h.f.buckets["data-ie"] { if strings.HasPrefix(k, "parked/"+h.inc+"/"+p1Host+"/"+src.Retirement+"/instances/") && strings.Contains(k, "/g-cur/") { pre++ } } if pre == 0 { t.Fatal("the pre-move generation was not archived under the location park's retirement") } q := h.claim(t).QuietAfter if _, ok := q[park.HomeRegion]; !ok { t.Fatalf("quiet_after %v names no %s", q, park.HomeRegion) } if _, ok := q[""]; ok { t.Fatalf("quiet_after %v names the unset region", q) } if m := h.read(t, p1Host).LastMove; m == nil || m.Outcome != "done" { t.Fatalf("the move did not close: %+v", m) } } // TestHomeParkViewNamesHomeAsARegion: the real park view for a move out of // home names HomeRegion where the spec's table names the source, seen from // home and from elsewhere; before the commit, home stays authoritative on // home (J2/F4). An unset region, a named region spelled "home" and a legacy // home holder with no admission still refuse. func TestHomeParkViewNamesHomeAsARegion(t *testing.T) { type row struct { name, seen string claim func(f *vwFixture) *hostclaim.Claim state string want string // "" wants a refusal } op := func(kind, phase string) hostclaim.Op { return hostclaim.Op{Kind: kind, ID: vwMove, Phase: phase, Exec: "box"} } home := park.HomeRegion rows := []row{ {"moving, a legacy holder, seen from home", home, func(f *vwFixture) *hostclaim.Claim { return &hostclaim.Claim{Holder: f.holder(""), Op: op(hostclaim.KindMoving, hostclaim.PhaseMoving)} }, provision.MoveCutting, home}, {"moving, admitted at home, seen from us", "us", func(f *vwFixture) *hostclaim.Claim { return &hostclaim.Claim{Holder: f.holder("cur", "cur@"+home), Op: op(hostclaim.KindMoving, hostclaim.PhaseMoving)} }, provision.MoveCutting, home}, {"reverting, seen from home", home, func(f *vwFixture) *hostclaim.Claim { return &hostclaim.Claim{Holder: f.holder("cur", "cur@"+home), Op: op(hostclaim.KindReverting, "")} }, provision.MoveReverting, home}, {"landing, the target's probe admitted, seen from home", home, func(f *vwFixture) *hostclaim.Claim { return &hostclaim.Claim{Holder: f.holder(vwMove, "cur@"+home, vwMove+"@uk"), Op: op(hostclaim.KindLanding, provision.LandProbing)} }, provision.MoveLanding, home}, {"landing, the target's probe admitted, seen from us", "us", func(f *vwFixture) *hostclaim.Claim { return &hostclaim.Claim{Holder: f.holder(vwMove, "cur@"+home, vwMove+"@uk"), Op: op(hostclaim.KindLanding, provision.LandProbing)} }, provision.MoveLanding, "uk"}, {"landing committed, seen from home", home, func(f *vwFixture) *hostclaim.Claim { return &hostclaim.Claim{Holder: f.holder(vwMove, "cur@"+home, vwMove+"@uk"), Op: op(hostclaim.KindLanding, hostclaim.PhaseCommitted)} }, provision.MoveCommitted, "uk"}, {"restoring before any admission", home, func(f *vwFixture) *hostclaim.Claim { return &hostclaim.Claim{Holder: f.holder(""), Op: op(hostclaim.KindRestoring, hostclaim.PhaseReleasing)} }, provision.MoveRollingBack, home}, {"moving, admitted in a named region spelled home", home, func(f *vwFixture) *hostclaim.Claim { return &hostclaim.Claim{Holder: f.holder("cur", "cur@home"), Op: op(hostclaim.KindMoving, hostclaim.PhaseMoving)} }, provision.MoveCutting, ""}, {"moving, seen from the unset region", "", func(f *vwFixture) *hostclaim.Claim { return &hostclaim.Claim{Holder: f.holder(""), Op: op(hostclaim.KindMoving, hostclaim.PhaseMoving)} }, provision.MoveCutting, ""}, {"serving, a legacy home holder with no admission", home, func(f *vwFixture) *hostclaim.Claim { return &hostclaim.Claim{Holder: f.holder(""), Op: hostclaim.Op{Kind: hostclaim.KindServing, Exec: "box"}} }, "", ""}, } for _, r := range rows { t.Run(r.name, func(t *testing.T) { f := newVwFixture(t) f.rec.Region = "" if r.state != "" { f.rec.Move = &provision.MoveState{ID: vwMove, Incarnation: f.inc, From: "", To: "uk", State: r.state} } obs := vwObs(r.claim(f)) v, err := movesParkView(f.records(), f.bucket, "data", r.seen)(t.Context(), obs) if r.want == "" { if !errors.Is(err, park.ErrUnsafe) { t.Fatalf("view %+v, %v; want a refusal", v, err) } return } if err != nil { t.Fatal(err) } if v.AuthoritativeRegion != r.want || v.Region != r.seen { t.Fatalf("view seen from %q names %q authoritative, want %q", v.Region, v.AuthoritativeRegion, r.want) } if (r.want == r.seen) != v.MarkerKnown { t.Fatalf("the marker was read %v, seen from %s with %s authoritative", v.MarkerKnown, r.seen, r.want) } }) } } // TestHomeLaneIsArmed: the lane park's arming takes the home's "" as a // region (the lane predicate), and refuses a code that is no placement. func TestHomeLaneIsArmed(t *testing.T) { c := newRevertHarness(t).laneCfg() for code, armed := range map[string]bool{"uk": true, "": true, "home": true, "IE": false, park.HomeRegion: false, "a/b": false} { c.Region = code if revertLaneArmed(c) != armed { t.Fatalf("lane armed for %q: %v, want %v", code, !armed, armed) } } } // TestMovesClaimPolicyRecoveryFromHome: a rollback's or a revert's recovery // on a home source is granted to the source's selection in park.HomeRegion, // the claim's engine region for home, and refused to one in a named region, // one named "home" among them. func TestMovesClaimPolicyRecoveryFromHome(t *testing.T) { type base struct { claim func() *hostclaim.Claim record func() *provision.Record } for name, b := range map[string]base{ "restoring probing": {func() *hostclaim.Claim { return rpRestoringClaim(rpClaimPhase(provision.RbSourceProbing)) }, func() *provision.Record { return rpRestoringRecord(provision.RbSourceProbing) }}, "reverting probing": {func() *hostclaim.Claim { return rpRevertingClaim(hostclaim.PhaseProbing) }, rpRevertingRecord}, } { for region, granted := range map[string]bool{park.HomeRegion: true, "home": false, "ie": false, "uk": false} { c, rec := b.claim(), b.record() rec.Move.From = "" s := rpSelection(c, "spawn") s.Region = region err := MovesClaimPolicy((&mpReader{rec: rec}).read)(t.Context(), c, s, rpIdentity("spawn")) if (err == nil) != granted { t.Fatalf("%s from home, selection in %q: %v, want granted %v", name, region, err, granted) } } } } // TestHomeLaneStagingLeaseKey: the staging lease of a lane in home (a move // out of home's return lane, taken with the record's From) is keyed by // park.HomeRegion, never an empty segment, and apart from every named // region, one named "home" among them; a code that is no placement refuses. func TestHomeLaneStagingLeaseKey(t *testing.T) { const host = "a.go.example.com" home, err := stagingLeaseKey("", host) if err != nil || home != "control/staging-leases/"+park.HomeRegion+"/"+host || strings.Contains(home, "//") { t.Fatalf("the home lane's staging lease is %q, %v", home, err) } for _, code := range []string{"uk", "home", "none"} { if got, err := stagingLeaseKey(code, host); err != nil || got == home || got != moves.StagingLeasePrefix(code, host) { t.Fatalf("%s's staging lease is %q, %v (home's %q)", code, got, err, home) } } for _, code := range []string{"IE", park.HomeRegion, "a/b"} { if got, err := stagingLeaseKey(code, host); !errors.Is(err, park.ErrUnsafe) { t.Fatalf("invalid code %q: %q, %v", code, got, err) } } }