Tests that GracefulStop will wait for all method handlers to return by blocking a handler and ensuring GracefulStop doesn't return until after it is unblocked.
(t *testing.T)
| 262 | // blocking a handler and ensuring GracefulStop doesn't return until after it is |
| 263 | // unblocked. |
| 264 | func (s) TestServer_GracefulStopWaits(t *testing.T) { |
| 265 | started := grpcsync.NewEvent() |
| 266 | blockCalls := grpcsync.NewEvent() |
| 267 | |
| 268 | // This stub server does not properly respect the stream context, so it will |
| 269 | // not exit when the context is canceled. |
| 270 | ss := stubserver.StubServer{ |
| 271 | FullDuplexCallF: func(testgrpc.TestService_FullDuplexCallServer) error { |
| 272 | started.Fire() |
| 273 | <-blockCalls.Done() |
| 274 | return nil |
| 275 | }, |
| 276 | } |
| 277 | if err := ss.Start(nil); err != nil { |
| 278 | t.Fatal("Error starting server:", err) |
| 279 | } |
| 280 | defer ss.Stop() |
| 281 | |
| 282 | ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) |
| 283 | defer cancel() |
| 284 | |
| 285 | // Start one RPC to the server. |
| 286 | ctx1, cancel1 := context.WithCancel(ctx) |
| 287 | _, err := ss.Client.FullDuplexCall(ctx1) |
| 288 | if err != nil { |
| 289 | t.Fatal("Error staring call:", err) |
| 290 | } |
| 291 | |
| 292 | // Wait for the handler to be invoked. |
| 293 | select { |
| 294 | case <-started.Done(): |
| 295 | case <-ctx.Done(): |
| 296 | t.Fatalf("Timed out waiting for RPC to start on server.") |
| 297 | } |
| 298 | |
| 299 | // Cancel it on the client. The server handler will still be running. |
| 300 | cancel1() |
| 301 | |
| 302 | // Close the connection. This might be sufficient to allow the server to |
| 303 | // return if it doesn't properly wait for outstanding method handlers to |
| 304 | // return. |
| 305 | ss.CC.Close() |
| 306 | |
| 307 | // Try to Stop() the server, which should block indefinitely (until |
| 308 | // blockCalls is fired). |
| 309 | stopped := grpcsync.NewEvent() |
| 310 | go func() { |
| 311 | ss.S.GracefulStop() |
| 312 | stopped.Fire() |
| 313 | }() |
| 314 | |
| 315 | // Wait 100ms and ensure stopped does not fire. |
| 316 | select { |
| 317 | case <-stopped.Done(): |
| 318 | trace := make([]byte, 4096) |
| 319 | trace = trace[0:runtime.Stack(trace, true)] |
| 320 | blockCalls.Fire() |
| 321 | t.Fatalf("Server returned from Stop() illegally. Stack trace:\n%v", string(trace)) |
nothing calls this directly
no test coverage detected