| 1 | package acp |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "encoding/json" |
| 6 | "sync/atomic" |
| 7 | "testing" |
| 8 | |
| 9 | "reasonix/internal/event" |
| 10 | ) |
| 11 | |
| 12 | func TestProtocolRecoveryACPRejectsMissingAndUnsupportedToken(t *testing.T) { |
| 13 | var attempts atomic.Int32 |
| 14 | factory := &fakeFactory{behavior: func(context.Context, event.Sink, string) error { attempts.Add(1); return nil }} |
| 15 | client, cleanup := startServer(t, factory) |
| 16 | defer cleanup() |
| 17 | client.call(t, "initialize", InitializeParams{ProtocolVersion: 1}) |
| 18 | response := client.call(t, "session/new", SessionNewParams{}) |
| 19 | var created SessionNewResult |
| 20 | if err := json.Unmarshal(response.Result, &created); err != nil { |
| 21 | t.Fatal(err) |
| 22 | } |
| 23 | for _, id := range []string{"", "stale"} { |
| 24 | response := client.callAsync("session/prompt", SessionPromptParams{SessionID: created.SessionID, Action: "protocol_recovery", RecoveryID: id}) |
| 25 | _, result := drainPrompt(t, client, response) |
| 26 | want := ErrInvalidRequest |
| 27 | if id == "" { |
| 28 | want = ErrInvalidParams |
| 29 | } |
| 30 | if result.Error == nil || result.Error.Code != want { |
| 31 | t.Fatalf("recovery error=%+v", result.Error) |
| 32 | } |
| 33 | } |
| 34 | if attempts.Load() != 0 { |
| 35 | t.Fatal("rejected recovery reached model runner") |
| 36 | } |
| 37 | } |
| 38 |