| index 40528d0ed..0015f9415 100644 |
| --- a/internal/console/offlinereturn_test.go |
| +++ b/internal/console/offlinereturn_test.go |
| @@ -28,6 +28,11 @@ type returnWorld struct { |
| func newReturnWorld(t *testing.T, edit func(o *moves.OpenRecord)) *returnWorld { |
| t.Helper() |
| w := &returnWorld{offlineWorld: newOfflineWorld(t, oneEach...)} |
| + // The forward finished: the record's last move is it, done. |
| + w.edit(func(r *provision.Record) error { |
| + r.LastMove = &provision.MoveOutcome{ID: returnFwd, Outcome: provision.OfflineOutcomeDone, At: time.Now().Add(-time.Hour).UTC()} |
| + return nil |
| + }) |
| rec := w.record() |
| w.open = moves.OpenRecord{MoveID: returnFwd, Host: offlineHost, Account: rec.Account, App: rec.App, Incarnation: rec.Incarnation, |
| From: "uk", To: "ie", Layout: moves.LayoutFlat, OpenedAt: time.Now().Add(-time.Hour).UTC(), |
| @@ -323,3 +328,36 @@ func TestOperatorReturnHandshakeAtTheConsole(t *testing.T) { |
| } |
| }) |
| } |
| + |
| +// TestReturnNeedsTheForwardCompleted (final review F4): a return names a |
| +// forward the record says completed, its last move that forward, done. |
| +// With a matching open record but no last move, another move's, or the |
| +// forward aborted, the return door, return-mode stage and return-mode |
| +// start all refuse before any write. |
| +func TestReturnNeedsTheForwardCompleted(t *testing.T) { |
| + noMove := "no completed move " + returnFwd + " from uk to ie for this instance" |
| + for name, last := range map[string]*provision.MoveOutcome{ |
| + "no last move": nil, |
| + "another move's": {ID: "mv_othermoveothermoveothermov", Outcome: provision.OfflineOutcomeDone, At: time.Now().UTC()}, |
| + "the forward aborted": {ID: returnFwd, Outcome: provision.OfflineOutcomeAborted, At: time.Now().UTC()}, |
| + } { |
| + t.Run(name, func(t *testing.T) { |
| + w := newReturnWorld(t, nil) |
| + // A request and its report written while the forward still |
| + // looked complete, so only the completion proof can refuse. |
| + w.report("uk-box", "uk-box", "", w.request(), time.Now(), w.ready()) |
| + w.edit(func(r *provision.Record) error { r.LastMove = last; return nil }) |
| + requests, _ := w.fx.rel.List(context.Background(), moves.ReturnRequestPrefix(offlineHost, returnFwd)) |
| + body := `{"region":"uk","return_of":"` + returnFwd + `"}` |
| + w.refused(http.MethodPost, "/return", body, http.StatusConflict, noMove) |
| + w.refused(http.MethodPost, "/stage", body, http.StatusConflict, noMove) |
| + w.refused(http.MethodPost, "", body, http.StatusConflict, noMove) |
| + if rec := w.record(); rec.Move != nil { |
| + t.Fatalf("a refused return wrote %+v", rec.Move) |
| + } |
| + if again, _ := w.fx.rel.List(context.Background(), moves.ReturnRequestPrefix(offlineHost, returnFwd)); len(again) != len(requests) { |
| + t.Fatalf("the refused return door wrote a request: %v, was %v", again, requests) |
| + } |
| + }) |
| + } |
| +} |