Skip to content

Commit 9060382

Browse files
fraenkelBryan C. Mills
authored and
Bryan C. Mills
committed
http2: rework Ping test to rely less on timing
Pings are either expected to occur, so count until you reach your goal before a deadline, or they do not occur, and the deadline is exceeded. Fixes golang/go#42514 Change-Id: If9ff19ed4954bee83ddeba83a4ac9c2d43f6e1c1 Reviewed-on: https://go-review.googlesource.com/c/net/+/269797 Trust: Bryan C. Mills <[email protected]> Trust: Damien Neil <[email protected]> Run-TryBot: Bryan C. Mills <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Damien Neil <[email protected]>
1 parent 5f55cee commit 9060382

File tree

1 file changed

+35
-62
lines changed

1 file changed

+35
-62
lines changed

http2/transport_test.go

Lines changed: 35 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -3393,63 +3393,54 @@ func TestTransportCloseAfterLostPing(t *testing.T) {
33933393

33943394
func TestTransportPingWhenReading(t *testing.T) {
33953395
testCases := []struct {
3396-
name string
3397-
readIdleTimeout time.Duration
3398-
serverResponseInterval time.Duration
3399-
expectedPingCount int
3396+
name string
3397+
readIdleTimeout time.Duration
3398+
deadline time.Duration
3399+
expectedPingCount int
34003400
}{
34013401
{
3402-
name: "two pings in each serverResponseInterval",
3403-
readIdleTimeout: 400 * time.Millisecond,
3404-
serverResponseInterval: 1000 * time.Millisecond,
3405-
expectedPingCount: 4,
3402+
name: "two pings",
3403+
readIdleTimeout: 100 * time.Millisecond,
3404+
deadline: time.Second,
3405+
expectedPingCount: 2,
34063406
},
34073407
{
3408-
name: "one ping in each serverResponseInterval",
3409-
readIdleTimeout: 700 * time.Millisecond,
3410-
serverResponseInterval: 1000 * time.Millisecond,
3411-
expectedPingCount: 2,
3408+
name: "zero ping",
3409+
readIdleTimeout: time.Second,
3410+
deadline: 200 * time.Millisecond,
3411+
expectedPingCount: 0,
34123412
},
34133413
{
3414-
name: "zero ping in each serverResponseInterval",
3415-
readIdleTimeout: 1000 * time.Millisecond,
3416-
serverResponseInterval: 500 * time.Millisecond,
3417-
expectedPingCount: 0,
3418-
},
3419-
{
3420-
name: "0 readIdleTimeout means no ping",
3421-
readIdleTimeout: 0 * time.Millisecond,
3422-
serverResponseInterval: 500 * time.Millisecond,
3423-
expectedPingCount: 0,
3414+
name: "0 readIdleTimeout means no ping",
3415+
readIdleTimeout: 0 * time.Millisecond,
3416+
deadline: 500 * time.Millisecond,
3417+
expectedPingCount: 0,
34243418
},
34253419
}
34263420

34273421
for _, tc := range testCases {
34283422
tc := tc // capture range variable
34293423
t.Run(tc.name, func(t *testing.T) {
3430-
t.Parallel()
3431-
testTransportPingWhenReading(t, tc.readIdleTimeout, tc.serverResponseInterval, tc.expectedPingCount)
3424+
testTransportPingWhenReading(t, tc.readIdleTimeout, tc.deadline, tc.expectedPingCount)
34323425
})
34333426
}
34343427
}
34353428

3436-
func testTransportPingWhenReading(t *testing.T, readIdleTimeout, serverResponseInterval time.Duration, expectedPingCount int) {
3429+
func testTransportPingWhenReading(t *testing.T, readIdleTimeout, deadline time.Duration, expectedPingCount int) {
34373430
var pingCount int
3438-
clientDone := make(chan struct{})
34393431
ct := newClientTester(t)
34403432
ct.tr.PingTimeout = 10 * time.Millisecond
34413433
ct.tr.ReadIdleTimeout = readIdleTimeout
3442-
// guards the ct.fr.Write
3443-
var wmu sync.Mutex
34443434

3435+
ctx, cancel := context.WithTimeout(context.Background(), deadline)
3436+
defer cancel()
34453437
ct.client = func() error {
34463438
defer ct.cc.(*net.TCPConn).CloseWrite()
34473439
if runtime.GOOS == "plan9" {
34483440
// CloseWrite not supported on Plan 9; Issue 17906
34493441
defer ct.cc.(*net.TCPConn).Close()
34503442
}
3451-
defer close(clientDone)
3452-
req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
3443+
req, _ := http.NewRequestWithContext(ctx, "GET", "https://dummy.tld/", nil)
34533444
res, err := ct.tr.RoundTrip(req)
34543445
if err != nil {
34553446
return fmt.Errorf("RoundTrip: %v", err)
@@ -3459,20 +3450,24 @@ func testTransportPingWhenReading(t *testing.T, readIdleTimeout, serverResponseI
34593450
return fmt.Errorf("status code = %v; want %v", res.StatusCode, 200)
34603451
}
34613452
_, err = ioutil.ReadAll(res.Body)
3453+
if expectedPingCount == 0 && errors.Is(ctx.Err(), context.DeadlineExceeded) {
3454+
return nil
3455+
}
3456+
3457+
cancel()
34623458
return err
34633459
}
34643460

34653461
ct.server = func() error {
34663462
ct.greet()
34673463
var buf bytes.Buffer
34683464
enc := hpack.NewEncoder(&buf)
3469-
var wg sync.WaitGroup
3470-
defer wg.Wait()
3465+
var streamID uint32
34713466
for {
34723467
f, err := ct.fr.ReadFrame()
34733468
if err != nil {
34743469
select {
3475-
case <-clientDone:
3470+
case <-ctx.Done():
34763471
// If the client's done, it
34773472
// will have reported any
34783473
// errors on its side.
@@ -3494,46 +3489,24 @@ func testTransportPingWhenReading(t *testing.T, readIdleTimeout, serverResponseI
34943489
EndStream: false,
34953490
BlockFragment: buf.Bytes(),
34963491
})
3497-
3498-
wg.Add(1)
3499-
go func() {
3500-
defer wg.Done()
3501-
for i := 0; i < 2; i++ {
3502-
wmu.Lock()
3503-
if err := ct.fr.WriteData(f.StreamID, false, []byte(fmt.Sprintf("hello, this is server data frame %d", i))); err != nil {
3504-
wmu.Unlock()
3505-
t.Error(err)
3506-
return
3507-
}
3508-
wmu.Unlock()
3509-
time.Sleep(serverResponseInterval)
3510-
}
3511-
wmu.Lock()
3512-
if err := ct.fr.WriteData(f.StreamID, true, []byte("hello, this is last server data frame")); err != nil {
3513-
wmu.Unlock()
3514-
t.Error(err)
3515-
return
3516-
}
3517-
wmu.Unlock()
3518-
}()
3492+
streamID = f.StreamID
35193493
case *PingFrame:
35203494
pingCount++
3521-
wmu.Lock()
3495+
if pingCount == expectedPingCount {
3496+
if err := ct.fr.WriteData(streamID, true, []byte("hello, this is last server data frame")); err != nil {
3497+
return err
3498+
}
3499+
}
35223500
if err := ct.fr.WritePing(true, f.Data); err != nil {
3523-
wmu.Unlock()
35243501
return err
35253502
}
3526-
wmu.Unlock()
3503+
case *RSTStreamFrame:
35273504
default:
35283505
return fmt.Errorf("Unexpected client frame %v", f)
35293506
}
35303507
}
35313508
}
35323509
ct.run()
3533-
if e, a := expectedPingCount, pingCount; e != a {
3534-
t.Errorf("expected receiving %d pings, got %d pings", e, a)
3535-
3536-
}
35373510
}
35383511

35393512
func TestTransportRetryAfterGOAWAY(t *testing.T) {

0 commit comments

Comments
 (0)