123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725 |
- /*
- *
- * Copyright 2019 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
- // This file contains tests related to the following proposals:
- // https://github.com/grpc/proposal/blob/master/A8-client-side-keepalive.md
- // https://github.com/grpc/proposal/blob/master/A9-server-side-conn-mgt.md
- // https://github.com/grpc/proposal/blob/master/A18-tcp-user-timeout.md
- package transport
- import (
- "context"
- "fmt"
- "io"
- "net"
- "strings"
- "testing"
- "time"
- "golang.org/x/net/http2"
- "google.golang.org/grpc/internal/channelz"
- "google.golang.org/grpc/internal/grpctest"
- "google.golang.org/grpc/internal/syscall"
- "google.golang.org/grpc/keepalive"
- )
- const defaultTestTimeout = 10 * time.Second
- // TestMaxConnectionIdle tests that a server will send GoAway to an idle
- // client. An idle client is one who doesn't make any RPC calls for a duration
- // of MaxConnectionIdle time.
- func (s) TestMaxConnectionIdle(t *testing.T) {
- serverConfig := &ServerConfig{
- KeepaliveParams: keepalive.ServerParameters{
- MaxConnectionIdle: 30 * time.Millisecond,
- },
- }
- server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{})
- defer func() {
- client.Close(fmt.Errorf("closed manually by test"))
- server.stop()
- cancel()
- }()
- ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
- defer cancel()
- stream, err := client.NewStream(ctx, &CallHdr{})
- if err != nil {
- t.Fatalf("client.NewStream() failed: %v", err)
- }
- client.CloseStream(stream, io.EOF)
- // Verify the server sends a GoAway to client after MaxConnectionIdle timeout
- // kicks in.
- select {
- case <-ctx.Done():
- t.Fatalf("context expired before receiving GoAway from the server.")
- case <-client.GoAway():
- reason, debugMsg := client.GetGoAwayReason()
- if reason != GoAwayNoReason {
- t.Fatalf("GoAwayReason is %v, want %v", reason, GoAwayNoReason)
- }
- if !strings.Contains(debugMsg, "max_idle") {
- t.Fatalf("GoAwayDebugMessage is %v, want %v", debugMsg, "max_idle")
- }
- }
- }
- // TestMaxConnectionIdleBusyClient tests that a server will not send GoAway to
- // a busy client.
- func (s) TestMaxConnectionIdleBusyClient(t *testing.T) {
- serverConfig := &ServerConfig{
- KeepaliveParams: keepalive.ServerParameters{
- MaxConnectionIdle: 100 * time.Millisecond,
- },
- }
- server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{})
- defer func() {
- client.Close(fmt.Errorf("closed manually by test"))
- server.stop()
- cancel()
- }()
- ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
- defer cancel()
- _, err := client.NewStream(ctx, &CallHdr{})
- if err != nil {
- t.Fatalf("client.NewStream() failed: %v", err)
- }
- // Verify the server does not send a GoAway to client even after MaxConnectionIdle
- // timeout kicks in.
- ctx, cancel = context.WithTimeout(context.Background(), time.Second)
- defer cancel()
- select {
- case <-client.GoAway():
- t.Fatalf("A busy client received a GoAway.")
- case <-ctx.Done():
- }
- }
- // TestMaxConnectionAge tests that a server will send GoAway after a duration
- // of MaxConnectionAge.
- func (s) TestMaxConnectionAge(t *testing.T) {
- maxConnAge := 100 * time.Millisecond
- serverConfig := &ServerConfig{
- KeepaliveParams: keepalive.ServerParameters{
- MaxConnectionAge: maxConnAge,
- MaxConnectionAgeGrace: 10 * time.Millisecond,
- },
- }
- server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{})
- defer func() {
- client.Close(fmt.Errorf("closed manually by test"))
- server.stop()
- cancel()
- }()
- ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
- defer cancel()
- if _, err := client.NewStream(ctx, &CallHdr{}); err != nil {
- t.Fatalf("client.NewStream() failed: %v", err)
- }
- // Verify the server sends a GoAway to client even after client remains idle
- // for more than MaxConnectionIdle time.
- select {
- case <-client.GoAway():
- reason, debugMsg := client.GetGoAwayReason()
- if reason != GoAwayNoReason {
- t.Fatalf("GoAwayReason is %v, want %v", reason, GoAwayNoReason)
- }
- if !strings.Contains(debugMsg, "max_age") {
- t.Fatalf("GoAwayDebugMessage is %v, want %v", debugMsg, "max_age")
- }
- case <-ctx.Done():
- t.Fatalf("timed out before getting a GoAway from the server.")
- }
- }
- const (
- defaultWriteBufSize = 32 * 1024
- defaultReadBufSize = 32 * 1024
- )
- // TestKeepaliveServerClosesUnresponsiveClient tests that a server closes
- // the connection with a client that doesn't respond to keepalive pings.
- //
- // This test creates a regular net.Conn connection to the server and sends the
- // clientPreface and the initial Settings frame, and then remains unresponsive.
- func (s) TestKeepaliveServerClosesUnresponsiveClient(t *testing.T) {
- serverConfig := &ServerConfig{
- KeepaliveParams: keepalive.ServerParameters{
- Time: 100 * time.Millisecond,
- Timeout: 10 * time.Millisecond,
- },
- }
- server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{})
- defer func() {
- client.Close(fmt.Errorf("closed manually by test"))
- server.stop()
- cancel()
- }()
- addr := server.addr()
- conn, err := net.Dial("tcp", addr)
- if err != nil {
- t.Fatalf("net.Dial(tcp, %v) failed: %v", addr, err)
- }
- defer conn.Close()
- if n, err := conn.Write(clientPreface); err != nil || n != len(clientPreface) {
- t.Fatalf("conn.Write(clientPreface) failed: n=%v, err=%v", n, err)
- }
- framer := newFramer(conn, defaultWriteBufSize, defaultReadBufSize, 0)
- if err := framer.fr.WriteSettings(http2.Setting{}); err != nil {
- t.Fatal("framer.WriteSettings(http2.Setting{}) failed:", err)
- }
- framer.writer.Flush()
- // We read from the net.Conn till we get an error, which is expected when
- // the server closes the connection as part of the keepalive logic.
- errCh := make(chan error, 1)
- go func() {
- b := make([]byte, 24)
- for {
- if _, err = conn.Read(b); err != nil {
- errCh <- err
- return
- }
- }
- }()
- // Server waits for KeepaliveParams.Time seconds before sending out a ping,
- // and then waits for KeepaliveParams.Timeout for a ping ack.
- ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
- defer cancel()
- select {
- case err := <-errCh:
- if err != io.EOF {
- t.Fatalf("client.Read(_) = _,%v, want io.EOF", err)
- }
- case <-ctx.Done():
- t.Fatalf("Test timed out before server closed the connection.")
- }
- }
- // TestKeepaliveServerWithResponsiveClient tests that a server doesn't close
- // the connection with a client that responds to keepalive pings.
- func (s) TestKeepaliveServerWithResponsiveClient(t *testing.T) {
- serverConfig := &ServerConfig{
- KeepaliveParams: keepalive.ServerParameters{
- Time: 100 * time.Millisecond,
- Timeout: 100 * time.Millisecond,
- },
- }
- server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{})
- defer func() {
- client.Close(fmt.Errorf("closed manually by test"))
- server.stop()
- cancel()
- }()
- // Give keepalive logic some time by sleeping.
- time.Sleep(500 * time.Millisecond)
- if err := checkForHealthyStream(client); err != nil {
- t.Fatalf("Stream creation failed: %v", err)
- }
- }
- // TestKeepaliveClientClosesUnresponsiveServer creates a server which does not
- // respond to keepalive pings, and makes sure that the client closes the
- // transport once the keepalive logic kicks in. Here, we set the
- // `PermitWithoutStream` parameter to true which ensures that the keepalive
- // logic is running even without any active streams.
- func (s) TestKeepaliveClientClosesUnresponsiveServer(t *testing.T) {
- connCh := make(chan net.Conn, 1)
- copts := ConnectOptions{
- ChannelzParentID: channelz.NewIdentifierForTesting(channelz.RefSubChannel, time.Now().Unix(), nil),
- KeepaliveParams: keepalive.ClientParameters{
- Time: 10 * time.Millisecond,
- Timeout: 10 * time.Millisecond,
- PermitWithoutStream: true,
- },
- }
- client, cancel := setUpWithNoPingServer(t, copts, connCh)
- defer cancel()
- defer client.Close(fmt.Errorf("closed manually by test"))
- conn, ok := <-connCh
- if !ok {
- t.Fatalf("Server didn't return connection object")
- }
- defer conn.Close()
- if err := pollForStreamCreationError(client); err != nil {
- t.Fatal(err)
- }
- }
- // TestKeepaliveClientOpenWithUnresponsiveServer creates a server which does
- // not respond to keepalive pings, and makes sure that the client does not
- // close the transport. Here, we do not set the `PermitWithoutStream` parameter
- // to true which ensures that the keepalive logic is turned off without any
- // active streams, and therefore the transport stays open.
- func (s) TestKeepaliveClientOpenWithUnresponsiveServer(t *testing.T) {
- connCh := make(chan net.Conn, 1)
- copts := ConnectOptions{
- ChannelzParentID: channelz.NewIdentifierForTesting(channelz.RefSubChannel, time.Now().Unix(), nil),
- KeepaliveParams: keepalive.ClientParameters{
- Time: 10 * time.Millisecond,
- Timeout: 10 * time.Millisecond,
- },
- }
- client, cancel := setUpWithNoPingServer(t, copts, connCh)
- defer cancel()
- defer client.Close(fmt.Errorf("closed manually by test"))
- conn, ok := <-connCh
- if !ok {
- t.Fatalf("Server didn't return connection object")
- }
- defer conn.Close()
- // Give keepalive some time.
- time.Sleep(500 * time.Millisecond)
- if err := checkForHealthyStream(client); err != nil {
- t.Fatalf("Stream creation failed: %v", err)
- }
- }
- // TestKeepaliveClientClosesWithActiveStreams creates a server which does not
- // respond to keepalive pings, and makes sure that the client closes the
- // transport even when there is an active stream.
- func (s) TestKeepaliveClientClosesWithActiveStreams(t *testing.T) {
- connCh := make(chan net.Conn, 1)
- copts := ConnectOptions{
- ChannelzParentID: channelz.NewIdentifierForTesting(channelz.RefSubChannel, time.Now().Unix(), nil),
- KeepaliveParams: keepalive.ClientParameters{
- Time: 500 * time.Millisecond,
- Timeout: 500 * time.Millisecond,
- },
- }
- // TODO(i/6099): Setup a server which can ping and no-ping based on a flag to
- // reduce the flakiness in this test.
- client, cancel := setUpWithNoPingServer(t, copts, connCh)
- defer cancel()
- defer client.Close(fmt.Errorf("closed manually by test"))
- conn, ok := <-connCh
- if !ok {
- t.Fatalf("Server didn't return connection object")
- }
- defer conn.Close()
- ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
- defer cancel()
- // Create a stream, but send no data on it.
- if _, err := client.NewStream(ctx, &CallHdr{}); err != nil {
- t.Fatalf("Stream creation failed: %v", err)
- }
- if err := pollForStreamCreationError(client); err != nil {
- t.Fatal(err)
- }
- }
- // TestKeepaliveClientStaysHealthyWithResponsiveServer creates a server which
- // responds to keepalive pings, and makes sure than a client transport stays
- // healthy without any active streams.
- func (s) TestKeepaliveClientStaysHealthyWithResponsiveServer(t *testing.T) {
- server, client, cancel := setUpWithOptions(t, 0,
- &ServerConfig{
- KeepalivePolicy: keepalive.EnforcementPolicy{
- MinTime: 50 * time.Millisecond,
- PermitWithoutStream: true,
- },
- },
- normal,
- ConnectOptions{
- KeepaliveParams: keepalive.ClientParameters{
- Time: 55 * time.Millisecond,
- Timeout: time.Second,
- PermitWithoutStream: true,
- }})
- defer func() {
- client.Close(fmt.Errorf("closed manually by test"))
- server.stop()
- cancel()
- }()
- // Give keepalive some time.
- time.Sleep(500 * time.Millisecond)
- if err := checkForHealthyStream(client); err != nil {
- t.Fatalf("Stream creation failed: %v", err)
- }
- }
- // TestKeepaliveClientFrequency creates a server which expects at most 1 client
- // ping for every 100 ms, while the client is configured to send a ping
- // every 50 ms. So, this configuration should end up with the client
- // transport being closed. But we had a bug wherein the client was sending one
- // ping every [Time+Timeout] instead of every [Time] period, and this test
- // explicitly makes sure the fix works and the client sends a ping every [Time]
- // period.
- func (s) TestKeepaliveClientFrequency(t *testing.T) {
- grpctest.TLogger.ExpectError("Client received GoAway with error code ENHANCE_YOUR_CALM and debug data equal to ASCII \"too_many_pings\"")
- serverConfig := &ServerConfig{
- KeepalivePolicy: keepalive.EnforcementPolicy{
- MinTime: 100 * time.Millisecond,
- PermitWithoutStream: true,
- },
- }
- clientOptions := ConnectOptions{
- KeepaliveParams: keepalive.ClientParameters{
- Time: 50 * time.Millisecond,
- Timeout: time.Second,
- PermitWithoutStream: true,
- },
- }
- server, client, cancel := setUpWithOptions(t, 0, serverConfig, normal, clientOptions)
- defer func() {
- client.Close(fmt.Errorf("closed manually by test"))
- server.stop()
- cancel()
- }()
- if err := waitForGoAwayTooManyPings(client); err != nil {
- t.Fatal(err)
- }
- }
- // TestKeepaliveServerEnforcementWithAbusiveClientNoRPC verifies that the
- // server closes a client transport when it sends too many keepalive pings
- // (when there are no active streams), based on the configured
- // EnforcementPolicy.
- func (s) TestKeepaliveServerEnforcementWithAbusiveClientNoRPC(t *testing.T) {
- grpctest.TLogger.ExpectError("Client received GoAway with error code ENHANCE_YOUR_CALM and debug data equal to ASCII \"too_many_pings\"")
- serverConfig := &ServerConfig{
- KeepalivePolicy: keepalive.EnforcementPolicy{
- MinTime: time.Second,
- },
- }
- clientOptions := ConnectOptions{
- KeepaliveParams: keepalive.ClientParameters{
- Time: 20 * time.Millisecond,
- Timeout: 100 * time.Millisecond,
- PermitWithoutStream: true,
- },
- }
- server, client, cancel := setUpWithOptions(t, 0, serverConfig, normal, clientOptions)
- defer func() {
- client.Close(fmt.Errorf("closed manually by test"))
- server.stop()
- cancel()
- }()
- if err := waitForGoAwayTooManyPings(client); err != nil {
- t.Fatal(err)
- }
- }
- // TestKeepaliveServerEnforcementWithAbusiveClientWithRPC verifies that the
- // server closes a client transport when it sends too many keepalive pings
- // (even when there is an active stream), based on the configured
- // EnforcementPolicy.
- func (s) TestKeepaliveServerEnforcementWithAbusiveClientWithRPC(t *testing.T) {
- grpctest.TLogger.ExpectError("Client received GoAway with error code ENHANCE_YOUR_CALM and debug data equal to ASCII \"too_many_pings\"")
- serverConfig := &ServerConfig{
- KeepalivePolicy: keepalive.EnforcementPolicy{
- MinTime: time.Second,
- },
- }
- clientOptions := ConnectOptions{
- KeepaliveParams: keepalive.ClientParameters{
- Time: 50 * time.Millisecond,
- Timeout: 100 * time.Millisecond,
- },
- }
- server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, clientOptions)
- defer func() {
- client.Close(fmt.Errorf("closed manually by test"))
- server.stop()
- cancel()
- }()
- ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
- defer cancel()
- if _, err := client.NewStream(ctx, &CallHdr{}); err != nil {
- t.Fatalf("Stream creation failed: %v", err)
- }
- if err := waitForGoAwayTooManyPings(client); err != nil {
- t.Fatal(err)
- }
- }
- // TestKeepaliveServerEnforcementWithObeyingClientNoRPC verifies that the
- // server does not close a client transport (with no active streams) which
- // sends keepalive pings in accordance to the configured keepalive
- // EnforcementPolicy.
- func (s) TestKeepaliveServerEnforcementWithObeyingClientNoRPC(t *testing.T) {
- serverConfig := &ServerConfig{
- KeepalivePolicy: keepalive.EnforcementPolicy{
- MinTime: 40 * time.Millisecond,
- PermitWithoutStream: true,
- },
- }
- clientOptions := ConnectOptions{
- KeepaliveParams: keepalive.ClientParameters{
- Time: 50 * time.Millisecond,
- Timeout: time.Second,
- PermitWithoutStream: true,
- },
- }
- server, client, cancel := setUpWithOptions(t, 0, serverConfig, normal, clientOptions)
- defer func() {
- client.Close(fmt.Errorf("closed manually by test"))
- server.stop()
- cancel()
- }()
- // Sleep for client to send ~10 keepalive pings.
- time.Sleep(500 * time.Millisecond)
- // Verify that the server does not close the client transport.
- if err := checkForHealthyStream(client); err != nil {
- t.Fatalf("Stream creation failed: %v", err)
- }
- }
- // TestKeepaliveServerEnforcementWithObeyingClientWithRPC verifies that the
- // server does not close a client transport (with active streams) which
- // sends keepalive pings in accordance to the configured keepalive
- // EnforcementPolicy.
- func (s) TestKeepaliveServerEnforcementWithObeyingClientWithRPC(t *testing.T) {
- serverConfig := &ServerConfig{
- KeepalivePolicy: keepalive.EnforcementPolicy{
- MinTime: 40 * time.Millisecond,
- },
- }
- clientOptions := ConnectOptions{
- KeepaliveParams: keepalive.ClientParameters{
- Time: 50 * time.Millisecond,
- },
- }
- server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, clientOptions)
- defer func() {
- client.Close(fmt.Errorf("closed manually by test"))
- server.stop()
- cancel()
- }()
- if err := checkForHealthyStream(client); err != nil {
- t.Fatalf("Stream creation failed: %v", err)
- }
- // Give keepalive enough time.
- time.Sleep(500 * time.Millisecond)
- if err := checkForHealthyStream(client); err != nil {
- t.Fatalf("Stream creation failed: %v", err)
- }
- }
- // TestKeepaliveServerEnforcementWithDormantKeepaliveOnClient verifies that the
- // server does not closes a client transport, which has been configured to send
- // more pings than allowed by the server's EnforcementPolicy. This client
- // transport does not have any active streams and `PermitWithoutStream` is set
- // to false. This should ensure that the keepalive functionality on the client
- // side enters a dormant state.
- func (s) TestKeepaliveServerEnforcementWithDormantKeepaliveOnClient(t *testing.T) {
- serverConfig := &ServerConfig{
- KeepalivePolicy: keepalive.EnforcementPolicy{
- MinTime: 100 * time.Millisecond,
- },
- }
- clientOptions := ConnectOptions{
- KeepaliveParams: keepalive.ClientParameters{
- Time: 10 * time.Millisecond,
- Timeout: 10 * time.Millisecond,
- },
- }
- server, client, cancel := setUpWithOptions(t, 0, serverConfig, normal, clientOptions)
- defer func() {
- client.Close(fmt.Errorf("closed manually by test"))
- server.stop()
- cancel()
- }()
- // No active streams on the client. Give keepalive enough time.
- time.Sleep(500 * time.Millisecond)
- if err := checkForHealthyStream(client); err != nil {
- t.Fatalf("Stream creation failed: %v", err)
- }
- }
- // TestTCPUserTimeout tests that the TCP_USER_TIMEOUT socket option is set to
- // the keepalive timeout, as detailed in proposal A18.
- func (s) TestTCPUserTimeout(t *testing.T) {
- tests := []struct {
- time time.Duration
- timeout time.Duration
- clientWantTimeout time.Duration
- serverWantTimeout time.Duration
- }{
- {
- 10 * time.Second,
- 10 * time.Second,
- 10 * 1000 * time.Millisecond,
- 10 * 1000 * time.Millisecond,
- },
- {
- 0,
- 0,
- 0,
- 20 * 1000 * time.Millisecond,
- },
- {
- infinity,
- infinity,
- 0,
- 0,
- },
- }
- for _, tt := range tests {
- server, client, cancel := setUpWithOptions(
- t,
- 0,
- &ServerConfig{
- KeepaliveParams: keepalive.ServerParameters{
- Time: tt.time,
- Timeout: tt.timeout,
- },
- },
- normal,
- ConnectOptions{
- KeepaliveParams: keepalive.ClientParameters{
- Time: tt.time,
- Timeout: tt.timeout,
- },
- },
- )
- defer func() {
- client.Close(fmt.Errorf("closed manually by test"))
- server.stop()
- cancel()
- }()
- var sc *http2Server
- // Wait until the server transport is setup.
- for {
- server.mu.Lock()
- if len(server.conns) == 0 {
- server.mu.Unlock()
- time.Sleep(time.Millisecond)
- continue
- }
- for k := range server.conns {
- var ok bool
- sc, ok = k.(*http2Server)
- if !ok {
- t.Fatalf("Failed to convert %v to *http2Server", k)
- }
- }
- server.mu.Unlock()
- break
- }
- ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
- defer cancel()
- stream, err := client.NewStream(ctx, &CallHdr{})
- if err != nil {
- t.Fatalf("client.NewStream() failed: %v", err)
- }
- client.CloseStream(stream, io.EOF)
- cltOpt, err := syscall.GetTCPUserTimeout(client.conn)
- if err != nil {
- t.Fatalf("syscall.GetTCPUserTimeout() failed: %v", err)
- }
- if cltOpt < 0 {
- t.Skipf("skipping test on unsupported environment")
- }
- if gotTimeout := time.Duration(cltOpt) * time.Millisecond; gotTimeout != tt.clientWantTimeout {
- t.Fatalf("syscall.GetTCPUserTimeout() = %d, want %d", gotTimeout, tt.clientWantTimeout)
- }
- srvOpt, err := syscall.GetTCPUserTimeout(sc.conn)
- if err != nil {
- t.Fatalf("syscall.GetTCPUserTimeout() failed: %v", err)
- }
- if gotTimeout := time.Duration(srvOpt) * time.Millisecond; gotTimeout != tt.serverWantTimeout {
- t.Fatalf("syscall.GetTCPUserTimeout() = %d, want %d", gotTimeout, tt.serverWantTimeout)
- }
- }
- }
- // checkForHealthyStream attempts to create a stream and return error if any.
- // The stream created is closed right after to avoid any leakages.
- func checkForHealthyStream(client *http2Client) error {
- ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
- defer cancel()
- stream, err := client.NewStream(ctx, &CallHdr{})
- client.CloseStream(stream, err)
- return err
- }
- func pollForStreamCreationError(client *http2Client) error {
- ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
- defer cancel()
- for {
- if _, err := client.NewStream(ctx, &CallHdr{}); err != nil {
- break
- }
- time.Sleep(50 * time.Millisecond)
- }
- if ctx.Err() != nil {
- return fmt.Errorf("test timed out before stream creation returned an error")
- }
- return nil
- }
- // waitForGoAwayTooManyPings waits for client to receive a GoAwayTooManyPings
- // from server. It also asserts that stream creation fails after receiving a
- // GoAway.
- func waitForGoAwayTooManyPings(client *http2Client) error {
- ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
- defer cancel()
- select {
- case <-client.GoAway():
- if reason, _ := client.GetGoAwayReason(); reason != GoAwayTooManyPings {
- return fmt.Errorf("goAwayReason is %v, want %v", reason, GoAwayTooManyPings)
- }
- case <-ctx.Done():
- return fmt.Errorf("test timed out before getting GoAway with reason:GoAwayTooManyPings from server")
- }
- if _, err := client.NewStream(ctx, &CallHdr{}); err == nil {
- return fmt.Errorf("stream creation succeeded after receiving a GoAway from the server")
- }
- return nil
- }
|