TestMCPServerOAuth2TokenRefreshFailureGraceful verifies that when the OAuth2 token endpoint is down, the chat still proceeds without the MCP server's tools. The expired token is preserved unchanged.
(t *testing.T)
| 8328 | // the OAuth2 token endpoint is down, the chat still proceeds without |
| 8329 | // the MCP server's tools. The expired token is preserved unchanged. |
| 8330 | func TestMCPServerOAuth2TokenRefreshFailureGraceful(t *testing.T) { |
| 8331 | t.Parallel() |
| 8332 | |
| 8333 | db, ps := dbtestutil.NewDB(t) |
| 8334 | ctx := testutil.Context(t, testutil.WaitLong) |
| 8335 | |
| 8336 | // Token endpoint that always returns an error. |
| 8337 | tokenSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { |
| 8338 | w.Header().Set("Content-Type", "application/json") |
| 8339 | w.WriteHeader(http.StatusBadGateway) |
| 8340 | _, _ = w.Write([]byte(`{"error":"server_error","error_description":"token endpoint unavailable"}`)) |
| 8341 | })) |
| 8342 | t.Cleanup(tokenSrv.Close) |
| 8343 | |
| 8344 | // The LLM just replies with text, no tool calls. |
| 8345 | var callCount atomic.Int32 |
| 8346 | openAIURL := chattest.NewOpenAI(t, func(req *chattest.OpenAIRequest) chattest.OpenAIResponse { |
| 8347 | if !req.Stream { |
| 8348 | return chattest.OpenAINonStreamingResponse("title") |
| 8349 | } |
| 8350 | callCount.Add(1) |
| 8351 | return chattest.OpenAIStreamingResponse( |
| 8352 | chattest.OpenAITextChunks("I responded without MCP tools.")..., |
| 8353 | ) |
| 8354 | }) |
| 8355 | |
| 8356 | user, org, model := seedChatDependenciesWithProvider(t, db, "openai-compat", openAIURL) |
| 8357 | |
| 8358 | mcpConfig := dbgen.MCPServerConfig(t, db, database.MCPServerConfig{ |
| 8359 | DisplayName: "Broken MCP", |
| 8360 | Slug: "broken-mcp", |
| 8361 | Url: "http://127.0.0.1:0/does-not-exist", |
| 8362 | AuthType: "oauth2", |
| 8363 | OAuth2ClientID: "test-client-id", |
| 8364 | OAuth2TokenURL: tokenSrv.URL, |
| 8365 | CreatedBy: uuid.NullUUID{UUID: user.ID, Valid: true}, |
| 8366 | UpdatedBy: uuid.NullUUID{UUID: user.ID, Valid: true}, |
| 8367 | }) |
| 8368 | _, err := db.UpsertMCPServerUserToken(ctx, database.UpsertMCPServerUserTokenParams{ |
| 8369 | MCPServerConfigID: mcpConfig.ID, |
| 8370 | UserID: user.ID, |
| 8371 | AccessToken: "old-expired-token", |
| 8372 | RefreshToken: "old-refresh-token", |
| 8373 | TokenType: "Bearer", |
| 8374 | Expiry: sql.NullTime{Time: time.Now().Add(-1 * time.Hour), Valid: true}, |
| 8375 | }) |
| 8376 | |
| 8377 | require.NoError(t, err) |
| 8378 | |
| 8379 | server := newActiveTestServer(t, db, ps) |
| 8380 | |
| 8381 | chat, err := server.CreateChat(ctx, chatd.CreateOptions{ |
| 8382 | OrganizationID: org.ID, |
| 8383 | OwnerID: user.ID, |
| 8384 | Title: "graceful-degradation-test", |
| 8385 | ModelConfigID: model.ID, |
| 8386 | MCPServerIDs: []uuid.UUID{mcpConfig.ID}, |
| 8387 | InitialUserContent: []codersdk.ChatMessagePart{ |
nothing calls this directly
no test coverage detected