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 }