github.com/cloudwego/kitex@v0.9.0/pkg/remote/trans/nphttp2/grpc/keepalive_test.go (about)

     1  /*
     2   *
     3   * Copyright 2019 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   * This file may have been modified by CloudWeGo authors. All CloudWeGo
    18   * Modifications are Copyright 2021 CloudWeGo Authors.
    19   */
    20  
    21  // This file contains tests related to the following proposals:
    22  // https://github.com/grpc/proposal/blob/master/A8-client-side-keepalive.md
    23  // https://github.com/grpc/proposal/blob/master/A9-server-side-conn-mgt.md
    24  // https://github.com/grpc/proposal/blob/master/A18-tcp-user-timeout.md
    25  package grpc
    26  
    27  import (
    28  	"context"
    29  	"io"
    30  	"net"
    31  	"testing"
    32  	"time"
    33  
    34  	"golang.org/x/net/http2"
    35  )
    36  
    37  const defaultTestTimeout = 10 * time.Second
    38  
    39  // TestMaxConnectionIdle tests that a server will send GoAway to an idle
    40  // client. An idle client is one who doesn't make any RPC calls for a duration
    41  // of MaxConnectionIdle time.
    42  func TestMaxConnectionIdle(t *testing.T) {
    43  	serverConfig := &ServerConfig{
    44  		KeepaliveParams: ServerKeepalive{
    45  			MaxConnectionIdle: 500 * time.Millisecond,
    46  		},
    47  	}
    48  	server, client := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{})
    49  	defer func() {
    50  		client.Close()
    51  		server.stop()
    52  	}()
    53  
    54  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
    55  	defer cancel()
    56  	stream, err := client.NewStream(ctx, &CallHdr{})
    57  	if err != nil {
    58  		t.Fatalf("client.NewStream() failed: %v", err)
    59  	}
    60  	client.CloseStream(stream, io.EOF)
    61  
    62  	// Wait for the server's MaxConnectionIdle timeout to kick in, and for it
    63  	// to send a GoAway.
    64  	timeout := time.NewTimer(time.Second * 1)
    65  	select {
    66  	case <-client.Error():
    67  		if !timeout.Stop() {
    68  			<-timeout.C
    69  		}
    70  		if reason := client.GetGoAwayReason(); reason != GoAwayNoReason {
    71  			t.Fatalf("GoAwayReason is %v, want %v", reason, GoAwayNoReason)
    72  		}
    73  	case <-timeout.C:
    74  		t.Fatalf("MaxConnectionIdle timeout expired, expected a GoAway from the server.")
    75  	}
    76  }
    77  
    78  // TestMaxConenctionIdleBusyClient tests that a server will not send GoAway to
    79  // a busy client.
    80  func TestMaxConnectionIdleBusyClient(t *testing.T) {
    81  	serverConfig := &ServerConfig{
    82  		KeepaliveParams: ServerKeepalive{
    83  			MaxConnectionIdle: 500 * time.Millisecond,
    84  		},
    85  	}
    86  	server, client := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{})
    87  	defer func() {
    88  		client.Close()
    89  		server.stop()
    90  	}()
    91  
    92  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
    93  	defer cancel()
    94  	_, err := client.NewStream(ctx, &CallHdr{})
    95  	if err != nil {
    96  		t.Fatalf("client.NewStream() failed: %v", err)
    97  	}
    98  
    99  	// Wait for double the MaxConnectionIdle time to make sure the server does
   100  	// not send a GoAway, as the client has an open stream.
   101  	timeout := time.NewTimer(time.Second * 1)
   102  	select {
   103  	case <-client.GoAway():
   104  		if !timeout.Stop() {
   105  			<-timeout.C
   106  		}
   107  		t.Fatalf("A non-idle client received a GoAway.")
   108  	case <-timeout.C:
   109  	}
   110  }
   111  
   112  // FIXME Test failed because DATA RACE.
   113  // TestMaxConnectionAge tests that a server will send GoAway after a duration
   114  // of MaxConnectionAge.
   115  //func TestMaxConnectionAge(t *testing.T) {
   116  //	serverConfig := &ServerConfig{
   117  //		KeepaliveParams: ServerKeepalive{
   118  //			MaxConnectionAge:      1 * time.Second,
   119  //			MaxConnectionAgeGrace: 1 * time.Second,
   120  //		},
   121  //	}
   122  //	server, client := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{})
   123  //	defer func() {
   124  //		client.Close()
   125  //		server.stop()
   126  //	}()
   127  //
   128  //	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   129  //	defer cancel()
   130  //	_, err := client.NewStream(ctx, &CallHdr{})
   131  //	if err != nil {
   132  //		t.Fatalf("client.NewStream() failed: %v", err)
   133  //	}
   134  //
   135  //	// Wait for the server's MaxConnectionAge timeout to kick in, and for it
   136  //	// to send a GoAway.
   137  //	timeout := time.NewTimer(4 * time.Second)
   138  //	select {
   139  //	case <-client.Error():
   140  //		if !timeout.Stop() {
   141  //			<-timeout.C
   142  //		}
   143  //		if reason := client.GetGoAwayReason(); reason != GoAwayNoReason {
   144  //			t.Fatalf("GoAwayReason is %v, want %v", reason, GoAwayNoReason)
   145  //		}
   146  //	case <-timeout.C:
   147  //		t.Fatalf("MaxConnectionAge timeout expired, expected a GoAway from the server.")
   148  //	}
   149  //}
   150  
   151  // TestKeepaliveServerClosesUnresponsiveClient tests that a server closes
   152  // the connection with a client that doesn't respond to keepalive pings.
   153  //
   154  // This test creates a regular net.Conn connection to the server and sends the
   155  // clientPreface and the initial Settings frame, and then remains unresponsive.
   156  func TestKeepaliveServerClosesUnresponsiveClient(t *testing.T) {
   157  	serverConfig := &ServerConfig{
   158  		KeepaliveParams: ServerKeepalive{
   159  			Time:    250 * time.Millisecond,
   160  			Timeout: 250 * time.Millisecond,
   161  		},
   162  	}
   163  	server, client := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{})
   164  	defer func() {
   165  		client.Close()
   166  		server.stop()
   167  	}()
   168  
   169  	addr := server.addr()
   170  	conn, err := net.DialTimeout("tcp", addr, time.Second)
   171  	if err != nil {
   172  		t.Fatalf("net.Dial(tcp, %v) failed: %v", addr, err)
   173  	}
   174  	defer conn.Close()
   175  
   176  	if n, err := conn.Write(ClientPreface); err != nil || n != len(ClientPreface) {
   177  		t.Fatalf("conn.write(clientPreface) failed: n=%v, err=%v", n, err)
   178  	}
   179  	framer := newFramer(conn, 0, 0, 0)
   180  	if err := framer.WriteSettings(http2.Setting{}); err != nil {
   181  		t.Fatal("framer.WriteSettings(http2.Setting{}) failed:", err)
   182  	}
   183  	framer.writer.Flush()
   184  
   185  	// We read from the net.Conn till we get an error, which is expected when
   186  	// the server closes the connection as part of the keepalive logic.
   187  	errCh := make(chan error)
   188  	go func() {
   189  		b := make([]byte, 24)
   190  		for {
   191  			if _, err = conn.Read(b); err != nil {
   192  				errCh <- err
   193  				return
   194  			}
   195  		}
   196  	}()
   197  
   198  	// Server waits for KeepaliveParams.Time seconds before sending out a ping,
   199  	// and then waits for KeepaliveParams.Timeout for a ping ack.
   200  	timeout := time.NewTimer(1 * time.Second)
   201  	select {
   202  	case err := <-errCh:
   203  		if err != io.EOF {
   204  			t.Fatalf("client.Read(_) = _,%v, want io.EOF", err)
   205  		}
   206  	case <-timeout.C:
   207  		t.Fatalf("keepalive timeout expired, server should have closed the connection.")
   208  	}
   209  }
   210  
   211  // TestKeepaliveServerWithResponsiveClient tests that a server doesn't close
   212  // the connection with a client that responds to keepalive pings.
   213  func TestKeepaliveServerWithResponsiveClient(t *testing.T) {
   214  	serverConfig := &ServerConfig{
   215  		KeepaliveParams: ServerKeepalive{
   216  			Time:    500 * time.Millisecond,
   217  			Timeout: 500 * time.Millisecond,
   218  		},
   219  	}
   220  	server, client := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{
   221  		// FIXME the original ut don't contain KeepaliveParams
   222  		KeepaliveParams: ClientKeepalive{
   223  			Time:                500 * time.Millisecond,
   224  			Timeout:             500 * time.Millisecond,
   225  			PermitWithoutStream: true,
   226  		},
   227  	})
   228  	defer func() {
   229  		client.Close()
   230  		server.stop()
   231  	}()
   232  
   233  	// Give keepalive logic some time by sleeping.
   234  	time.Sleep(1 * time.Second)
   235  
   236  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   237  	defer cancel()
   238  	// Make sure the client transport is healthy.
   239  	if _, err := client.NewStream(ctx, &CallHdr{}); err != nil {
   240  		t.Fatalf("client.NewStream() failed: %v", err)
   241  	}
   242  }
   243  
   244  // TestKeepaliveClientClosesUnresponsiveServer creates a server which does not
   245  // respond to keepalive pings, and makes sure that the client closes the
   246  // transport once the keepalive logic kicks in. Here, we set the
   247  // `PermitWithoutStream` parameter to true which ensures that the keepalive
   248  // logic is running even without any active streams.
   249  func TestKeepaliveClientClosesUnresponsiveServer(t *testing.T) {
   250  	connCh := make(chan net.Conn, 1)
   251  	client := setUpWithNoPingServer(t, ConnectOptions{KeepaliveParams: ClientKeepalive{
   252  		Time:                250 * time.Millisecond,
   253  		Timeout:             250 * time.Millisecond,
   254  		PermitWithoutStream: true,
   255  	}}, connCh)
   256  	if client == nil {
   257  		t.Fatalf("setUpWithNoPingServer failed, return nil client")
   258  	}
   259  	defer client.Close()
   260  
   261  	conn, ok := <-connCh
   262  	if !ok {
   263  		t.Fatalf("Server didn't return connection object")
   264  	}
   265  	defer conn.Close()
   266  
   267  	// Sleep for keepalive to close the connection.
   268  	time.Sleep(1 * time.Second)
   269  
   270  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   271  	defer cancel()
   272  	// Make sure the client transport is not healthy.
   273  	if _, err := client.NewStream(ctx, &CallHdr{}); err == nil {
   274  		t.Fatal("client.NewStream() should have failed, but succeeded")
   275  	}
   276  }
   277  
   278  // TestKeepaliveClientOpenWithUnresponsiveServer creates a server which does
   279  // not respond to keepalive pings, and makes sure that the client does not
   280  // close the transport. Here, we do not set the `PermitWithoutStream` parameter
   281  // to true which ensures that the keepalive logic is turned off without any
   282  // active streams, and therefore the transport stays open.
   283  func TestKeepaliveClientOpenWithUnresponsiveServer(t *testing.T) {
   284  	connCh := make(chan net.Conn, 1)
   285  	client := setUpWithNoPingServer(t, ConnectOptions{KeepaliveParams: ClientKeepalive{
   286  		Time:    250 * time.Millisecond,
   287  		Timeout: 250 * time.Millisecond,
   288  	}}, connCh)
   289  	if client == nil {
   290  		t.Fatalf("setUpWithNoPingServer failed, return nil client")
   291  	}
   292  	defer client.Close()
   293  
   294  	conn, ok := <-connCh
   295  	if !ok {
   296  		t.Fatalf("Server didn't return connection object")
   297  	}
   298  	defer conn.Close()
   299  
   300  	// Give keepalive some time.
   301  	time.Sleep(1 * time.Second)
   302  
   303  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   304  	defer cancel()
   305  	// Make sure the client transport is healthy.
   306  	if _, err := client.NewStream(ctx, &CallHdr{}); err != nil {
   307  		t.Fatalf("client.NewStream() failed: %v", err)
   308  	}
   309  }
   310  
   311  // TestKeepaliveClientClosesWithActiveStreams creates a server which does not
   312  // respond to keepalive pings, and makes sure that the client closes the
   313  // transport even when there is an active stream.
   314  func TestKeepaliveClientClosesWithActiveStreams(t *testing.T) {
   315  	connCh := make(chan net.Conn, 1)
   316  	client := setUpWithNoPingServer(t, ConnectOptions{KeepaliveParams: ClientKeepalive{
   317  		Time:    250 * time.Millisecond,
   318  		Timeout: 250 * time.Millisecond,
   319  	}}, connCh)
   320  	if client == nil {
   321  		t.Fatalf("setUpWithNoPingServer failed, return nil client")
   322  	}
   323  	defer client.Close()
   324  
   325  	conn, ok := <-connCh
   326  	if !ok {
   327  		t.Fatalf("Server didn't return connection object")
   328  	}
   329  	defer conn.Close()
   330  
   331  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   332  	defer cancel()
   333  	// Create a stream, but send no data on it.
   334  	if _, err := client.NewStream(ctx, &CallHdr{}); err != nil {
   335  		t.Fatalf("client.NewStream() failed: %v", err)
   336  	}
   337  
   338  	// Give keepalive some time.
   339  	time.Sleep(1 * time.Second)
   340  
   341  	// Make sure the client transport is not healthy.
   342  	if _, err := client.NewStream(ctx, &CallHdr{}); err == nil {
   343  		t.Fatal("client.NewStream() should have failed, but succeeded")
   344  	}
   345  }
   346  
   347  // TestKeepaliveClientStaysHealthyWithResponsiveServer creates a server which
   348  // responds to keepalive pings, and makes sure than a client transport stays
   349  // healthy without any active streams.
   350  func TestKeepaliveClientStaysHealthyWithResponsiveServer(t *testing.T) {
   351  	server, client := setUpWithOptions(t, 0, &ServerConfig{}, normal, ConnectOptions{
   352  		KeepaliveParams: ClientKeepalive{
   353  			Time:                500 * time.Millisecond,
   354  			Timeout:             500 * time.Millisecond,
   355  			PermitWithoutStream: true,
   356  		},
   357  	})
   358  	defer func() {
   359  		client.Close()
   360  		server.stop()
   361  	}()
   362  
   363  	// Give keepalive some time.
   364  	time.Sleep(1 * time.Second)
   365  
   366  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   367  	defer cancel()
   368  	// Make sure the client transport is healthy.
   369  	if _, err := client.NewStream(ctx, &CallHdr{}); err != nil {
   370  		t.Fatalf("client.NewStream() failed: %v", err)
   371  	}
   372  }
   373  
   374  // TestKeepaliveClientFrequency creates a server which expects at most 1 client
   375  // ping for every 1.2 seconds, while the client is configured to send a ping
   376  // every 1 second. So, this configuration should end up with the client
   377  // transport being closed. But we had a bug wherein the client was sending one
   378  // ping every [Time+Timeout] instead of every [Time] period, and this test
   379  // explicitly makes sure the fix works and the client sends a ping every [Time]
   380  // period.
   381  func TestKeepaliveClientFrequency(t *testing.T) {
   382  	serverConfig := &ServerConfig{
   383  		KeepaliveEnforcementPolicy: EnforcementPolicy{
   384  			MinTime:             200 * time.Millisecond, // 1.2 seconds
   385  			PermitWithoutStream: true,
   386  		},
   387  	}
   388  	clientOptions := ConnectOptions{
   389  		KeepaliveParams: ClientKeepalive{
   390  			Time:                150 * time.Millisecond,
   391  			Timeout:             300 * time.Millisecond,
   392  			PermitWithoutStream: true,
   393  		},
   394  	}
   395  	server, client := setUpWithOptions(t, 0, serverConfig, normal, clientOptions)
   396  	defer func() {
   397  		client.Close()
   398  		server.stop()
   399  	}()
   400  
   401  	timeout := time.NewTimer(1 * time.Second)
   402  	select {
   403  	case <-client.Error():
   404  		if !timeout.Stop() {
   405  			<-timeout.C
   406  		}
   407  		if reason := client.GetGoAwayReason(); reason != GoAwayTooManyPings {
   408  			t.Fatalf("GoAwayReason is %v, want %v", reason, GoAwayTooManyPings)
   409  		}
   410  	case <-timeout.C:
   411  		t.Fatalf("client transport still healthy; expected GoAway from the server.")
   412  	}
   413  
   414  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   415  	defer cancel()
   416  	// Make sure the client transport is not healthy.
   417  	if _, err := client.NewStream(ctx, &CallHdr{}); err == nil {
   418  		t.Fatal("client.NewStream() should have failed, but succeeded")
   419  	}
   420  }
   421  
   422  // TestKeepaliveServerEnforcementWithAbusiveClientNoRPC verifies that the
   423  // server closes a client transport when it sends too many keepalive pings
   424  // (when there are no active streams), based on the configured
   425  // EnforcementPolicy.
   426  func TestKeepaliveServerEnforcementWithAbusiveClientNoRPC(t *testing.T) {
   427  	serverConfig := &ServerConfig{
   428  		KeepaliveEnforcementPolicy: EnforcementPolicy{
   429  			MinTime: 2 * time.Second,
   430  		},
   431  	}
   432  	clientOptions := ConnectOptions{
   433  		KeepaliveParams: ClientKeepalive{
   434  			Time:                50 * time.Millisecond,
   435  			Timeout:             1 * time.Second,
   436  			PermitWithoutStream: true,
   437  		},
   438  	}
   439  	server, client := setUpWithOptions(t, 0, serverConfig, normal, clientOptions)
   440  	defer func() {
   441  		client.Close()
   442  		server.stop()
   443  	}()
   444  
   445  	timeout := time.NewTimer(4 * time.Second)
   446  	select {
   447  	case <-client.Error():
   448  		if !timeout.Stop() {
   449  			<-timeout.C
   450  		}
   451  		if reason := client.GetGoAwayReason(); reason != GoAwayTooManyPings {
   452  			t.Fatalf("GoAwayReason is %v, want %v", reason, GoAwayTooManyPings)
   453  		}
   454  	case <-timeout.C:
   455  		t.Fatalf("client transport still healthy; expected GoAway from the server.")
   456  	}
   457  
   458  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   459  	defer cancel()
   460  	// Make sure the client transport is not healthy.
   461  	if _, err := client.NewStream(ctx, &CallHdr{}); err == nil {
   462  		t.Fatal("client.NewStream() should have failed, but succeeded")
   463  	}
   464  }
   465  
   466  // TestKeepaliveServerEnforcementWithAbusiveClientWithRPC verifies that the
   467  // server closes a client transport when it sends too many keepalive pings
   468  // (even when there is an active stream), based on the configured
   469  // EnforcementPolicy.
   470  func TestKeepaliveServerEnforcementWithAbusiveClientWithRPC(t *testing.T) {
   471  	serverConfig := &ServerConfig{
   472  		KeepaliveEnforcementPolicy: EnforcementPolicy{
   473  			MinTime: 2 * time.Second,
   474  		},
   475  	}
   476  	clientOptions := ConnectOptions{
   477  		KeepaliveParams: ClientKeepalive{
   478  			Time:    50 * time.Millisecond,
   479  			Timeout: 1 * time.Second,
   480  		},
   481  	}
   482  	server, client := setUpWithOptions(t, 0, serverConfig, suspended, clientOptions)
   483  	defer func() {
   484  		client.Close()
   485  		server.stop()
   486  	}()
   487  
   488  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   489  	defer cancel()
   490  	if _, err := client.NewStream(ctx, &CallHdr{}); err != nil {
   491  		t.Fatalf("client.NewStream() failed: %v", err)
   492  	}
   493  
   494  	timeout := time.NewTimer(4 * time.Second)
   495  	select {
   496  	case <-client.Error():
   497  		if !timeout.Stop() {
   498  			<-timeout.C
   499  		}
   500  		if reason := client.GetGoAwayReason(); reason != GoAwayTooManyPings {
   501  			t.Fatalf("GoAwayReason is %v, want %v", reason, GoAwayTooManyPings)
   502  		}
   503  	case <-timeout.C:
   504  		t.Fatalf("client transport still healthy; expected GoAway from the server.")
   505  	}
   506  
   507  	// Make sure the client transport is not healthy.
   508  	if _, err := client.NewStream(ctx, &CallHdr{}); err == nil {
   509  		t.Fatal("client.NewStream() should have failed, but succeeded")
   510  	}
   511  }
   512  
   513  // TestKeepaliveServerEnforcementWithObeyingClientNoRPC verifies that the
   514  // server does not close a client transport (with no active streams) which
   515  // sends keepalive pings in accordance to the configured keepalive
   516  // EnforcementPolicy.
   517  func TestKeepaliveServerEnforcementWithObeyingClientNoRPC(t *testing.T) {
   518  	serverConfig := &ServerConfig{
   519  		KeepaliveEnforcementPolicy: EnforcementPolicy{
   520  			MinTime:             50 * time.Millisecond,
   521  			PermitWithoutStream: true,
   522  		},
   523  	}
   524  	clientOptions := ConnectOptions{
   525  		KeepaliveParams: ClientKeepalive{
   526  			Time:                51 * time.Millisecond,
   527  			Timeout:             500 * time.Millisecond,
   528  			PermitWithoutStream: true,
   529  		},
   530  	}
   531  	server, client := setUpWithOptions(t, 0, serverConfig, normal, clientOptions)
   532  	defer func() {
   533  		client.Close()
   534  		server.stop()
   535  	}()
   536  
   537  	// Give keepalive enough time.
   538  	time.Sleep(500 * time.Millisecond)
   539  
   540  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   541  	defer cancel()
   542  	// Make sure the client transport is healthy.
   543  	if _, err := client.NewStream(ctx, &CallHdr{}); err != nil {
   544  		t.Fatalf("client.NewStream() failed: %v", err)
   545  	}
   546  }
   547  
   548  // TestKeepaliveServerEnforcementWithObeyingClientWithRPC verifies that the
   549  // server does not close a client transport (with active streams) which
   550  // sends keepalive pings in accordance to the configured keepalive
   551  // EnforcementPolicy.
   552  func TestKeepaliveServerEnforcementWithObeyingClientWithRPC(t *testing.T) {
   553  	serverConfig := &ServerConfig{
   554  		KeepaliveEnforcementPolicy: EnforcementPolicy{
   555  			MinTime: 50 * time.Millisecond,
   556  		},
   557  	}
   558  	clientOptions := ConnectOptions{
   559  		KeepaliveParams: ClientKeepalive{
   560  			Time:    51 * time.Millisecond,
   561  			Timeout: 500 * time.Millisecond,
   562  		},
   563  	}
   564  	server, client := setUpWithOptions(t, 0, serverConfig, suspended, clientOptions)
   565  	defer func() {
   566  		client.Close()
   567  		server.stop()
   568  	}()
   569  
   570  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   571  	defer cancel()
   572  	if _, err := client.NewStream(ctx, &CallHdr{}); err != nil {
   573  		t.Fatalf("client.NewStream() failed: %v", err)
   574  	}
   575  
   576  	// Give keepalive enough time.
   577  	time.Sleep(1 * time.Second)
   578  
   579  	// Make sure the client transport is healthy.
   580  	if _, err := client.NewStream(ctx, &CallHdr{}); err != nil {
   581  		t.Fatalf("client.NewStream() failed: %v", err)
   582  	}
   583  }
   584  
   585  // TestKeepaliveServerEnforcementWithDormantKeepaliveOnClient verifies that the
   586  // server does not closes a client transport, which has been configured to send
   587  // more pings than allowed by the server's EnforcementPolicy. This client
   588  // transport does not have any active streams and `PermitWithoutStream` is set
   589  // to false. This should ensure that the keepalive functionality on the client
   590  // side enters a dormant state.
   591  func TestKeepaliveServerEnforcementWithDormantKeepaliveOnClient(t *testing.T) {
   592  	serverConfig := &ServerConfig{
   593  		KeepaliveEnforcementPolicy: EnforcementPolicy{
   594  			MinTime: 400 * time.Millisecond,
   595  		},
   596  	}
   597  	clientOptions := ConnectOptions{
   598  		KeepaliveParams: ClientKeepalive{
   599  			Time:    25 * time.Millisecond,
   600  			Timeout: 250 * time.Millisecond,
   601  		},
   602  	}
   603  	server, client := setUpWithOptions(t, 0, serverConfig, normal, clientOptions)
   604  	defer func() {
   605  		client.Close()
   606  		server.stop()
   607  	}()
   608  
   609  	// No active streams on the client. Give keepalive enough time.
   610  	time.Sleep(500 * time.Millisecond)
   611  
   612  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   613  	defer cancel()
   614  	// Make sure the client transport is healthy.
   615  	if _, err := client.NewStream(ctx, &CallHdr{}); err != nil {
   616  		t.Fatalf("client.NewStream() failed: %v", err)
   617  	}
   618  }
   619  
   620  // FIXME syscall.GetTCPUserTimeout() failed: conn is not *net.TCPConn. got *netpoll.TCPConnection
   621  // TestTCPUserTimeout tests that the TCP_USER_TIMEOUT socket option is set to
   622  // the keepalive timeout, as detailed in proposal A18.
   623  //func TestTCPUserTimeout(t *testing.T) {
   624  //	tests := []struct {
   625  //		time        time.Duration
   626  //		timeout     time.Duration
   627  //		wantTimeout time.Duration
   628  //	}{
   629  //		{
   630  //			10 * time.Second,
   631  //			10 * time.Second,
   632  //			10 * 1000 * time.Millisecond,
   633  //		},
   634  //		{
   635  //			0,
   636  //			0,
   637  //			0,
   638  //		},
   639  //	}
   640  //	for _, tt := range tests {
   641  //		server, client := setUpWithOptions(
   642  //			t,
   643  //			0,
   644  //			&ServerConfig{
   645  //				KeepaliveParams: ServerKeepalive{
   646  //					Time:    tt.timeout,
   647  //					Timeout: tt.timeout,
   648  //				},
   649  //			},
   650  //			normal,
   651  //			ConnectOptions{
   652  //				KeepaliveParams: ClientKeepalive{
   653  //					Time:    tt.time,
   654  //					Timeout: tt.timeout,
   655  //				},
   656  //			},
   657  //		)
   658  //		defer func() {
   659  //			client.Close()
   660  //			server.stop()
   661  //		}()
   662  //
   663  //		ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   664  //		defer cancel()
   665  //		stream, err := client.NewStream(ctx, &CallHdr{})
   666  //		if err != nil {
   667  //			t.Fatalf("client.NewStream() failed: %v", err)
   668  //		}
   669  //		client.CloseStream(stream, io.EOF)
   670  //
   671  //		opt, err := syscall.GetTCPUserTimeout(client.conn)
   672  //		if err != nil {
   673  //			t.Fatalf("syscall.GetTCPUserTimeout() failed: %v", err)
   674  //		}
   675  //		if opt < 0 {
   676  //			t.Skipf("skipping test on unsupported environment")
   677  //		}
   678  //		if gotTimeout := time.Duration(opt) * time.Millisecond; gotTimeout != tt.wantTimeout {
   679  //			t.Fatalf("syscall.GetTCPUserTimeout() = %d, want %d", gotTimeout, tt.wantTimeout)
   680  //		}
   681  //	}
   682  //}