Repository: grpc/grpc-go
File: test/gracefulstop_test.go (Go)

Code before:
func (s) TestGracefulStop(t *testing.T) {
	lis, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		t.Fatalf("Error listenening: %v", err)
	}
	dlis := &delayListener{
		Listener:     lis,
		acceptCalled: make(chan struct{}),
		closeCalled:  make(chan struct{}),
		allowCloseCh: make(chan struct{}),
	}

	ss := &stubserver.StubServer{
		Listener: dlis,
		FullDuplexCallF: func(stream testgrpc.TestService_FullDuplexCallServer) error {
			_, err := stream.Recv()
			if err != nil {
				return err
			}
			return stream.Send(&testpb.StreamingOutputCallResponse{})
		},
		S: grpc.NewServer(),
	}
	stubserver.StartTestService(t, ss)

	// 1. Start Server
	gracefulStopDone := make(chan struct{})
	<-dlis.acceptCalled
	go func() {
		ss.S.GracefulStop()
		close(gracefulStopDone)
	}()
	// 2. GracefulStop() Server after listener's Accept is called, but don't
	//    allow Accept() to exit when Close() is called on it.

	// 3. Create a new connection to the server after listener.Close() is called.
	//    Server should close this connection immediately, before handshaking.

	<-dlis.closeCalled // Block until GracefulStop calls dlis.Close()

	// Now dial.  The listener's Accept method will return a valid connection,
	// even though GracefulStop has closed the listener.
	ctx, dialCancel := context.WithTimeout(context.Background(), defaultTestTimeout)
	defer dialCancel()
	dialer := func(ctx context.Context, _ string) (net.Conn, error) { return dlis.Dial(ctx) }
	cc, err := grpc.DialContext(ctx, "", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithContextDialer(dialer))
	if err != nil {
		t.Fatalf("grpc.DialContext(_, %q, _) = %v", lis.Addr().String(), err)
	}
	client := testgrpc.NewTestServiceClient(cc)
	defer cc.Close()

Review comment (suggestion):
Step number 1 is now happening as part of the call to `stubserver.StartTestService`. So, this comment needs to move there.

Code after:
func (s) TestGracefulStop(t *testing.T) {
	lis, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		t.Fatalf("Error listenening: %v", err)
	}
	dlis := &delayListener{
		Listener:     lis,
		acceptCalled: make(chan struct{}),
		closeCalled:  make(chan struct{}),
		allowCloseCh: make(chan struct{}),
	}

	ss := &stubserver.StubServer{
		Listener: dlis,
		FullDuplexCallF: func(stream testgrpc.TestService_FullDuplexCallServer) error {
			if _, err := stream.Recv(); err != nil {
				return err
			}
			return stream.Send(&testpb.StreamingOutputCallResponse{})
		},
		S: grpc.NewServer(),
	}
	// 1. Start Server and start serving by calling Serve().
	stubserver.StartTestService(t, ss)

	// 2. Call GracefulStop from a goroutine. It will trigger Close on the
	// listener, but the listener will not actually close until a connection
	// is accepted.
	gracefulStopDone := make(chan struct{})
	<-dlis.acceptCalled
	go func() {
		ss.S.GracefulStop()
		close(gracefulStopDone)
	}()

	// 3. Create a new connection to the server after listener.Close() is called.
	// Server should close this connection immediately, before handshaking.

	<-dlis.closeCalled // Block until GracefulStop calls dlis.Close()

	// Dial the server. This will cause a connection to be accepted. This will
	// also unblock the Close method .
	ctx, dialCancel := context.WithTimeout(context.Background(), defaultTestTimeout)
	defer dialCancel()
	dialer := func(ctx context.Context, _ string) (net.Conn, error) { return dlis.Dial(ctx) }
	cc, err := grpc.DialContext(ctx, "", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithContextDialer(dialer))
	if err != nil {
		t.Fatalf("grpc.DialContext(_, %q, _) = %v", lis.Addr().String(), err)
	}
	client := testgrpc.NewTestServiceClient(cc)
	defer cc.Close()