MCPcopy Index your code
hub / github.com/coder/coder / TestProcessChatPanicRecovery

Function TestProcessChatPanicRecovery

coderd/x/chatd/chatd_test.go:7573–7634  ·  view source on GitHub ↗
(t *testing.T)

Source from the content-addressed store, hash-verified

7571}
7572
7573func TestProcessChatPanicRecovery(t *testing.T) {
7574 t.Parallel()
7575
7576 db, ps := dbtestutil.NewDB(t)
7577
7578 // Wrap the database so we can trigger a panic on the main
7579 // goroutine of processChat. The chatloop's executeTools has
7580 // its own recover, so panicking inside a tool goroutine won't
7581 // reach the processChat-level recovery. Instead, we panic
7582 // during PersistStep's InTx call, which runs synchronously on
7583 // the processChat goroutine.
7584 panicWrapper := &panicOnInTxDB{Store: db}
7585
7586 openAIURL := chattest.NewOpenAI(t, func(req *chattest.OpenAIRequest) chattest.OpenAIResponse {
7587 if !req.Stream {
7588 return chattest.OpenAINonStreamingResponse("Panic recovery test")
7589 }
7590 return chattest.OpenAIStreamingResponse(
7591 chattest.OpenAITextChunks("hello")...,
7592 )
7593 })
7594
7595 ctx := testutil.Context(t, testutil.WaitLong)
7596 user, org, model := seedChatDependenciesWithProvider(t, db, "openai-compat", openAIURL)
7597
7598 // Pass the panic wrapper to the server, but use the real
7599 // database for seeding so those operations don't panic.
7600 server := newActiveTestServer(t, panicWrapper, ps)
7601
7602 chat, err := server.CreateChat(ctx, chatd.CreateOptions{
7603 OrganizationID: org.ID,
7604 OwnerID: user.ID,
7605 Title: "panic-recovery",
7606 ModelConfigID: model.ID,
7607 InitialUserContent: []codersdk.ChatMessagePart{
7608 codersdk.ChatMessageText("hello"),
7609 },
7610 })
7611 require.NoError(t, err)
7612
7613 // Enable the panic now that CreateChat's InTx has completed.
7614 // The next InTx call is PersistStep inside the chatloop,
7615 // running synchronously on the processChat goroutine.
7616 panicWrapper.enablePanic()
7617
7618 // Wait for the panic to be recovered and the chat to
7619 // transition to error status.
7620 var chatResult database.Chat
7621 require.Eventually(t, func() bool {
7622 got, getErr := db.GetChatByID(ctx, chat.ID)
7623 if getErr != nil {
7624 return false
7625 }
7626 chatResult = got
7627 return got.Status == database.ChatStatusError
7628 }, testutil.WaitLong, testutil.IntervalFast)
7629
7630 persistedError := requireChatLastErrorPayload(t, chatResult.LastError)

Callers

nothing calls this directly

Calls 15

enablePanicMethod · 0.95
NewDBFunction · 0.92
NewOpenAIFunction · 0.92
OpenAIStreamingResponseFunction · 0.92
OpenAITextChunksFunction · 0.92
ContextFunction · 0.92
ChatMessageTextFunction · 0.92
newActiveTestServerFunction · 0.85
CreateChatMethod · 0.65

Tested by

no test coverage detected