| 72 | } |
| 73 | |
| 74 | func TestServer_Start_And_Shutdown(t *testing.T) { |
| 75 | port := freePort(t) |
| 76 | cfg := &Config{Host: "127.0.0.1", Port: port} |
| 77 | srv := New(cfg) |
| 78 | |
| 79 | ctx, cancel := context.WithCancel(context.Background()) |
| 80 | defer cancel() |
| 81 | |
| 82 | errCh := make(chan error, 1) |
| 83 | go func() { |
| 84 | errCh <- srv.Start(ctx) |
| 85 | }() |
| 86 | |
| 87 | // Poll until the server is accepting connections. |
| 88 | addr := fmt.Sprintf("http://127.0.0.1:%d/mcp", port) |
| 89 | ready := false |
| 90 | for i := 0; i < 50; i++ { |
| 91 | resp, err := http.Post(addr, "application/json", nil) |
| 92 | if err == nil { |
| 93 | resp.Body.Close() |
| 94 | ready = true |
| 95 | break |
| 96 | } |
| 97 | time.Sleep(50 * time.Millisecond) |
| 98 | } |
| 99 | if !ready { |
| 100 | t.Fatal("server did not become ready within timeout") |
| 101 | } |
| 102 | |
| 103 | // Cancel context to trigger graceful shutdown. |
| 104 | cancel() |
| 105 | |
| 106 | select { |
| 107 | case err := <-errCh: |
| 108 | if err != nil { |
| 109 | t.Fatalf("Start returned unexpected error: %v", err) |
| 110 | } |
| 111 | case <-time.After(5 * time.Second): |
| 112 | t.Fatal("server did not shut down within 5s") |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | func TestServer_Start_PortInUse(t *testing.T) { |
| 117 | // Occupy a port. |