package host import ( "encoding/json" "github.com/carlosframework/platform/internal/hostclaim" "github.com/carlosframework/platform/internal/lease" "github.com/carlosframework/platform/internal/moves" "github.com/carlosframework/platform/internal/park" "strings" "testing" "time" ) func TestPlan13HomeTargetReadiness(t *testing.T) { for _, stored := range []string{park.HomeRegion, "ie", "ca"} { t.Run(stored, func(t *testing.T) { h := newPhase1Harness(t) h.start(t, "manual") rec := h.read(t, p1Host) rec.Move.To = "" obs, err := hostclaim.Read(t.Context(), h.s, p1Host) if err != nil { t.Fatal(err) } obs.Claim.Op.Intent["home_region"] = "ie" obs.Claim.Touched.Regions = []string{stored} obs.Claim.Touched.Boxes = append(obs.Claim.Touched.Boxes, "uk-box") raw, err := json.Marshal(moves.MoveJSON{MoveID: rec.Move.ID, Incarnation: rec.Move.Incarnation, Host: rec.Host, From: rec.Move.From, To: rec.Move.To}) if err != nil { t.Fatal(err) } h.f.store("data-uk", moves.MoveJSONKey(rec.Host, rec.Move.ID), fakeMoveObject{lease.MirrorObject{ETag: "x", Size: int64(len(raw))}, string(raw)}) w := &movesWorker{cfg: h.targetCfg(), mirrors: map[string]lease.MirrorStore{}} got := w.checkClaim(t.Context(), obs, rec) if got.OK != (stored != "ca") { t.Fatalf("%s: %+v", stored, got) } if !got.OK && got.Reason != t9Untouched("ie") { t.Fatal(got.Reason) } }) } } func TestPlan13HomeQuietReason(t *testing.T) { now := time.Unix(1000, 0) o := hostclaim.Observed{Claim: &hostclaim.Claim{Op: hostclaim.Op{Intent: map[string]string{"home_region": "ie"}}, QuietAfter: map[string]time.Time{park.HomeRegion: now.Add(time.Minute)}}} got := checkQuiet(o, park.HomeRegion, now) if got.OK || strings.Contains(got.Reason, park.HomeRegion) || got.Reason != t12NotQuiet("ie", now.Add(time.Minute)) { t.Fatal(got) } } func TestPlan13ProbeHomeHistory(t *testing.T) { h := &hostclaim.Holder{Admissions: []hostclaim.AdmissionRecord{ {Generation: "move", Region: "ie", Box: "box", Mode: "cold"}, {Generation: "next", Predecessor: "move", Region: "@home", Box: "box", Mode: "cold"}, }} for _, home := range []string{"ie", ""} { m := &movesProbeOwners{Region: "ie", HomeRegion: home, Box: "box"} if got := m.descendsFromMove(h, "next", "move"); got != (home != "") { t.Fatal("descent", home, got) } _, ok := m.unpublishedPath(h, "next", "move") if ok != (home != "") { t.Fatal("unpublished path", home, ok) } } } func TestPlan13LandingUsesLocalBinding(t *testing.T) { for _, tc := range []struct { local, fleet, operation string ok bool }{ {"", "ie", "uk", false}, {"", "uk", "uk", false}, {"uk", "uk", "uk", true}, {"uk", "ie", "uk", false}, } { f := newPOFixture(t) c := f.poFlipClaim() c.Op.Intent["to"], c.Op.Intent["home_region"] = park.HomeRegion, tc.operation f.rec.Move.To = "" f.owners.HomeRegion, f.owners.FleetHomeRegion = tc.local, tc.fleet _, err := f.owners.landing(t.Context(), hostclaim.Observed{Host: poHost, Claim: c}) if (err == nil) != tc.ok { t.Fatalf("%+v: %v", tc, err) } } } func TestPlan13OwnStorageProjectionIgnoresOperationHome(t *testing.T) { h := &hostclaim.Holder{Admissions: []hostclaim.AdmissionRecord{{Region: park.HomeRegion, PredecessorRegion: park.HomeRegion}}} m := &movesProbeOwners{Region: "uk"} r := m.request("test.example", h) if r.Holder.Admissions[0].Region != park.HomeRegion { t.Fatal("named storage borrowed a home alias") } m.HomeRegion = "uk" r = m.request("test.example", h) if r.Holder.Admissions[0].Region != "uk" || h.Admissions[0].Region != park.HomeRegion { t.Fatal("home view lost binding or rewrote history") } } func TestPlan13HomeOwnerReason(t *testing.T) { got := checkOneOwner(moveFleet{}, "", "ie") if got.OK || got.Reason != t8Count(0, "ie") { t.Fatal(got) } o := hostclaim.Observed{Claim: &hostclaim.Claim{QuietAfter: map[string]time.Time{park.HomeRegion: time.Unix(2, 0)}}} got = checkQuiet(o, park.HomeRegion, time.Unix(1, 0)) if strings.Contains(got.Reason, park.HomeRegion) || strings.Contains(got.Reason, "left recently") { t.Fatal(got) } }