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