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