google.golang.org/grpc@v1.72.2/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 "crypto/tls" 28 "crypto/x509" 29 "fmt" 30 "io" 31 "net" 32 "os" 33 "strings" 34 "testing" 35 "time" 36 37 "golang.org/x/net/http2" 38 "google.golang.org/grpc/credentials" 39 "google.golang.org/grpc/internal/channelz" 40 "google.golang.org/grpc/internal/grpctest" 41 "google.golang.org/grpc/internal/syscall" 42 "google.golang.org/grpc/keepalive" 43 "google.golang.org/grpc/testdata" 44 ) 45 46 const defaultTestTimeout = 10 * time.Second 47 const defaultTestShortTimeout = 10 * time.Millisecond 48 49 // TestMaxConnectionIdle tests that a server will send GoAway to an idle 50 // client. An idle client is one who doesn't make any RPC calls for a duration 51 // of MaxConnectionIdle time. 52 func (s) TestMaxConnectionIdle(t *testing.T) { 53 serverConfig := &ServerConfig{ 54 KeepaliveParams: keepalive.ServerParameters{ 55 MaxConnectionIdle: 30 * time.Millisecond, 56 }, 57 } 58 server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{}) 59 defer func() { 60 client.Close(fmt.Errorf("closed manually by test")) 61 server.stop() 62 cancel() 63 }() 64 65 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 66 defer cancel() 67 stream, err := client.NewStream(ctx, &CallHdr{}) 68 if err != nil { 69 t.Fatalf("client.NewStream() failed: %v", err) 70 } 71 stream.Close(io.EOF) 72 73 // Verify the server sends a GoAway to client after MaxConnectionIdle timeout 74 // kicks in. 75 select { 76 case <-ctx.Done(): 77 t.Fatalf("context expired before receiving GoAway from the server.") 78 case <-client.GoAway(): 79 reason, debugMsg := client.GetGoAwayReason() 80 if reason != GoAwayNoReason { 81 t.Fatalf("GoAwayReason is %v, want %v", reason, GoAwayNoReason) 82 } 83 if !strings.Contains(debugMsg, "max_idle") { 84 t.Fatalf("GoAwayDebugMessage is %v, want %v", debugMsg, "max_idle") 85 } 86 } 87 } 88 89 // TestMaxConnectionIdleBusyClient tests that a server will not send GoAway to 90 // a busy client. 91 func (s) TestMaxConnectionIdleBusyClient(t *testing.T) { 92 serverConfig := &ServerConfig{ 93 KeepaliveParams: keepalive.ServerParameters{ 94 MaxConnectionIdle: 100 * time.Millisecond, 95 }, 96 } 97 server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{}) 98 defer func() { 99 client.Close(fmt.Errorf("closed manually by test")) 100 server.stop() 101 cancel() 102 }() 103 104 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 105 defer cancel() 106 _, err := client.NewStream(ctx, &CallHdr{}) 107 if err != nil { 108 t.Fatalf("client.NewStream() failed: %v", err) 109 } 110 111 // Verify the server does not send a GoAway to client even after MaxConnectionIdle 112 // timeout kicks in. 113 ctx, cancel = context.WithTimeout(context.Background(), time.Second) 114 defer cancel() 115 select { 116 case <-client.GoAway(): 117 t.Fatalf("A busy client received a GoAway.") 118 case <-ctx.Done(): 119 } 120 } 121 122 // TestMaxConnectionAge tests that a server will send GoAway after a duration 123 // of MaxConnectionAge. 124 func (s) TestMaxConnectionAge(t *testing.T) { 125 maxConnAge := 100 * time.Millisecond 126 serverConfig := &ServerConfig{ 127 KeepaliveParams: keepalive.ServerParameters{ 128 MaxConnectionAge: maxConnAge, 129 MaxConnectionAgeGrace: 10 * time.Millisecond, 130 }, 131 } 132 server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{}) 133 defer func() { 134 client.Close(fmt.Errorf("closed manually by test")) 135 server.stop() 136 cancel() 137 }() 138 139 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 140 defer cancel() 141 if _, err := client.NewStream(ctx, &CallHdr{}); err != nil { 142 t.Fatalf("client.NewStream() failed: %v", err) 143 } 144 145 // Verify the server sends a GoAway to client even after client remains idle 146 // for more than MaxConnectionIdle time. 147 select { 148 case <-client.GoAway(): 149 reason, debugMsg := client.GetGoAwayReason() 150 if reason != GoAwayNoReason { 151 t.Fatalf("GoAwayReason is %v, want %v", reason, GoAwayNoReason) 152 } 153 if !strings.Contains(debugMsg, "max_age") { 154 t.Fatalf("GoAwayDebugMessage is %v, want %v", debugMsg, "max_age") 155 } 156 case <-ctx.Done(): 157 t.Fatalf("timed out before getting a GoAway from the server.") 158 } 159 } 160 161 const ( 162 defaultWriteBufSize = 32 * 1024 163 defaultReadBufSize = 32 * 1024 164 ) 165 166 // TestKeepaliveServerClosesUnresponsiveClient tests that a server closes 167 // the connection with a client that doesn't respond to keepalive pings. 168 // 169 // This test creates a regular net.Conn connection to the server and sends the 170 // clientPreface and the initial Settings frame, and then remains unresponsive. 171 func (s) TestKeepaliveServerClosesUnresponsiveClient(t *testing.T) { 172 serverConfig := &ServerConfig{ 173 KeepaliveParams: keepalive.ServerParameters{ 174 Time: 100 * time.Millisecond, 175 Timeout: 10 * time.Millisecond, 176 }, 177 } 178 server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{}) 179 defer func() { 180 client.Close(fmt.Errorf("closed manually by test")) 181 server.stop() 182 cancel() 183 }() 184 185 addr := server.addr() 186 conn, err := net.Dial("tcp", addr) 187 if err != nil { 188 t.Fatalf("net.Dial(tcp, %v) failed: %v", addr, err) 189 } 190 defer conn.Close() 191 192 if n, err := conn.Write(clientPreface); err != nil || n != len(clientPreface) { 193 t.Fatalf("conn.Write(clientPreface) failed: n=%v, err=%v", n, err) 194 } 195 framer := newFramer(conn, defaultWriteBufSize, defaultReadBufSize, false, 0) 196 if err := framer.fr.WriteSettings(http2.Setting{}); err != nil { 197 t.Fatal("framer.WriteSettings(http2.Setting{}) failed:", err) 198 } 199 framer.writer.Flush() 200 201 // We read from the net.Conn till we get an error, which is expected when 202 // the server closes the connection as part of the keepalive logic. 203 errCh := make(chan error, 1) 204 go func() { 205 b := make([]byte, 24) 206 for { 207 if _, err = conn.Read(b); err != nil { 208 errCh <- err 209 return 210 } 211 } 212 }() 213 214 // Server waits for KeepaliveParams.Time seconds before sending out a ping, 215 // and then waits for KeepaliveParams.Timeout for a ping ack. 216 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 217 defer cancel() 218 select { 219 case err := <-errCh: 220 if err != io.EOF { 221 t.Fatalf("client.Read(_) = _,%v, want io.EOF", err) 222 223 } 224 case <-ctx.Done(): 225 t.Fatalf("Test timed out before server closed the connection.") 226 } 227 } 228 229 // TestKeepaliveServerWithResponsiveClient tests that a server doesn't close 230 // the connection with a client that responds to keepalive pings. 231 func (s) TestKeepaliveServerWithResponsiveClient(t *testing.T) { 232 serverConfig := &ServerConfig{ 233 KeepaliveParams: keepalive.ServerParameters{ 234 Time: 100 * time.Millisecond, 235 Timeout: 100 * time.Millisecond, 236 }, 237 } 238 server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, ConnectOptions{}) 239 defer func() { 240 client.Close(fmt.Errorf("closed manually by test")) 241 server.stop() 242 cancel() 243 }() 244 245 // Give keepalive logic some time by sleeping. 246 time.Sleep(500 * time.Millisecond) 247 248 if err := checkForHealthyStream(client); err != nil { 249 t.Fatalf("Stream creation failed: %v", err) 250 } 251 } 252 253 func channelzSubChannel(t *testing.T) *channelz.SubChannel { 254 ch := channelz.RegisterChannel(nil, "test chan") 255 sc := channelz.RegisterSubChannel(ch, "test subchan") 256 t.Cleanup(func() { 257 channelz.RemoveEntry(sc.ID) 258 channelz.RemoveEntry(ch.ID) 259 }) 260 return sc 261 } 262 263 // TestKeepaliveClientClosesUnresponsiveServer creates a server which does not 264 // respond to keepalive pings, and makes sure that the client closes the 265 // transport once the keepalive logic kicks in. Here, we set the 266 // `PermitWithoutStream` parameter to true which ensures that the keepalive 267 // logic is running even without any active streams. 268 func (s) TestKeepaliveClientClosesUnresponsiveServer(t *testing.T) { 269 connCh := make(chan net.Conn, 1) 270 copts := ConnectOptions{ 271 ChannelzParent: channelzSubChannel(t), 272 KeepaliveParams: keepalive.ClientParameters{ 273 Time: 10 * time.Millisecond, 274 Timeout: 10 * time.Millisecond, 275 PermitWithoutStream: true, 276 }, 277 } 278 client, cancel := setUpWithNoPingServer(t, copts, connCh) 279 defer cancel() 280 defer client.Close(fmt.Errorf("closed manually by test")) 281 282 conn, ok := <-connCh 283 if !ok { 284 t.Fatalf("Server didn't return connection object") 285 } 286 defer conn.Close() 287 288 if err := pollForStreamCreationError(client); err != nil { 289 t.Fatal(err) 290 } 291 } 292 293 // TestKeepaliveClientOpenWithUnresponsiveServer creates a server which does 294 // not respond to keepalive pings, and makes sure that the client does not 295 // close the transport. Here, we do not set the `PermitWithoutStream` parameter 296 // to true which ensures that the keepalive logic is turned off without any 297 // active streams, and therefore the transport stays open. 298 func (s) TestKeepaliveClientOpenWithUnresponsiveServer(t *testing.T) { 299 connCh := make(chan net.Conn, 1) 300 copts := ConnectOptions{ 301 ChannelzParent: channelzSubChannel(t), 302 KeepaliveParams: keepalive.ClientParameters{ 303 Time: 10 * time.Millisecond, 304 Timeout: 10 * time.Millisecond, 305 }, 306 } 307 client, cancel := setUpWithNoPingServer(t, copts, connCh) 308 defer cancel() 309 defer client.Close(fmt.Errorf("closed manually by test")) 310 311 conn, ok := <-connCh 312 if !ok { 313 t.Fatalf("Server didn't return connection object") 314 } 315 defer conn.Close() 316 317 // Give keepalive some time. 318 time.Sleep(500 * time.Millisecond) 319 320 if err := checkForHealthyStream(client); err != nil { 321 t.Fatalf("Stream creation failed: %v", err) 322 } 323 } 324 325 // TestKeepaliveClientClosesWithActiveStreams creates a server which does not 326 // respond to keepalive pings, and makes sure that the client closes the 327 // transport even when there is an active stream. 328 func (s) TestKeepaliveClientClosesWithActiveStreams(t *testing.T) { 329 connCh := make(chan net.Conn, 1) 330 copts := ConnectOptions{ 331 ChannelzParent: channelzSubChannel(t), 332 KeepaliveParams: keepalive.ClientParameters{ 333 Time: 500 * time.Millisecond, 334 Timeout: 500 * time.Millisecond, 335 }, 336 } 337 // TODO(i/6099): Setup a server which can ping and no-ping based on a flag to 338 // reduce the flakiness in this test. 339 client, cancel := setUpWithNoPingServer(t, copts, connCh) 340 defer cancel() 341 defer client.Close(fmt.Errorf("closed manually by test")) 342 343 conn, ok := <-connCh 344 if !ok { 345 t.Fatalf("Server didn't return connection object") 346 } 347 defer conn.Close() 348 349 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 350 defer cancel() 351 // Create a stream, but send no data on it. 352 if _, err := client.NewStream(ctx, &CallHdr{}); err != nil { 353 t.Fatalf("Stream creation failed: %v", err) 354 } 355 356 if err := pollForStreamCreationError(client); err != nil { 357 t.Fatal(err) 358 } 359 } 360 361 // TestKeepaliveClientStaysHealthyWithResponsiveServer creates a server which 362 // responds to keepalive pings, and makes sure than a client transport stays 363 // healthy without any active streams. 364 func (s) TestKeepaliveClientStaysHealthyWithResponsiveServer(t *testing.T) { 365 server, client, cancel := setUpWithOptions(t, 0, 366 &ServerConfig{ 367 KeepalivePolicy: keepalive.EnforcementPolicy{ 368 MinTime: 50 * time.Millisecond, 369 PermitWithoutStream: true, 370 }, 371 }, 372 normal, 373 ConnectOptions{ 374 KeepaliveParams: keepalive.ClientParameters{ 375 Time: 55 * time.Millisecond, 376 Timeout: time.Second, 377 PermitWithoutStream: true, 378 }}) 379 defer func() { 380 client.Close(fmt.Errorf("closed manually by test")) 381 server.stop() 382 cancel() 383 }() 384 385 // Give keepalive some time. 386 time.Sleep(500 * time.Millisecond) 387 388 if err := checkForHealthyStream(client); err != nil { 389 t.Fatalf("Stream creation failed: %v", err) 390 } 391 } 392 393 // TestKeepaliveClientFrequency creates a server which expects at most 1 client 394 // ping for every 100 ms, while the client is configured to send a ping 395 // every 50 ms. So, this configuration should end up with the client 396 // transport being closed. But we had a bug wherein the client was sending one 397 // ping every [Time+Timeout] instead of every [Time] period, and this test 398 // explicitly makes sure the fix works and the client sends a ping every [Time] 399 // period. 400 func (s) TestKeepaliveClientFrequency(t *testing.T) { 401 grpctest.TLogger.ExpectError("Client received GoAway with error code ENHANCE_YOUR_CALM and debug data equal to ASCII \"too_many_pings\"") 402 403 serverConfig := &ServerConfig{ 404 KeepalivePolicy: keepalive.EnforcementPolicy{ 405 MinTime: 100 * time.Millisecond, 406 PermitWithoutStream: true, 407 }, 408 } 409 clientOptions := ConnectOptions{ 410 KeepaliveParams: keepalive.ClientParameters{ 411 Time: 50 * time.Millisecond, 412 Timeout: time.Second, 413 PermitWithoutStream: true, 414 }, 415 } 416 server, client, cancel := setUpWithOptions(t, 0, serverConfig, normal, clientOptions) 417 defer func() { 418 client.Close(fmt.Errorf("closed manually by test")) 419 server.stop() 420 cancel() 421 }() 422 423 if err := waitForGoAwayTooManyPings(client); err != nil { 424 t.Fatal(err) 425 } 426 } 427 428 // TestKeepaliveServerEnforcementWithAbusiveClientNoRPC verifies that the 429 // server closes a client transport when it sends too many keepalive pings 430 // (when there are no active streams), based on the configured 431 // EnforcementPolicy. 432 func (s) TestKeepaliveServerEnforcementWithAbusiveClientNoRPC(t *testing.T) { 433 grpctest.TLogger.ExpectError("Client received GoAway with error code ENHANCE_YOUR_CALM and debug data equal to ASCII \"too_many_pings\"") 434 435 serverConfig := &ServerConfig{ 436 KeepalivePolicy: keepalive.EnforcementPolicy{ 437 MinTime: time.Second, 438 }, 439 } 440 clientOptions := ConnectOptions{ 441 KeepaliveParams: keepalive.ClientParameters{ 442 Time: 20 * time.Millisecond, 443 Timeout: 100 * time.Millisecond, 444 PermitWithoutStream: true, 445 }, 446 } 447 server, client, cancel := setUpWithOptions(t, 0, serverConfig, normal, clientOptions) 448 defer func() { 449 client.Close(fmt.Errorf("closed manually by test")) 450 server.stop() 451 cancel() 452 }() 453 454 if err := waitForGoAwayTooManyPings(client); err != nil { 455 t.Fatal(err) 456 } 457 } 458 459 // TestKeepaliveServerEnforcementWithAbusiveClientWithRPC verifies that the 460 // server closes a client transport when it sends too many keepalive pings 461 // (even when there is an active stream), based on the configured 462 // EnforcementPolicy. 463 func (s) TestKeepaliveServerEnforcementWithAbusiveClientWithRPC(t *testing.T) { 464 grpctest.TLogger.ExpectError("Client received GoAway with error code ENHANCE_YOUR_CALM and debug data equal to ASCII \"too_many_pings\"") 465 466 serverConfig := &ServerConfig{ 467 KeepalivePolicy: keepalive.EnforcementPolicy{ 468 MinTime: time.Second, 469 }, 470 } 471 clientOptions := ConnectOptions{ 472 KeepaliveParams: keepalive.ClientParameters{ 473 Time: 50 * time.Millisecond, 474 Timeout: 100 * time.Millisecond, 475 }, 476 } 477 server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, clientOptions) 478 defer func() { 479 client.Close(fmt.Errorf("closed manually by test")) 480 server.stop() 481 cancel() 482 }() 483 484 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 485 defer cancel() 486 if _, err := client.NewStream(ctx, &CallHdr{}); err != nil { 487 t.Fatalf("Stream creation failed: %v", err) 488 } 489 490 if err := waitForGoAwayTooManyPings(client); err != nil { 491 t.Fatal(err) 492 } 493 } 494 495 // TestKeepaliveServerEnforcementWithObeyingClientNoRPC verifies that the 496 // server does not close a client transport (with no active streams) which 497 // sends keepalive pings in accordance to the configured keepalive 498 // EnforcementPolicy. 499 func (s) TestKeepaliveServerEnforcementWithObeyingClientNoRPC(t *testing.T) { 500 serverConfig := &ServerConfig{ 501 KeepalivePolicy: keepalive.EnforcementPolicy{ 502 MinTime: 40 * time.Millisecond, 503 PermitWithoutStream: true, 504 }, 505 } 506 clientOptions := ConnectOptions{ 507 KeepaliveParams: keepalive.ClientParameters{ 508 Time: 50 * time.Millisecond, 509 Timeout: time.Second, 510 PermitWithoutStream: true, 511 }, 512 } 513 server, client, cancel := setUpWithOptions(t, 0, serverConfig, normal, clientOptions) 514 defer func() { 515 client.Close(fmt.Errorf("closed manually by test")) 516 server.stop() 517 cancel() 518 }() 519 520 // Sleep for client to send ~10 keepalive pings. 521 time.Sleep(500 * time.Millisecond) 522 523 // Verify that the server does not close the client transport. 524 if err := checkForHealthyStream(client); err != nil { 525 t.Fatalf("Stream creation failed: %v", err) 526 } 527 } 528 529 // TestKeepaliveServerEnforcementWithObeyingClientWithRPC verifies that the 530 // server does not close a client transport (with active streams) which 531 // sends keepalive pings in accordance to the configured keepalive 532 // EnforcementPolicy. 533 func (s) TestKeepaliveServerEnforcementWithObeyingClientWithRPC(t *testing.T) { 534 serverConfig := &ServerConfig{ 535 KeepalivePolicy: keepalive.EnforcementPolicy{ 536 MinTime: 40 * time.Millisecond, 537 }, 538 } 539 clientOptions := ConnectOptions{ 540 KeepaliveParams: keepalive.ClientParameters{ 541 Time: 50 * time.Millisecond, 542 }, 543 } 544 server, client, cancel := setUpWithOptions(t, 0, serverConfig, suspended, clientOptions) 545 defer func() { 546 client.Close(fmt.Errorf("closed manually by test")) 547 server.stop() 548 cancel() 549 }() 550 551 if err := checkForHealthyStream(client); err != nil { 552 t.Fatalf("Stream creation failed: %v", err) 553 } 554 555 // Give keepalive enough time. 556 time.Sleep(500 * time.Millisecond) 557 558 if err := checkForHealthyStream(client); err != nil { 559 t.Fatalf("Stream creation failed: %v", err) 560 } 561 } 562 563 // TestKeepaliveServerEnforcementWithDormantKeepaliveOnClient verifies that the 564 // server does not closes a client transport, which has been configured to send 565 // more pings than allowed by the server's EnforcementPolicy. This client 566 // transport does not have any active streams and `PermitWithoutStream` is set 567 // to false. This should ensure that the keepalive functionality on the client 568 // side enters a dormant state. 569 func (s) TestKeepaliveServerEnforcementWithDormantKeepaliveOnClient(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: 10 * time.Millisecond, 578 Timeout: 10 * time.Millisecond, 579 }, 580 } 581 server, client, cancel := setUpWithOptions(t, 0, serverConfig, normal, clientOptions) 582 defer func() { 583 client.Close(fmt.Errorf("closed manually by test")) 584 server.stop() 585 cancel() 586 }() 587 588 // No active streams on the client. Give keepalive enough time. 589 time.Sleep(500 * time.Millisecond) 590 591 if err := checkForHealthyStream(client); err != nil { 592 t.Fatalf("Stream creation failed: %v", err) 593 } 594 } 595 596 // TestTCPUserTimeout tests that the TCP_USER_TIMEOUT socket option is set to 597 // the keepalive timeout, as detailed in proposal A18. 598 func (s) TestTCPUserTimeout(t *testing.T) { 599 tests := []struct { 600 tls bool 601 time time.Duration 602 timeout time.Duration 603 clientWantTimeout time.Duration 604 serverWantTimeout time.Duration 605 }{ 606 { 607 false, 608 10 * time.Second, 609 10 * time.Second, 610 10 * 1000 * time.Millisecond, 611 10 * 1000 * time.Millisecond, 612 }, 613 { 614 false, 615 0, 616 0, 617 0, 618 20 * 1000 * time.Millisecond, 619 }, 620 { 621 false, 622 infinity, 623 infinity, 624 0, 625 0, 626 }, 627 { 628 true, 629 10 * time.Second, 630 10 * time.Second, 631 10 * 1000 * time.Millisecond, 632 10 * 1000 * time.Millisecond, 633 }, 634 { 635 true, 636 0, 637 0, 638 0, 639 20 * 1000 * time.Millisecond, 640 }, 641 { 642 true, 643 infinity, 644 infinity, 645 0, 646 0, 647 }, 648 } 649 for _, tt := range tests { 650 sopts := &ServerConfig{ 651 KeepaliveParams: keepalive.ServerParameters{ 652 Time: tt.time, 653 Timeout: tt.timeout, 654 }, 655 } 656 657 copts := ConnectOptions{ 658 KeepaliveParams: keepalive.ClientParameters{ 659 Time: tt.time, 660 Timeout: tt.timeout, 661 }, 662 } 663 664 if tt.tls { 665 copts.TransportCredentials = makeTLSCreds(t, "x509/client1_cert.pem", "x509/client1_key.pem", "x509/server_ca_cert.pem") 666 sopts.Credentials = makeTLSCreds(t, "x509/server1_cert.pem", "x509/server1_key.pem", "x509/client_ca_cert.pem") 667 668 } 669 670 server, client, cancel := setUpWithOptions( 671 t, 672 0, 673 sopts, 674 normal, 675 copts, 676 ) 677 defer func() { 678 client.Close(fmt.Errorf("closed manually by test")) 679 server.stop() 680 cancel() 681 }() 682 683 var sc *http2Server 684 var srawConn net.Conn 685 // Wait until the server transport is setup. 686 for { 687 server.mu.Lock() 688 if len(server.conns) == 0 { 689 server.mu.Unlock() 690 time.Sleep(time.Millisecond) 691 continue 692 } 693 for k := range server.conns { 694 var ok bool 695 sc, ok = k.(*http2Server) 696 if !ok { 697 t.Fatalf("Failed to convert %v to *http2Server", k) 698 } 699 srawConn = server.conns[k] 700 } 701 server.mu.Unlock() 702 break 703 } 704 705 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 706 defer cancel() 707 stream, err := client.NewStream(ctx, &CallHdr{}) 708 if err != nil { 709 t.Fatalf("client.NewStream() failed: %v", err) 710 } 711 stream.Close(io.EOF) 712 713 // check client TCP user timeout only when non TLS 714 // TODO : find a way to get the underlying conn for client when TLS 715 if !tt.tls { 716 cltOpt, err := syscall.GetTCPUserTimeout(client.conn) 717 if err != nil { 718 t.Fatalf("syscall.GetTCPUserTimeout() failed: %v", err) 719 } 720 if cltOpt < 0 { 721 t.Skipf("skipping test on unsupported environment") 722 } 723 if gotTimeout := time.Duration(cltOpt) * time.Millisecond; gotTimeout != tt.clientWantTimeout { 724 t.Fatalf("syscall.GetTCPUserTimeout() = %d, want %d", gotTimeout, tt.clientWantTimeout) 725 } 726 } 727 scConn := sc.conn 728 if tt.tls { 729 if _, ok := sc.conn.(*net.TCPConn); ok { 730 t.Fatalf("sc.conn is should have wrapped conn with TLS") 731 } 732 scConn = srawConn 733 } 734 // verify the type of scConn (on which TCP user timeout will be got) 735 if _, ok := scConn.(*net.TCPConn); !ok { 736 t.Fatalf("server underlying conn is of type %T, want net.TCPConn", scConn) 737 } 738 srvOpt, err := syscall.GetTCPUserTimeout(scConn) 739 if err != nil { 740 t.Fatalf("syscall.GetTCPUserTimeout() failed: %v", err) 741 } 742 if gotTimeout := time.Duration(srvOpt) * time.Millisecond; gotTimeout != tt.serverWantTimeout { 743 t.Fatalf("syscall.GetTCPUserTimeout() = %d, want %d", gotTimeout, tt.serverWantTimeout) 744 } 745 746 } 747 } 748 749 func makeTLSCreds(t *testing.T, certPath, keyPath, rootsPath string) credentials.TransportCredentials { 750 cert, err := tls.LoadX509KeyPair(testdata.Path(certPath), testdata.Path(keyPath)) 751 if err != nil { 752 t.Fatalf("tls.LoadX509KeyPair(%q, %q) failed: %v", certPath, keyPath, err) 753 } 754 b, err := os.ReadFile(testdata.Path(rootsPath)) 755 if err != nil { 756 t.Fatalf("os.ReadFile(%q) failed: %v", rootsPath, err) 757 } 758 roots := x509.NewCertPool() 759 if !roots.AppendCertsFromPEM(b) { 760 t.Fatal("failed to append certificates") 761 } 762 return credentials.NewTLS(&tls.Config{ 763 Certificates: []tls.Certificate{cert}, 764 RootCAs: roots, 765 InsecureSkipVerify: true, 766 }) 767 } 768 769 // checkForHealthyStream attempts to create a stream and return error if any. 770 // The stream created is closed right after to avoid any leakages. 771 func checkForHealthyStream(client *http2Client) error { 772 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 773 defer cancel() 774 stream, err := client.NewStream(ctx, &CallHdr{}) 775 stream.Close(err) 776 return err 777 } 778 779 func pollForStreamCreationError(client *http2Client) error { 780 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 781 defer cancel() 782 for { 783 if _, err := client.NewStream(ctx, &CallHdr{}); err != nil { 784 break 785 } 786 time.Sleep(50 * time.Millisecond) 787 } 788 if ctx.Err() != nil { 789 return fmt.Errorf("test timed out before stream creation returned an error") 790 } 791 return nil 792 } 793 794 // waitForGoAwayTooManyPings waits for client to receive a GoAwayTooManyPings 795 // from server. It also asserts that stream creation fails after receiving a 796 // GoAway. 797 func waitForGoAwayTooManyPings(client *http2Client) error { 798 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 799 defer cancel() 800 select { 801 case <-client.GoAway(): 802 if reason, _ := client.GetGoAwayReason(); reason != GoAwayTooManyPings { 803 return fmt.Errorf("goAwayReason is %v, want %v", reason, GoAwayTooManyPings) 804 } 805 case <-ctx.Done(): 806 return fmt.Errorf("test timed out before getting GoAway with reason:GoAwayTooManyPings from server") 807 } 808 809 if _, err := client.NewStream(ctx, &CallHdr{}); err == nil { 810 return fmt.Errorf("stream creation succeeded after receiving a GoAway from the server") 811 } 812 return nil 813 }