|
9 | 9 | "log" |
10 | 10 | "slices" |
11 | 11 | "testing" |
| 12 | + "time" |
12 | 13 |
|
13 | 14 | "github.com/google/go-cmp/cmp" |
14 | 15 | "github.com/google/jsonschema-go/jsonschema" |
@@ -371,3 +372,51 @@ func TestServerCapabilities(t *testing.T) { |
371 | 372 | }) |
372 | 373 | } |
373 | 374 | } |
| 375 | + |
| 376 | +// TestServerSessionkeepaliveCancelOverwritten is to verify that `ServerSession.keepaliveCancel` is assigned exactly once, |
| 377 | +// ensuring that only a single goroutine is responsible for the session's keepalive ping mechanism. |
| 378 | +func TestServerSessionkeepaliveCancelOverwritten(t *testing.T) { |
| 379 | + // Set KeepAlive to a long duration to ensure the keepalive |
| 380 | + // goroutine stays alive for the duration of the test without actually sending |
| 381 | + // ping requests, since we don't have a real client connection established. |
| 382 | + server := NewServer(testImpl, &ServerOptions{KeepAlive: 5 * time.Second}) |
| 383 | + ss := &ServerSession{server: server} |
| 384 | + |
| 385 | + // 1. Initialize the session. |
| 386 | + _, err := ss.initialize(context.Background(), &InitializeParams{}) |
| 387 | + if err != nil { |
| 388 | + t.Fatalf("ServerSession initialize failed: %v", err) |
| 389 | + } |
| 390 | + |
| 391 | + // 2. Call 'initialized' for the first time. This should start the keepalive mechanism. |
| 392 | + _, err = ss.initialized(context.Background(), &InitializedParams{}) |
| 393 | + if err != nil { |
| 394 | + t.Fatalf("First initialized call failed: %v", err) |
| 395 | + } |
| 396 | + if ss.keepaliveCancel == nil { |
| 397 | + t.Fatalf("expected ServerSession.keepaliveCancel to be set after the first call of initialized") |
| 398 | + } |
| 399 | + |
| 400 | + // Save the cancel function and use defer to ensure resources are cleaned up. |
| 401 | + firstCancel := ss.keepaliveCancel |
| 402 | + defer firstCancel() |
| 403 | + |
| 404 | + // 3. Manually set the field to nil. |
| 405 | + // Do this to facilitate the test's core assertion. The goal is to verify that |
| 406 | + // 'ss.keepaliveCancel' is not assigned a second time. By setting it to nil, |
| 407 | + // we can easily check after the next call if a new keepalive goroutine was started. |
| 408 | + ss.keepaliveCancel = nil |
| 409 | + |
| 410 | + // 4. Call 'initialized' for the second time. This should return an error. |
| 411 | + _, err = ss.initialized(context.Background(), &InitializedParams{}) |
| 412 | + if err == nil { |
| 413 | + t.Fatalf("Expected 'duplicate initialized received' error on second call, got nil") |
| 414 | + } |
| 415 | + |
| 416 | + // 5. Re-check the field to ensure it remains nil. |
| 417 | + // Since 'initialized' correctly returned an error and did not call |
| 418 | + // 'startKeepalive', the field should remain unchanged. |
| 419 | + if ss.keepaliveCancel != nil { |
| 420 | + t.Fatal("expected ServerSession.keepaliveCancel to be nil after we manually niled it and re-initialized") |
| 421 | + } |
| 422 | +} |
0 commit comments