moves: run the source's return-residue park for real (Task 9a fix round 2, I3)
TestReturnResidueParkRunsThroughTheInstall drives a dirty return's parking phase (installRun.parking) with the real view, through the installer's own engine and RunHeld. The boundary is the target's admission: - before it, the pre-move generation is still holder.generation, authoritative in the source's region: the residue park is refused, the return stays at parking and the pre-move objects keep their bytes; - after it (the target's probe admitted in uk), the same parking archives the pre-move generation under parked/ and retires it from the source's location, and the return moves on. The target-cleaning test (TestRollbackReturnCleanupKeepsTheFilesLiveSet) stays. RED (restoring always naming the target, the old stand-in's rule): "the return's residue park before the target's admission: <nil>".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 file changed,
+58
−0
internal/host/movesfileslive_test.go+58 −0
diff --git a/internal/host/movesfileslive_test.go b/internal/host/movesfileslive_test.go| index 9ed75f05e..14ebdf121 100644 |
| --- a/internal/host/movesfileslive_test.go |
| +++ b/internal/host/movesfileslive_test.go |
| @@ -450,3 +450,61 @@ func TestRollbackReturnCleanupKeepsTheFilesLiveSet(t *testing.T) { |
| t.Fatal("the target's file was not archived") |
| } |
| } |
| + |
| +// TestReturnResidueParkRunsThroughTheInstall (fix round 2, I3; the source's |
| +// return-residue park, movesinstall.go parking): a dirty return's parking |
| +// phase runs its residue chores through the installer's own engine with the |
| +// real view. The boundary is the target's admission: before it, the |
| +// pre-move generation is still holder.generation, authoritative in the |
| +// source's region, so its residue park is refused and its bytes stay; once |
| +// the target's probe was admitted (the holder's generation is the target's, |
| +// authoritative in uk) the same parking archives the pre-move generation |
| +// and retires it from the source's location. |
| +func TestReturnResidueParkRunsThroughTheInstall(t *testing.T) { |
| + h := newReturnHarness(t, false) |
| + location := strings.TrimSuffix(h.claim(t).Holder.Location, "/") |
| + var pre []string |
| + for k := range h.f.buckets["data-ie"] { |
| + if strings.HasPrefix(k, location+"/g-cur/") { |
| + pre = append(pre, k) |
| + } |
| + } |
| + if len(pre) == 0 { |
| + t.Fatal("fixture: no pre-move generation at the source's location") |
| + } |
| + h.rcfg.ParkView = movesParkView(MovesRecordsFrom(h.s), h.vs, "data-ie", "ie") |
| + before := map[string]string{} |
| + for _, k := range pre { |
| + before[k] = h.f.buckets["data-ie"][k].body |
| + } |
| + |
| + // Before the target's admission: refused, bytes intact, still parking. |
| + if _, err := h.install(t); !errors.Is(err, park.ErrUnsafe) { |
| + t.Fatalf("the return's residue park before the target's admission: %v", err) |
| + } |
| + if rb := h.read(t, p1Host).Move.Rollback; rb.SourcePhase != provision.RbSourceParking { |
| + t.Fatalf("the return went past parking: %+v", rb) |
| + } |
| + for k, body := range before { |
| + if got, ok := h.f.buckets["data-ie"][k]; !ok || got.body != body { |
| + t.Fatalf("%s changed before the boundary", k) |
| + } |
| + } |
| + |
| + // After it: the target's probe was admitted in uk. |
| + admitTarget(t, h.landingHarness) |
| + if _, err := h.install(t); err != nil { |
| + t.Fatalf("the return after the target's admission: %v", err) |
| + } |
| + if rb := h.read(t, p1Host).Move.Rollback; rb.SourcePhase == provision.RbSourceParking { |
| + t.Fatalf("the return is still parking: %+v", rb) |
| + } |
| + for _, k := range pre { |
| + if _, ok := h.f.buckets["data-ie"][k]; ok { |
| + t.Fatalf("%s was not retired", k) |
| + } |
| + if !archivedUnder(h.f, "data-ie", h.inc, location, k) { |
| + t.Fatalf("%s was not archived", k) |
| + } |
| + } |
| +} |