(t *testing.T)
| 2378 | } |
| 2379 | |
| 2380 | func TestStreamableSessionTimeout(t *testing.T) { |
| 2381 | // TODO: this test relies on timing and may be flaky. |
| 2382 | // Fixing with testing/synctest is challenging because it uses real I/O (via |
| 2383 | // httptest.NewServer). |
| 2384 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) |
| 2385 | defer cancel() |
| 2386 | |
| 2387 | server := NewServer(testImpl, nil) |
| 2388 | |
| 2389 | deleted := make(chan string, 1) |
| 2390 | handler := NewStreamableHTTPHandler( |
| 2391 | func(req *http.Request) *Server { return server }, |
| 2392 | &StreamableHTTPOptions{ |
| 2393 | SessionTimeout: 50 * time.Millisecond, |
| 2394 | }, |
| 2395 | ) |
| 2396 | handler.onTransportDeletion = func(sessionID string) { |
| 2397 | deleted <- sessionID |
| 2398 | } |
| 2399 | |
| 2400 | httpServer := httptest.NewServer(mustNotPanic(t, handler)) |
| 2401 | defer httpServer.Close() |
| 2402 | |
| 2403 | // Connect a client to create a session. |
| 2404 | client := NewClient(testImpl, nil) |
| 2405 | session, err := client.Connect(ctx, &StreamableClientTransport{Endpoint: httpServer.URL}, nil) |
| 2406 | if err != nil { |
| 2407 | t.Fatalf("client.Connect() failed: %v", err) |
| 2408 | } |
| 2409 | defer session.Close() |
| 2410 | |
| 2411 | sessionID := session.ID() |
| 2412 | if sessionID == "" { |
| 2413 | t.Fatal("client session has empty ID") |
| 2414 | } |
| 2415 | |
| 2416 | // Verify the session exists on the server. |
| 2417 | serverSessions := slices.Collect(server.Sessions()) |
| 2418 | if len(serverSessions) != 1 { |
| 2419 | t.Fatalf("got %d sessions, want 1", len(serverSessions)) |
| 2420 | } |
| 2421 | if got := serverSessions[0].ID(); got != sessionID { |
| 2422 | t.Fatalf("server session is %q, want %q", got, sessionID) |
| 2423 | } |
| 2424 | |
| 2425 | // Test that (possibly concurrent) requests keep the session alive. |
| 2426 | // |
| 2427 | // Spin up two goroutines, each making a request every 10ms. These requests |
| 2428 | // should keep the server from timing out. |
| 2429 | var wg sync.WaitGroup |
| 2430 | for range 2 { |
| 2431 | wg.Go(func() { |
| 2432 | for range 20 { |
| 2433 | if _, err := session.ListTools(ctx, nil); err != nil { |
| 2434 | t.Errorf("ListTools failed: %v", err) |
| 2435 | } |
| 2436 | time.Sleep(10 * time.Millisecond) |
| 2437 | } |
nothing calls this directly
no test coverage detected
searching dependent graphs…