Skip to content

Commit

Permalink
tests: add server.Stop() and server.GracefulStop testcases
Browse files Browse the repository at this point in the history
Add 2 testcases that ensure that:
- GracefulStop blocks and waits until ongoing client grpc calls finis,
- Stop() returns despite ongoing blocking grpc calls and clients receive
  a connection error
  • Loading branch information
fho committed Oct 26, 2023
1 parent 8a58769 commit e85749a
Showing 1 changed file with 88 additions and 0 deletions.
88 changes: 88 additions & 0 deletions test/gracefulstop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"net"
"sync"
"testing"
"time"

"golang.org/x/net/http2"
"google.golang.org/grpc"
Expand Down Expand Up @@ -216,3 +217,90 @@ func (s) TestGracefulStopClosesConnAfterLastStream(t *testing.T) {
<-gracefulStopDone // Wait for GracefulStop to return.
})
}

func (s) TestGracefulStopBlocksUntilGRPCConnectionsTerminate(t *testing.T) {
// This tests ensures that GracefulStop() blocks until all ongoing
// client grpc-calls finished.
unblockGRPCCall := make(chan struct{})
grpcCallExecuting := make(chan struct{})
ss := &stubserver.StubServer{
UnaryCallF: func(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) {
close(grpcCallExecuting)
<-unblockGRPCCall
return &testpb.SimpleResponse{}, nil
},
}

err := ss.Start(nil)
if err != nil {
t.Fatalf("StubServer.start failed: %s", err)
}
t.Cleanup(ss.Stop)

grpcClientCallReturned := make(chan struct{})
go func() {
clt := ss.Client
_, err := clt.UnaryCall(context.Background(), &testpb.SimpleRequest{})
if err != nil {
t.Errorf("grpc call failed with error: %s", err)
}
close(grpcClientCallReturned)
}()

gracefulStopReturned := make(chan struct{})
<-grpcCallExecuting
go func() {
ss.S.GracefulStop()
close(gracefulStopReturned)
}()

time.Sleep(time.Second)
select {
case <-gracefulStopReturned:
t.Error("GracefulStop returned before GRPC method call ended")
default:
}

unblockGRPCCall <- struct{}{}
<-grpcClientCallReturned
<-gracefulStopReturned
}

func (s) TestStopAbortsBlockingGAbortsBlockingGRPCCall(t *testing.T) {
// This tests ensures that when Stop() is called while an ongoing grpc
// call is blocking that:
// - Stop() returns
// - and grpc-call on the client side fails with an connection closed
// error
unblockGRPCCall := make(chan struct{})
grpcCallExecuting := make(chan struct{})
ss := &stubserver.StubServer{
UnaryCallF: func(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) {
close(grpcCallExecuting)
<-unblockGRPCCall
return &testpb.SimpleResponse{}, nil
},
}

err := ss.Start(nil)
if err != nil {
t.Fatalf("StubServer.start failed: %s", err)
}
t.Cleanup(ss.Stop)

grpcClientCallReturned := make(chan struct{})
go func() {
clt := ss.Client
_, err := clt.UnaryCall(context.Background(), &testpb.SimpleRequest{})
if err == nil || !isConnClosedErr(err) {
t.Errorf("expected grpc call to fail with connection closed error, got: %v", err)
}
close(grpcClientCallReturned)
}()

<-grpcCallExecuting
ss.S.Stop()

unblockGRPCCall <- struct{}{}
<-grpcClientCallReturned
}

0 comments on commit e85749a

Please sign in to comment.