Skip to content

Commit c25db9b

Browse files
committed
Added end2end test
1 parent 8af4b0b commit c25db9b

File tree

4 files changed

+51
-121
lines changed

4 files changed

+51
-121
lines changed

internal/transport/controlbuf.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -453,12 +453,6 @@ func (c *controlBuffer) finish() {
453453
c.mu.Unlock()
454454
}
455455

456-
func (c *controlBuffer) setError(err error) {
457-
c.mu.Lock()
458-
c.err = err
459-
c.mu.Unlock()
460-
}
461-
462456
type side int
463457

464458
const (

internal/transport/http2_client.go

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,6 @@ type http2Client struct {
117117
nextID uint32
118118
registeredCompressors string
119119

120-
// goAwaySent is initialised with http2Client and fired when client
121-
// transport is shutdown
122-
goAwaySent *grpcsync.Event
123-
124120
// Do not access controlBuf with mu held.
125121
mu sync.Mutex // guard the following variables
126122
state transportState
@@ -331,7 +327,6 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
331327
registeredCompressors: grpcutil.RegisteredCompressors(),
332328
address: addr,
333329
conn: conn,
334-
goAwaySent: grpcsync.NewEvent(),
335330
remoteAddr: conn.RemoteAddr(),
336331
localAddr: conn.LocalAddr(),
337332
authInfo: authInfo,
@@ -456,12 +451,15 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
456451
}
457452
go func() {
458453
t.loopy = newLoopyWriter(clientSide, t.framer, t.controlBuf, t.bdpEst, t.conn, t.logger)
459-
t.loopy.ssGoAwayHandler = t.outgoingGoAwayHandler
460454
if err := t.loopy.run(); !isIOError(err) {
461455
// Immediately close the connection, as the loopy writer returns
462456
// when there are no more active streams and we were draining (the
463457
// server sent a GOAWAY). For I/O errors, the reader will hit it
464458
// after draining any remaining incoming data.
459+
err = t.framer.fr.WriteGoAway(math.MaxUint32, http2.ErrCodeNo, []byte("GOAWAY from client"))
460+
if err != nil {
461+
t.logger.Infof("Failed writing goaway %v", err)
462+
}
465463
t.conn.Close()
466464
}
467465
close(t.writerDone)
@@ -514,20 +512,6 @@ func (t *http2Client) getPeer() *peer.Peer {
514512
}
515513
}
516514

517-
// Handles outgoing GoAway and returns true if loopy needs to put itself
518-
// in draining mode.
519-
func (t *http2Client) outgoingGoAwayHandler(g *goAway) (bool, error) {
520-
// Send out a GOAWAY frame so server is aware of client transport shutdown
521-
if err := t.framer.fr.WriteGoAway(math.MaxUint32, http2.ErrCodeNo, g.debugData); err != nil {
522-
return false, err
523-
}
524-
t.goAwaySent.Fire()
525-
if err := t.framer.fr.WritePing(false, goAwayPing.data); err != nil {
526-
return false, err
527-
}
528-
return false, nil
529-
}
530-
531515
func (t *http2Client) createHeaderFields(ctx context.Context, callHdr *CallHdr) ([]hpack.HeaderField, error) {
532516
aud := t.createAudience(callHdr)
533517
ri := credentials.RequestInfo{
@@ -1003,19 +987,6 @@ func (t *http2Client) Close(err error) {
1003987
}
1004988
t.mu.Unlock()
1005989
t.controlBuf.finish()
1006-
t.controlBuf.setError(nil)
1007-
err1 := t.controlBuf.put(&goAway{code: http2.ErrCodeNo, debugData: []byte("GOAWAY from client"), headsUp: true})
1008-
if err1 != nil {
1009-
t.logger.Infof("Failed to put goaway to server: %v\n", err1)
1010-
}
1011-
timer := time.NewTimer(2 * time.Second)
1012-
defer timer.Stop()
1013-
select {
1014-
case <-t.goAwaySent.Done():
1015-
case <-timer.C:
1016-
case <-t.ctx.Done():
1017-
}
1018-
t.controlBuf.setError(ErrConnClosing)
1019990
t.cancel()
1020991
t.conn.Close()
1021992
channelz.RemoveEntry(t.channelzID)

internal/transport/transport_test.go

Lines changed: 0 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,88 +1188,6 @@ func (s) TestServerConnDecoupledFromApplicationRead(t *testing.T) {
11881188

11891189
}
11901190

1191-
// Test that a transport level client shutdown successfully sends a GOAWAY frame
1192-
// to underlying connection.
1193-
func (s) TestClientSendsAGoAwayFrame(t *testing.T) {
1194-
// Create a server.
1195-
lis, err := net.Listen("tcp", "localhost:0")
1196-
if err != nil {
1197-
t.Fatalf("Error while listening: %v", err)
1198-
}
1199-
defer lis.Close()
1200-
// The success channel verifies that the server's reader goroutine received
1201-
// a GOAWAY frame from the client.
1202-
success := testutils.NewChannel()
1203-
// Launch the server.
1204-
go func() {
1205-
sconn, err := lis.Accept()
1206-
if err != nil {
1207-
t.Errorf("Error while accepting: %v", err)
1208-
}
1209-
defer sconn.Close()
1210-
if _, err := io.ReadFull(sconn, make([]byte, len(clientPreface))); err != nil {
1211-
t.Errorf("Error while writing settings ack: %v", err)
1212-
return
1213-
}
1214-
sfr := http2.NewFramer(sconn, sconn)
1215-
if err := sfr.WriteSettings(); err != nil {
1216-
t.Errorf("Error while writing settings %v", err)
1217-
return
1218-
}
1219-
if err := sfr.WriteSettingsAck(); err != nil {
1220-
t.Errorf("Error while writing settings ack %v", err)
1221-
return
1222-
}
1223-
1224-
// Read frames off the wire. Should expect to see a GOAWAY frame after
1225-
// the client closes.
1226-
for {
1227-
frame, err := sfr.ReadFrame()
1228-
if err != nil {
1229-
return
1230-
}
1231-
switch frame.(type) {
1232-
case *http2.SettingsFrame:
1233-
// Do nothing. A settings frame is expected from client preface.
1234-
case *http2.GoAwayFrame:
1235-
// Records that the server successfully received a GOAWAY frame.
1236-
success.Send(nil)
1237-
return
1238-
default:
1239-
// The client should have sent nothing but settings and GOAWAY frame.
1240-
success.Send(errors.New("the server received a frame other than settings or GOAWAY"))
1241-
return
1242-
}
1243-
}
1244-
}()
1245-
connectCtx, cancel := context.WithDeadline(context.Background(), time.Now().Add(5*time.Second))
1246-
defer cancel()
1247-
1248-
copts := ConnectOptions{ChannelzParentID: channelz.NewIdentifierForTesting(channelz.RefSubChannel, time.Now().Unix(), nil)}
1249-
ct, err := NewClientTransport(connectCtx, context.Background(), resolver.Address{Addr: lis.Addr().String()}, copts, func(GoAwayReason) {})
1250-
if err != nil {
1251-
t.Fatalf("Error while creating client transport: %v", err)
1252-
}
1253-
callHdr := &CallHdr{
1254-
Host: "localhost",
1255-
Method: "foo.Small",
1256-
}
1257-
s1, err1 := ct.NewStream(connectCtx, callHdr)
1258-
if err1 != nil {
1259-
t.Fatalf("failed to open stream: %v", err1)
1260-
}
1261-
if s1.id != 1 {
1262-
t.Fatalf("wrong stream id: %d", s1.id)
1263-
}
1264-
ct.Close(errors.New("manually closed by client"))
1265-
t.Logf("Closed the client connection")
1266-
if e, err := success.Receive(connectCtx); e != nil || err != nil {
1267-
t.Fatalf("Error in frame received: %v. Error receiving from channel: %v", e, err)
1268-
} else {
1269-
t.Logf("Server received the GOAWAY from client")
1270-
}
1271-
}
1272-
12731191
func (s) TestServerWithMisbehavedClient(t *testing.T) {
12741192
server := setUpServerOnly(t, 0, &ServerConfig{}, suspended)
12751193
defer server.stop()

test/goaway_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,3 +761,50 @@ func (s) TestTwoGoAwayPingFrames(t *testing.T) {
761761
t.Fatalf("Error waiting for graceful shutdown of the server: %v", err)
762762
}
763763
}
764+
765+
func (s) TestClientSendsAGoAwayFrame(t *testing.T) {
766+
lis, err := net.Listen("tcp", "localhost:0")
767+
if err != nil {
768+
t.Fatalf("Failed to listen: %v", err)
769+
}
770+
defer lis.Close()
771+
s := grpc.NewServer()
772+
defer s.Stop()
773+
go s.Serve(lis)
774+
775+
conn, err := net.DialTimeout("tcp", lis.Addr().String(), defaultTestTimeout)
776+
if err != nil {
777+
t.Fatalf("Failed to dial: %v", err)
778+
}
779+
780+
st := newServerTesterFromConn(t, conn)
781+
st.greet()
782+
goAwayFrameReceived := testutils.NewChannel()
783+
go func() {
784+
for {
785+
f, err := st.readFrame()
786+
if err != nil {
787+
return
788+
}
789+
switch f.(type) {
790+
case *http2.GoAwayFrame:
791+
t.Logf("Received GoAway Frame")
792+
goAwayFrameReceived.Send(nil)
793+
default:
794+
t.Logf("server tester received unexpected frame type %T", f)
795+
}
796+
}
797+
}()
798+
go func() {
799+
s.GracefulStop()
800+
}()
801+
ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
802+
defer cancel()
803+
if _, err := goAwayFrameReceived.Receive(ctx); err != nil {
804+
t.Fatalf("Error sending GOAWAY from client: %v", err)
805+
}
806+
// Write Ping
807+
st.writePing(true, [8]byte{1, 6, 1, 8, 0, 3, 3, 9})
808+
// Close the conn to finish up the Shutdown process.
809+
conn.Close()
810+
}

0 commit comments

Comments
 (0)