MCPcopy Index your code
hub / github.com/docker/docker-agent / TestServer_ForkSession

Function TestServer_ForkSession

pkg/server/server_test.go:210–257  ·  view source on GitHub ↗

TestServer_ForkSession exercises the POST /api/sessions/:id/fork endpoint end-to-end: a fork at the Nth user message must return a new session with the history before that message, a fork-numbered title, and a fresh ID. An out-of-range ordinal must be rejected with 400 Bad Request.

(t *testing.T)

Source from the content-addressed store, hash-verified

208// title, and a fresh ID. An out-of-range ordinal must be rejected with
209// 400 Bad Request.
210func TestServer_ForkSession(t *testing.T) {
211 t.Parallel()
212
213 ctx := t.Context()
214 store := session.NewInMemorySessionStore()
215
216 parent := session.New()
217 parent.Title = "Original"
218 parent.Messages = []session.Item{
219 session.NewMessageItem(session.UserMessage("hello")),
220 session.NewMessageItem(session.NewAgentMessage("root", &chat.Message{
221 Role: chat.MessageRoleAssistant,
222 Content: "hi there",
223 })),
224 session.NewMessageItem(session.UserMessage("ignore me")),
225 }
226 require.NoError(t, store.AddSession(ctx, parent))
227
228 lnPath := startServerWithStore(t, ctx, prepareAgentsDir(t), store)
229
230 // Happy path: fork before the second user message (ordinal 1).
231 resp := httpDo(t, ctx, http.MethodPost, lnPath,
232 "/api/sessions/"+parent.ID+"/fork",
233 api.ForkSessionRequest{UserMessageIndex: 1})
234 var forked api.SessionResponse
235 unmarshal(t, resp, &forked)
236
237 assert.NotEqual(t, parent.ID, forked.ID)
238 assert.Equal(t, "Original (fork 1)", forked.Title)
239 require.Len(t, forked.Messages, 2)
240 assert.Equal(t, "hello", forked.Messages[0].Message.Content)
241 assert.Equal(t, "hi there", forked.Messages[1].Message.Content)
242
243 // Fork must be persisted server-side so a subsequent GET returns it.
244 getResp := httpGET(t, ctx, lnPath, "/api/sessions/"+forked.ID)
245 var fetched api.SessionResponse
246 unmarshal(t, getResp, &fetched)
247 assert.Equal(t, forked.ID, fetched.ID)
248 assert.Equal(t, "Original (fork 1)", fetched.Title)
249
250 // Forking past the last user message (no "full clone" shortcut) must
251 // return 400, not 500. This pins the sentinel-driven classification so
252 // future error-message reshuffles can't silently flip the status code.
253 outOfRange := httpRaw(t, ctx, http.MethodPost, lnPath,
254 "/api/sessions/"+parent.ID+"/fork",
255 api.ForkSessionRequest{UserMessageIndex: 99})
256 assert.Equal(t, http.StatusBadRequest, outOfRange.StatusCode, outOfRange.body)
257}
258
259// httpRaw issues an HTTP request and returns the raw response without
260// asserting on the status code, so tests can verify 4xx/5xx paths.

Callers

nothing calls this directly

Calls 14

AddSessionMethod · 0.95
NewInMemorySessionStoreFunction · 0.92
NewFunction · 0.92
NewMessageItemFunction · 0.92
UserMessageFunction · 0.92
NewAgentMessageFunction · 0.92
startServerWithStoreFunction · 0.85
prepareAgentsDirFunction · 0.85
httpDoFunction · 0.85
unmarshalFunction · 0.85
httpGETFunction · 0.85
httpRawFunction · 0.85

Tested by

no test coverage detected