| index dc8b77388..419cb8abe 100644 |
| --- a/internal/console/offlinereturn_test.go |
| +++ b/internal/console/offlinereturn_test.go |
| @@ -7,6 +7,7 @@ import ( |
| "fmt" |
| "net/http" |
| "sort" |
| + "strings" |
| "sync" |
| "testing" |
| "time" |
| @@ -791,3 +792,47 @@ func TestReturnSweepHourlyIsBounded(t *testing.T) { |
| } |
| }) |
| } |
| + |
| +// panicStore panics on every read of key: a store bug in the cleanup. |
| +type panicStore struct { |
| + release.Store |
| + key string |
| +} |
| + |
| +func (p *panicStore) Get(ctx context.Context, key string) ([]byte, string, error) { |
| + if key == p.key { |
| + panic("panicStore: " + key) |
| + } |
| + return p.Store.Get(ctx, key) |
| +} |
| + |
| +// TestReturnIndexCleanupPanicIsContained (fix round 4, item 2a): a panic in |
| +// the detached index cleanup is recovered and logged with the move id, as |
| +// an HTTP handler's panic is contained: the console survives, the answer |
| +// stands, and the entry stays for the sweep. |
| +func TestReturnIndexCleanupPanicIsContained(t *testing.T) { |
| + w := newReturnWorld(t, nil) |
| + w.report("uk-box", "uk-box", "", w.request(), time.Now(), w.ready()) |
| + indexKey := moves.ReturnIndexKey("uk", offlineHost, returnFwd) |
| + w.fx.srv.cfg.Releases = &panicStore{Store: w.fx.rel, key: indexKey} |
| + var logs strings.Builder |
| + restore := captureLogTo(&logs) |
| + code, out := w.req(http.MethodPost, "/stage", `{"region":"uk","return_of":"`+returnFwd+`"}`) |
| + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) |
| + defer cancel() |
| + serr := w.fx.srv.Shutdown(ctx) |
| + restore() |
| + if code != http.StatusAccepted { |
| + t.Fatalf("stage = %d %s", code, out) |
| + } |
| + if serr != nil { |
| + t.Fatal(serr) |
| + } |
| + id := w.record().Move.ID |
| + if !strings.Contains(logs.String(), "panic") || !strings.Contains(logs.String(), id) { |
| + t.Fatalf("the cleanup's panic was not logged with the move id %s: %q", id, logs.String()) |
| + } |
| + if _, _, err := w.fx.rel.Get(context.Background(), indexKey); err != nil { |
| + t.Fatalf("the entry the sweep owns is gone: %v", err) |
| + } |
| +} |