gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/grpc/clientconn_test.go (about) 1 /* 2 * 3 * Copyright 2014 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 package grpc 20 21 import ( 22 "context" 23 "errors" 24 "fmt" 25 "math" 26 "net" 27 "strings" 28 "sync/atomic" 29 "testing" 30 "time" 31 32 "gitee.com/ks-custle/core-gm/grpc/backoff" 33 "gitee.com/ks-custle/core-gm/grpc/connectivity" 34 "gitee.com/ks-custle/core-gm/grpc/credentials" 35 internalbackoff "gitee.com/ks-custle/core-gm/grpc/internal/backoff" 36 "gitee.com/ks-custle/core-gm/grpc/internal/grpcsync" 37 "gitee.com/ks-custle/core-gm/grpc/internal/transport" 38 "gitee.com/ks-custle/core-gm/grpc/keepalive" 39 "gitee.com/ks-custle/core-gm/grpc/resolver" 40 "gitee.com/ks-custle/core-gm/grpc/resolver/manual" 41 "gitee.com/ks-custle/core-gm/grpc/testdata" 42 "gitee.com/ks-custle/core-gm/net/http2" 43 ) 44 45 func (s) TestDialWithTimeout(t *testing.T) { 46 lis, err := net.Listen("tcp", "localhost:0") 47 if err != nil { 48 t.Fatalf("Error while listening. Err: %v", err) 49 } 50 defer lis.Close() 51 lisAddr := resolver.Address{Addr: lis.Addr().String()} 52 lisDone := make(chan struct{}) 53 dialDone := make(chan struct{}) 54 // 1st listener accepts the connection and then does nothing 55 go func() { 56 defer close(lisDone) 57 conn, err := lis.Accept() 58 if err != nil { 59 t.Errorf("Error while accepting. Err: %v", err) 60 return 61 } 62 framer := http2.NewFramer(conn, conn) 63 if err := framer.WriteSettings(http2.Setting{}); err != nil { 64 t.Errorf("Error while writing settings. Err: %v", err) 65 return 66 } 67 <-dialDone // Close conn only after dial returns. 68 }() 69 70 r := manual.NewBuilderWithScheme("whatever") 71 r.InitialState(resolver.State{Addresses: []resolver.Address{lisAddr}}) 72 client, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithResolvers(r), WithTimeout(5*time.Second)) 73 close(dialDone) 74 if err != nil { 75 t.Fatalf("Dial failed. Err: %v", err) 76 } 77 defer client.Close() 78 timeout := time.After(1 * time.Second) 79 select { 80 case <-timeout: 81 t.Fatal("timed out waiting for server to finish") 82 case <-lisDone: 83 } 84 } 85 86 func (s) TestDialWithMultipleBackendsNotSendingServerPreface(t *testing.T) { 87 lis1, err := net.Listen("tcp", "localhost:0") 88 if err != nil { 89 t.Fatalf("Error while listening. Err: %v", err) 90 } 91 defer lis1.Close() 92 lis1Addr := resolver.Address{Addr: lis1.Addr().String()} 93 lis1Done := make(chan struct{}) 94 // 1st listener accepts the connection and immediately closes it. 95 go func() { 96 defer close(lis1Done) 97 conn, err := lis1.Accept() 98 if err != nil { 99 t.Errorf("Error while accepting. Err: %v", err) 100 return 101 } 102 conn.Close() 103 }() 104 105 lis2, err := net.Listen("tcp", "localhost:0") 106 if err != nil { 107 t.Fatalf("Error while listening. Err: %v", err) 108 } 109 defer lis2.Close() 110 lis2Done := make(chan struct{}) 111 lis2Addr := resolver.Address{Addr: lis2.Addr().String()} 112 // 2nd listener should get a connection attempt since the first one failed. 113 go func() { 114 defer close(lis2Done) 115 _, err := lis2.Accept() // Closing the client will clean up this conn. 116 if err != nil { 117 t.Errorf("Error while accepting. Err: %v", err) 118 return 119 } 120 }() 121 122 r := manual.NewBuilderWithScheme("whatever") 123 r.InitialState(resolver.State{Addresses: []resolver.Address{lis1Addr, lis2Addr}}) 124 client, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithResolvers(r)) 125 if err != nil { 126 t.Fatalf("Dial failed. Err: %v", err) 127 } 128 defer client.Close() 129 timeout := time.After(5 * time.Second) 130 select { 131 case <-timeout: 132 t.Fatal("timed out waiting for server 1 to finish") 133 case <-lis1Done: 134 } 135 select { 136 case <-timeout: 137 t.Fatal("timed out waiting for server 2 to finish") 138 case <-lis2Done: 139 } 140 } 141 142 func (s) TestDialWaitsForServerSettings(t *testing.T) { 143 lis, err := net.Listen("tcp", "localhost:0") 144 if err != nil { 145 t.Fatalf("Error while listening. Err: %v", err) 146 } 147 defer lis.Close() 148 done := make(chan struct{}) 149 sent := make(chan struct{}) 150 dialDone := make(chan struct{}) 151 go func() { // Launch the server. 152 defer func() { 153 close(done) 154 }() 155 conn, err := lis.Accept() 156 if err != nil { 157 t.Errorf("Error while accepting. Err: %v", err) 158 return 159 } 160 defer conn.Close() 161 // Sleep for a little bit to make sure that Dial on client 162 // side blocks until settings are received. 163 time.Sleep(100 * time.Millisecond) 164 framer := http2.NewFramer(conn, conn) 165 close(sent) 166 if err := framer.WriteSettings(http2.Setting{}); err != nil { 167 t.Errorf("Error while writing settings. Err: %v", err) 168 return 169 } 170 <-dialDone // Close conn only after dial returns. 171 }() 172 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 173 defer cancel() 174 client, err := DialContext(ctx, lis.Addr().String(), WithInsecure(), WithBlock()) 175 close(dialDone) 176 if err != nil { 177 t.Fatalf("Error while dialing. Err: %v", err) 178 } 179 defer client.Close() 180 select { 181 case <-sent: 182 default: 183 t.Fatalf("Dial returned before server settings were sent") 184 } 185 <-done 186 } 187 188 func (s) TestDialWaitsForServerSettingsAndFails(t *testing.T) { 189 lis, err := net.Listen("tcp", "localhost:0") 190 if err != nil { 191 t.Fatalf("Error while listening. Err: %v", err) 192 } 193 done := make(chan struct{}) 194 numConns := 0 195 go func() { // Launch the server. 196 defer func() { 197 close(done) 198 }() 199 for { 200 conn, err := lis.Accept() 201 if err != nil { 202 break 203 } 204 numConns++ 205 defer conn.Close() 206 } 207 }() 208 ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) 209 defer cancel() 210 client, err := DialContext(ctx, 211 lis.Addr().String(), 212 WithInsecure(), 213 WithReturnConnectionError(), 214 withBackoff(noBackoff{}), 215 withMinConnectDeadline(func() time.Duration { return time.Second / 4 })) 216 lis.Close() 217 if err == nil { 218 client.Close() 219 t.Fatalf("Unexpected success (err=nil) while dialing") 220 } 221 expectedMsg := "server preface" 222 if !strings.Contains(err.Error(), context.DeadlineExceeded.Error()) || !strings.Contains(err.Error(), expectedMsg) { 223 t.Fatalf("DialContext(_) = %v; want a message that includes both %q and %q", err, context.DeadlineExceeded.Error(), expectedMsg) 224 } 225 <-done 226 if numConns < 2 { 227 t.Fatalf("dial attempts: %v; want > 1", numConns) 228 } 229 } 230 231 // 1. Client connects to a server that doesn't send preface. 232 // 2. After minConnectTimeout(500 ms here), client disconnects and retries. 233 // 3. The new server sends its preface. 234 // 4. Client doesn't kill the connection this time. 235 func (s) TestCloseConnectionWhenServerPrefaceNotReceived(t *testing.T) { 236 lis, err := net.Listen("tcp", "localhost:0") 237 if err != nil { 238 t.Fatalf("Error while listening. Err: %v", err) 239 } 240 var ( 241 conn2 net.Conn 242 over uint32 243 ) 244 defer func() { 245 lis.Close() 246 // conn2 shouldn't be closed until the client has 247 // observed a successful test. 248 if conn2 != nil { 249 conn2.Close() 250 } 251 }() 252 done := make(chan struct{}) 253 accepted := make(chan struct{}) 254 go func() { // Launch the server. 255 defer close(done) 256 conn1, err := lis.Accept() 257 if err != nil { 258 t.Errorf("Error while accepting. Err: %v", err) 259 return 260 } 261 defer conn1.Close() 262 // Don't send server settings and the client should close the connection and try again. 263 conn2, err = lis.Accept() // Accept a reconnection request from client. 264 if err != nil { 265 t.Errorf("Error while accepting. Err: %v", err) 266 return 267 } 268 close(accepted) 269 framer := http2.NewFramer(conn2, conn2) 270 if err = framer.WriteSettings(http2.Setting{}); err != nil { 271 t.Errorf("Error while writing settings. Err: %v", err) 272 return 273 } 274 b := make([]byte, 8) 275 for { 276 _, err = conn2.Read(b) 277 if err == nil { 278 continue 279 } 280 if atomic.LoadUint32(&over) == 1 { 281 // The connection stayed alive for the timer. 282 // Success. 283 return 284 } 285 t.Errorf("Unexpected error while reading. Err: %v, want timeout error", err) 286 break 287 } 288 }() 289 client, err := Dial(lis.Addr().String(), WithInsecure(), withMinConnectDeadline(func() time.Duration { return time.Millisecond * 500 })) 290 if err != nil { 291 t.Fatalf("Error while dialing. Err: %v", err) 292 } 293 294 go stayConnected(client) 295 296 // wait for connection to be accepted on the server. 297 timer := time.NewTimer(time.Second * 10) 298 select { 299 case <-accepted: 300 case <-timer.C: 301 t.Fatalf("Client didn't make another connection request in time.") 302 } 303 // Make sure the connection stays alive for sometime. 304 time.Sleep(time.Second) 305 atomic.StoreUint32(&over, 1) 306 client.Close() 307 <-done 308 } 309 310 func (s) TestBackoffWhenNoServerPrefaceReceived(t *testing.T) { 311 lis, err := net.Listen("tcp", "localhost:0") 312 if err != nil { 313 t.Fatalf("Error while listening. Err: %v", err) 314 } 315 defer lis.Close() 316 done := make(chan struct{}) 317 go func() { // Launch the server. 318 defer close(done) 319 conn, err := lis.Accept() // Accept the connection only to close it immediately. 320 if err != nil { 321 t.Errorf("Error while accepting. Err: %v", err) 322 return 323 } 324 prevAt := time.Now() 325 conn.Close() 326 var prevDuration time.Duration 327 // Make sure the retry attempts are backed off properly. 328 for i := 0; i < 3; i++ { 329 conn, err := lis.Accept() 330 if err != nil { 331 t.Errorf("Error while accepting. Err: %v", err) 332 return 333 } 334 meow := time.Now() 335 conn.Close() 336 dr := meow.Sub(prevAt) 337 if dr <= prevDuration { 338 t.Errorf("Client backoff did not increase with retries. Previous duration: %v, current duration: %v", prevDuration, dr) 339 return 340 } 341 prevDuration = dr 342 prevAt = meow 343 } 344 }() 345 cc, err := Dial(lis.Addr().String(), WithInsecure()) 346 if err != nil { 347 t.Fatalf("Error while dialing. Err: %v", err) 348 } 349 defer cc.Close() 350 go stayConnected(cc) 351 <-done 352 } 353 354 func (s) TestWithTimeout(t *testing.T) { 355 conn, err := Dial("passthrough:///Non-Existent.Server:80", WithTimeout(time.Millisecond), WithBlock(), WithInsecure()) 356 if err == nil { 357 conn.Close() 358 } 359 if err != context.DeadlineExceeded { 360 t.Fatalf("Dial(_, _) = %v, %v, want %v", conn, err, context.DeadlineExceeded) 361 } 362 } 363 364 func (s) TestWithTransportCredentialsTLS(t *testing.T) { 365 ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) 366 defer cancel() 367 creds, err := credentials.NewClientTLSFromFile(testdata.Path("x509/server_ca_cert.pem"), "x.test.example.com") 368 if err != nil { 369 t.Fatalf("Failed to create credentials %v", err) 370 } 371 conn, err := DialContext(ctx, "passthrough:///Non-Existent.Server:80", WithTransportCredentials(creds), WithBlock()) 372 if err == nil { 373 conn.Close() 374 } 375 if err != context.DeadlineExceeded { 376 t.Fatalf("Dial(_, _) = %v, %v, want %v", conn, err, context.DeadlineExceeded) 377 } 378 } 379 380 // When creating a transport configured with n addresses, only calculate the 381 // backoff once per "round" of attempts instead of once per address (n times 382 // per "round" of attempts). 383 func (s) TestDial_OneBackoffPerRetryGroup(t *testing.T) { 384 var attempts uint32 385 getMinConnectTimeout := func() time.Duration { 386 if atomic.AddUint32(&attempts, 1) == 1 { 387 // Once all addresses are exhausted, hang around and wait for the 388 // client.Close to happen rather than re-starting a new round of 389 // attempts. 390 return time.Hour 391 } 392 t.Error("only one attempt backoff calculation, but got more") 393 return 0 394 } 395 396 ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) 397 defer cancel() 398 399 lis1, err := net.Listen("tcp", "localhost:0") 400 if err != nil { 401 t.Fatalf("Error while listening. Err: %v", err) 402 } 403 defer lis1.Close() 404 405 lis2, err := net.Listen("tcp", "localhost:0") 406 if err != nil { 407 t.Fatalf("Error while listening. Err: %v", err) 408 } 409 defer lis2.Close() 410 411 server1Done := make(chan struct{}) 412 server2Done := make(chan struct{}) 413 414 // Launch server 1. 415 go func() { 416 conn, err := lis1.Accept() 417 if err != nil { 418 t.Error(err) 419 return 420 } 421 422 conn.Close() 423 close(server1Done) 424 }() 425 // Launch server 2. 426 go func() { 427 conn, err := lis2.Accept() 428 if err != nil { 429 t.Error(err) 430 return 431 } 432 conn.Close() 433 close(server2Done) 434 }() 435 436 rb := manual.NewBuilderWithScheme("whatever") 437 rb.InitialState(resolver.State{Addresses: []resolver.Address{ 438 {Addr: lis1.Addr().String()}, 439 {Addr: lis2.Addr().String()}, 440 }}) 441 client, err := DialContext(ctx, "whatever:///this-gets-overwritten", 442 WithInsecure(), 443 WithBalancerName(stateRecordingBalancerName), 444 WithResolvers(rb), 445 withMinConnectDeadline(getMinConnectTimeout)) 446 if err != nil { 447 t.Fatal(err) 448 } 449 defer client.Close() 450 451 timeout := time.After(15 * time.Second) 452 453 select { 454 case <-timeout: 455 t.Fatal("timed out waiting for test to finish") 456 case <-server1Done: 457 } 458 459 select { 460 case <-timeout: 461 t.Fatal("timed out waiting for test to finish") 462 case <-server2Done: 463 } 464 } 465 466 func (s) TestDialContextCancel(t *testing.T) { 467 ctx, cancel := context.WithCancel(context.Background()) 468 cancel() 469 if _, err := DialContext(ctx, "Non-Existent.Server:80", WithBlock(), WithInsecure()); err != context.Canceled { 470 t.Fatalf("DialContext(%v, _) = _, %v, want _, %v", ctx, err, context.Canceled) 471 } 472 } 473 474 type failFastError struct{} 475 476 func (failFastError) Error() string { return "failfast" } 477 func (failFastError) Temporary() bool { return false } 478 479 func (s) TestDialContextFailFast(t *testing.T) { 480 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 481 defer cancel() 482 failErr := failFastError{} 483 dialer := func(string, time.Duration) (net.Conn, error) { 484 return nil, failErr 485 } 486 487 _, err := DialContext(ctx, "Non-Existent.Server:80", WithBlock(), WithInsecure(), WithDialer(dialer), FailOnNonTempDialError(true)) 488 if terr, ok := err.(transport.ConnectionError); !ok || terr.Origin() != failErr { 489 t.Fatalf("DialContext() = _, %v, want _, %v", err, failErr) 490 } 491 } 492 493 // securePerRPCCredentials always requires transport security. 494 type securePerRPCCredentials struct { 495 credentials.PerRPCCredentials 496 } 497 498 func (c securePerRPCCredentials) RequireTransportSecurity() bool { 499 return true 500 } 501 502 type fakeBundleCreds struct { 503 credentials.Bundle 504 transportCreds credentials.TransportCredentials 505 } 506 507 func (b *fakeBundleCreds) TransportCredentials() credentials.TransportCredentials { 508 return b.transportCreds 509 } 510 511 func (s) TestCredentialsMisuse(t *testing.T) { 512 // Use of no transport creds and no creds bundle must fail. 513 if _, err := Dial("passthrough:///Non-Existent.Server:80"); err != errNoTransportSecurity { 514 t.Fatalf("Dial(_, _) = _, %v, want _, %v", err, errNoTransportSecurity) 515 } 516 517 // Use of both transport creds and creds bundle must fail. 518 creds, err := credentials.NewClientTLSFromFile(testdata.Path("x509/server_ca_cert.pem"), "x.test.example.com") 519 if err != nil { 520 t.Fatalf("Failed to create authenticator %v", err) 521 } 522 dopts := []DialOption{ 523 WithTransportCredentials(creds), 524 WithCredentialsBundle(&fakeBundleCreds{transportCreds: creds}), 525 } 526 if _, err := Dial("passthrough:///Non-Existent.Server:80", dopts...); err != errTransportCredsAndBundle { 527 t.Fatalf("Dial(_, _) = _, %v, want _, %v", err, errTransportCredsAndBundle) 528 } 529 530 // Use of perRPC creds requiring transport security over an insecure 531 // transport must fail. 532 if _, err := Dial("passthrough:///Non-Existent.Server:80", WithPerRPCCredentials(securePerRPCCredentials{}), WithInsecure()); err != errTransportCredentialsMissing { 533 t.Fatalf("Dial(_, _) = _, %v, want _, %v", err, errTransportCredentialsMissing) 534 } 535 536 // Use of a creds bundle with nil transport credentials must fail. 537 if _, err := Dial("passthrough:///Non-Existent.Server:80", WithCredentialsBundle(&fakeBundleCreds{})); err != errNoTransportCredsInBundle { 538 t.Fatalf("Dial(_, _) = _, %v, want _, %v", err, errTransportCredsAndBundle) 539 } 540 } 541 542 func (s) TestWithBackoffConfigDefault(t *testing.T) { 543 testBackoffConfigSet(t, internalbackoff.DefaultExponential) 544 } 545 546 func (s) TestWithBackoffConfig(t *testing.T) { 547 b := BackoffConfig{MaxDelay: DefaultBackoffConfig.MaxDelay / 2} 548 bc := backoff.DefaultConfig 549 bc.MaxDelay = b.MaxDelay 550 wantBackoff := internalbackoff.Exponential{Config: bc} 551 testBackoffConfigSet(t, wantBackoff, WithBackoffConfig(b)) 552 } 553 554 func (s) TestWithBackoffMaxDelay(t *testing.T) { 555 md := DefaultBackoffConfig.MaxDelay / 2 556 bc := backoff.DefaultConfig 557 bc.MaxDelay = md 558 wantBackoff := internalbackoff.Exponential{Config: bc} 559 testBackoffConfigSet(t, wantBackoff, WithBackoffMaxDelay(md)) 560 } 561 562 func (s) TestWithConnectParams(t *testing.T) { 563 bd := 2 * time.Second 564 mltpr := 2.0 565 jitter := 0.0 566 bc := backoff.Config{BaseDelay: bd, Multiplier: mltpr, Jitter: jitter} 567 568 crt := ConnectParams{Backoff: bc} 569 // MaxDelay is not set in the ConnectParams. So it should not be set on 570 // internalbackoff.Exponential as well. 571 wantBackoff := internalbackoff.Exponential{Config: bc} 572 testBackoffConfigSet(t, wantBackoff, WithConnectParams(crt)) 573 } 574 575 func testBackoffConfigSet(t *testing.T, wantBackoff internalbackoff.Exponential, opts ...DialOption) { 576 opts = append(opts, WithInsecure()) 577 conn, err := Dial("passthrough:///foo:80", opts...) 578 if err != nil { 579 t.Fatalf("unexpected error dialing connection: %v", err) 580 } 581 defer conn.Close() 582 583 if conn.dopts.bs == nil { 584 t.Fatalf("backoff config not set") 585 } 586 587 gotBackoff, ok := conn.dopts.bs.(internalbackoff.Exponential) 588 if !ok { 589 t.Fatalf("unexpected type of backoff config: %#v", conn.dopts.bs) 590 } 591 592 if gotBackoff != wantBackoff { 593 t.Fatalf("unexpected backoff config on connection: %v, want %v", gotBackoff, wantBackoff) 594 } 595 } 596 597 func (s) TestConnectParamsWithMinConnectTimeout(t *testing.T) { 598 // Default value specified for minConnectTimeout in the spec is 20 seconds. 599 mct := 1 * time.Minute 600 conn, err := Dial("passthrough:///foo:80", WithInsecure(), WithConnectParams(ConnectParams{MinConnectTimeout: mct})) 601 if err != nil { 602 t.Fatalf("unexpected error dialing connection: %v", err) 603 } 604 defer conn.Close() 605 606 if got := conn.dopts.minConnectTimeout(); got != mct { 607 t.Errorf("unexpect minConnectTimeout on the connection: %v, want %v", got, mct) 608 } 609 } 610 611 func (s) TestResolverServiceConfigBeforeAddressNotPanic(t *testing.T) { 612 r := manual.NewBuilderWithScheme("whatever") 613 614 cc, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithResolvers(r)) 615 if err != nil { 616 t.Fatalf("failed to dial: %v", err) 617 } 618 defer cc.Close() 619 620 // SwitchBalancer before NewAddress. There was no balancer created, this 621 // makes sure we don't call close on nil balancerWrapper. 622 r.UpdateState(resolver.State{ServiceConfig: parseCfg(r, `{"loadBalancingPolicy": "round_robin"}`)}) // This should not panic. 623 624 time.Sleep(time.Second) // Sleep to make sure the service config is handled by ClientConn. 625 } 626 627 func (s) TestResolverServiceConfigWhileClosingNotPanic(t *testing.T) { 628 for i := 0; i < 10; i++ { // Run this multiple times to make sure it doesn't panic. 629 r := manual.NewBuilderWithScheme(fmt.Sprintf("whatever-%d", i)) 630 631 cc, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithResolvers(r)) 632 if err != nil { 633 t.Fatalf("failed to dial: %v", err) 634 } 635 // Send a new service config while closing the ClientConn. 636 go cc.Close() 637 go r.UpdateState(resolver.State{ServiceConfig: parseCfg(r, `{"loadBalancingPolicy": "round_robin"}`)}) // This should not panic. 638 } 639 } 640 641 func (s) TestResolverEmptyUpdateNotPanic(t *testing.T) { 642 r := manual.NewBuilderWithScheme("whatever") 643 644 cc, err := Dial(r.Scheme()+":///test.server", WithInsecure(), WithResolvers(r)) 645 if err != nil { 646 t.Fatalf("failed to dial: %v", err) 647 } 648 defer cc.Close() 649 650 // This make sure we don't create addrConn with empty address list. 651 r.UpdateState(resolver.State{}) // This should not panic. 652 653 time.Sleep(time.Second) // Sleep to make sure the service config is handled by ClientConn. 654 } 655 656 func (s) TestClientUpdatesParamsAfterGoAway(t *testing.T) { 657 lis, err := net.Listen("tcp", "localhost:0") 658 if err != nil { 659 t.Fatalf("Failed to listen. Err: %v", err) 660 } 661 defer lis.Close() 662 connected := grpcsync.NewEvent() 663 defer connected.Fire() 664 go func() { 665 conn, err := lis.Accept() 666 if err != nil { 667 t.Errorf("error accepting connection: %v", err) 668 return 669 } 670 defer conn.Close() 671 f := http2.NewFramer(conn, conn) 672 // Start a goroutine to read from the conn to prevent the client from 673 // blocking after it writes its preface. 674 go func() { 675 for { 676 if _, err := f.ReadFrame(); err != nil { 677 return 678 } 679 } 680 }() 681 if err := f.WriteSettings(http2.Setting{}); err != nil { 682 t.Errorf("error writing settings: %v", err) 683 return 684 } 685 <-connected.Done() 686 if err := f.WriteGoAway(0, http2.ErrCodeEnhanceYourCalm, []byte("too_many_pings")); err != nil { 687 t.Errorf("error writing GOAWAY: %v", err) 688 return 689 } 690 }() 691 addr := lis.Addr().String() 692 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 693 defer cancel() 694 cc, err := DialContext(ctx, addr, WithBlock(), WithInsecure(), WithKeepaliveParams(keepalive.ClientParameters{ 695 Time: 10 * time.Second, 696 Timeout: 100 * time.Millisecond, 697 PermitWithoutStream: true, 698 })) 699 if err != nil { 700 t.Fatalf("Dial(%s, _) = _, %v, want _, <nil>", addr, err) 701 } 702 defer cc.Close() 703 connected.Fire() 704 for { 705 time.Sleep(10 * time.Millisecond) 706 cc.mu.RLock() 707 v := cc.mkp.Time 708 cc.mu.RUnlock() 709 if v == 20*time.Second { 710 // Success 711 return 712 } 713 if ctx.Err() != nil { 714 // Timeout 715 t.Fatalf("cc.dopts.copts.Keepalive.Time = %v , want 20s", v) 716 } 717 } 718 } 719 720 func (s) TestDisableServiceConfigOption(t *testing.T) { 721 r := manual.NewBuilderWithScheme("whatever") 722 addr := r.Scheme() + ":///non.existent" 723 cc, err := Dial(addr, WithInsecure(), WithResolvers(r), WithDisableServiceConfig()) 724 if err != nil { 725 t.Fatalf("Dial(%s, _) = _, %v, want _, <nil>", addr, err) 726 } 727 defer cc.Close() 728 r.UpdateState(resolver.State{ServiceConfig: parseCfg(r, `{ 729 "methodConfig": [ 730 { 731 "name": [ 732 { 733 "service": "foo", 734 "method": "Bar" 735 } 736 ], 737 "waitForReady": true 738 } 739 ] 740 }`)}) 741 time.Sleep(1 * time.Second) 742 m := cc.GetMethodConfig("/foo/Bar") 743 if m.WaitForReady != nil { 744 t.Fatalf("want: method (\"/foo/bar/\") config to be empty, got: %+v", m) 745 } 746 } 747 748 func (s) TestMethodConfigDefaultService(t *testing.T) { 749 addr := "nonexist:///non.existent" 750 cc, err := Dial(addr, WithInsecure(), WithDefaultServiceConfig(`{ 751 "methodConfig": [{ 752 "name": [ 753 { 754 "service": "" 755 } 756 ], 757 "waitForReady": true 758 }] 759 }`)) 760 if err != nil { 761 t.Fatalf("Dial(%s, _) = _, %v, want _, <nil>", addr, err) 762 } 763 defer cc.Close() 764 765 m := cc.GetMethodConfig("/foo/Bar") 766 if m.WaitForReady == nil { 767 t.Fatalf("want: method (%q) config to fallback to the default service", "/foo/Bar") 768 } 769 } 770 771 func (s) TestGetClientConnTarget(t *testing.T) { 772 addr := "nonexist:///non.existent" 773 cc, err := Dial(addr, WithInsecure()) 774 if err != nil { 775 t.Fatalf("Dial(%s, _) = _, %v, want _, <nil>", addr, err) 776 } 777 defer cc.Close() 778 if cc.Target() != addr { 779 t.Fatalf("Target() = %s, want %s", cc.Target(), addr) 780 } 781 } 782 783 type backoffForever struct{} 784 785 func (b backoffForever) Backoff(int) time.Duration { return time.Duration(math.MaxInt64) } 786 787 func (s) TestResetConnectBackoff(t *testing.T) { 788 dials := make(chan struct{}) 789 defer func() { // If we fail, let the http2client break out of dialing. 790 select { 791 case <-dials: 792 default: 793 } 794 }() 795 dialer := func(string, time.Duration) (net.Conn, error) { 796 dials <- struct{}{} 797 return nil, errors.New("failed to fake dial") 798 } 799 cc, err := Dial("any", WithInsecure(), WithDialer(dialer), withBackoff(backoffForever{})) 800 if err != nil { 801 t.Fatalf("Dial() = _, %v; want _, nil", err) 802 } 803 defer cc.Close() 804 go stayConnected(cc) 805 select { 806 case <-dials: 807 case <-time.NewTimer(10 * time.Second).C: 808 t.Fatal("Failed to call dial within 10s") 809 } 810 811 select { 812 case <-dials: 813 t.Fatal("Dial called unexpectedly before resetting backoff") 814 case <-time.NewTimer(100 * time.Millisecond).C: 815 } 816 817 cc.ResetConnectBackoff() 818 819 select { 820 case <-dials: 821 case <-time.NewTimer(10 * time.Second).C: 822 t.Fatal("Failed to call dial within 10s after resetting backoff") 823 } 824 } 825 826 func (s) TestBackoffCancel(t *testing.T) { 827 dialStrCh := make(chan string) 828 cc, err := Dial("any", WithInsecure(), WithDialer(func(t string, _ time.Duration) (net.Conn, error) { 829 dialStrCh <- t 830 return nil, fmt.Errorf("test dialer, always error") 831 })) 832 if err != nil { 833 t.Fatalf("Failed to create ClientConn: %v", err) 834 } 835 <-dialStrCh 836 cc.Close() 837 // Should not leak. May need -count 5000 to exercise. 838 } 839 840 // UpdateAddresses should cause the next reconnect to begin from the top of the 841 // list if the connection is not READY. 842 func (s) TestUpdateAddresses_RetryFromFirstAddr(t *testing.T) { 843 lis1, err := net.Listen("tcp", "localhost:0") 844 if err != nil { 845 t.Fatalf("Error while listening. Err: %v", err) 846 } 847 defer lis1.Close() 848 849 lis2, err := net.Listen("tcp", "localhost:0") 850 if err != nil { 851 t.Fatalf("Error while listening. Err: %v", err) 852 } 853 defer lis2.Close() 854 855 lis3, err := net.Listen("tcp", "localhost:0") 856 if err != nil { 857 t.Fatalf("Error while listening. Err: %v", err) 858 } 859 defer lis3.Close() 860 861 closeServer2 := make(chan struct{}) 862 exitCh := make(chan struct{}) 863 server1ContactedFirstTime := make(chan struct{}) 864 server1ContactedSecondTime := make(chan struct{}) 865 server2ContactedFirstTime := make(chan struct{}) 866 server2ContactedSecondTime := make(chan struct{}) 867 server3Contacted := make(chan struct{}) 868 869 defer close(exitCh) 870 871 // Launch server 1. 872 go func() { 873 // First, let's allow the initial connection to go READY. We need to do 874 // this because tryUpdateAddrs only works after there's some non-nil 875 // address on the ac, and curAddress is only set after READY. 876 conn1, err := lis1.Accept() 877 if err != nil { 878 t.Error(err) 879 return 880 } 881 go keepReading(conn1) 882 883 framer := http2.NewFramer(conn1, conn1) 884 if err := framer.WriteSettings(http2.Setting{}); err != nil { 885 t.Errorf("Error while writing settings frame. %v", err) 886 return 887 } 888 889 // nextStateNotifier() is updated after balancerBuilder.Build(), which is 890 // called by grpc.Dial. It's safe to do it here because lis1.Accept blocks 891 // until balancer is built to process the addresses. 892 stateNotifications := testBalancerBuilder.nextStateNotifier() 893 // Wait for the transport to become ready. 894 for { 895 select { 896 case st := <-stateNotifications: 897 if st == connectivity.Ready { 898 goto ready 899 } 900 case <-exitCh: 901 return 902 } 903 } 904 905 ready: 906 // Once it's ready, curAddress has been set. So let's close this 907 // connection prompting the first reconnect cycle. 908 conn1.Close() 909 910 // Accept and immediately close, causing it to go to server2. 911 conn2, err := lis1.Accept() 912 if err != nil { 913 t.Error(err) 914 return 915 } 916 close(server1ContactedFirstTime) 917 conn2.Close() 918 919 // Hopefully it picks this server after tryUpdateAddrs. 920 lis1.Accept() 921 close(server1ContactedSecondTime) 922 }() 923 // Launch server 2. 924 go func() { 925 // Accept and then hang waiting for the test call tryUpdateAddrs and 926 // then signal to this server to close. After this server closes, it 927 // should start from the top instead of trying server2 or continuing 928 // to server3. 929 conn, err := lis2.Accept() 930 if err != nil { 931 t.Error(err) 932 return 933 } 934 935 close(server2ContactedFirstTime) 936 <-closeServer2 937 conn.Close() 938 939 // After tryUpdateAddrs, it should NOT try server2. 940 lis2.Accept() 941 close(server2ContactedSecondTime) 942 }() 943 // Launch server 3. 944 go func() { 945 // After tryUpdateAddrs, it should NOT try server3. (or any other time) 946 lis3.Accept() 947 close(server3Contacted) 948 }() 949 950 addrsList := []resolver.Address{ 951 {Addr: lis1.Addr().String()}, 952 {Addr: lis2.Addr().String()}, 953 {Addr: lis3.Addr().String()}, 954 } 955 rb := manual.NewBuilderWithScheme("whatever") 956 rb.InitialState(resolver.State{Addresses: addrsList}) 957 958 client, err := Dial("whatever:///this-gets-overwritten", 959 WithInsecure(), 960 WithResolvers(rb), 961 withBackoff(noBackoff{}), 962 WithBalancerName(stateRecordingBalancerName), 963 withMinConnectDeadline(func() time.Duration { return time.Hour })) 964 if err != nil { 965 t.Fatal(err) 966 } 967 defer client.Close() 968 go stayConnected(client) 969 970 timeout := time.After(5 * time.Second) 971 972 // Wait for server1 to be contacted (which will immediately fail), then 973 // server2 (which will hang waiting for our signal). 974 select { 975 case <-server1ContactedFirstTime: 976 case <-timeout: 977 t.Fatal("timed out waiting for server1 to be contacted") 978 } 979 select { 980 case <-server2ContactedFirstTime: 981 case <-timeout: 982 t.Fatal("timed out waiting for server2 to be contacted") 983 } 984 985 // Grab the addrConn and call tryUpdateAddrs. 986 var ac *addrConn 987 client.mu.Lock() 988 for clientAC := range client.conns { 989 ac = clientAC 990 break 991 } 992 client.mu.Unlock() 993 994 ac.acbw.UpdateAddresses(addrsList) 995 996 // We've called tryUpdateAddrs - now let's make server2 close the 997 // connection and check that it goes back to server1 instead of continuing 998 // to server3 or trying server2 again. 999 close(closeServer2) 1000 1001 select { 1002 case <-server1ContactedSecondTime: 1003 case <-server2ContactedSecondTime: 1004 t.Fatal("server2 was contacted a second time, but it after tryUpdateAddrs it should have re-started the list and tried server1") 1005 case <-server3Contacted: 1006 t.Fatal("server3 was contacted, but after tryUpdateAddrs it should have re-started the list and tried server1") 1007 case <-timeout: 1008 t.Fatal("timed out waiting for any server to be contacted after tryUpdateAddrs") 1009 } 1010 } 1011 1012 func (s) TestDefaultServiceConfig(t *testing.T) { 1013 r := manual.NewBuilderWithScheme("whatever") 1014 addr := r.Scheme() + ":///non.existent" 1015 js := `{ 1016 "methodConfig": [ 1017 { 1018 "name": [ 1019 { 1020 "service": "foo", 1021 "method": "bar" 1022 } 1023 ], 1024 "waitForReady": true 1025 } 1026 ] 1027 }` 1028 testInvalidDefaultServiceConfig(t) 1029 testDefaultServiceConfigWhenResolverServiceConfigDisabled(t, r, addr, js) 1030 testDefaultServiceConfigWhenResolverDoesNotReturnServiceConfig(t, r, addr, js) 1031 testDefaultServiceConfigWhenResolverReturnInvalidServiceConfig(t, r, addr, js) 1032 } 1033 1034 func verifyWaitForReadyEqualsTrue(cc *ClientConn) bool { 1035 var i int 1036 for i = 0; i < 10; i++ { 1037 mc := cc.GetMethodConfig("/foo/bar") 1038 if mc.WaitForReady != nil && *mc.WaitForReady == true { 1039 break 1040 } 1041 time.Sleep(100 * time.Millisecond) 1042 } 1043 return i != 10 1044 } 1045 1046 func testInvalidDefaultServiceConfig(t *testing.T) { 1047 _, err := Dial("fake.com", WithInsecure(), WithDefaultServiceConfig("")) 1048 if !strings.Contains(err.Error(), invalidDefaultServiceConfigErrPrefix) { 1049 t.Fatalf("Dial got err: %v, want err contains: %v", err, invalidDefaultServiceConfigErrPrefix) 1050 } 1051 } 1052 1053 func testDefaultServiceConfigWhenResolverServiceConfigDisabled(t *testing.T, r *manual.Resolver, addr string, js string) { 1054 cc, err := Dial(addr, WithInsecure(), WithDisableServiceConfig(), WithResolvers(r), WithDefaultServiceConfig(js)) 1055 if err != nil { 1056 t.Fatalf("Dial(%s, _) = _, %v, want _, <nil>", addr, err) 1057 } 1058 defer cc.Close() 1059 // Resolver service config gets ignored since resolver service config is disabled. 1060 r.UpdateState(resolver.State{ 1061 Addresses: []resolver.Address{{Addr: addr}}, 1062 ServiceConfig: parseCfg(r, "{}"), 1063 }) 1064 if !verifyWaitForReadyEqualsTrue(cc) { 1065 t.Fatal("default service config failed to be applied after 1s") 1066 } 1067 } 1068 1069 func testDefaultServiceConfigWhenResolverDoesNotReturnServiceConfig(t *testing.T, r *manual.Resolver, addr string, js string) { 1070 cc, err := Dial(addr, WithInsecure(), WithResolvers(r), WithDefaultServiceConfig(js)) 1071 if err != nil { 1072 t.Fatalf("Dial(%s, _) = _, %v, want _, <nil>", addr, err) 1073 } 1074 defer cc.Close() 1075 r.UpdateState(resolver.State{ 1076 Addresses: []resolver.Address{{Addr: addr}}, 1077 }) 1078 if !verifyWaitForReadyEqualsTrue(cc) { 1079 t.Fatal("default service config failed to be applied after 1s") 1080 } 1081 } 1082 1083 func testDefaultServiceConfigWhenResolverReturnInvalidServiceConfig(t *testing.T, r *manual.Resolver, addr string, js string) { 1084 cc, err := Dial(addr, WithInsecure(), WithResolvers(r), WithDefaultServiceConfig(js)) 1085 if err != nil { 1086 t.Fatalf("Dial(%s, _) = _, %v, want _, <nil>", addr, err) 1087 } 1088 defer cc.Close() 1089 r.UpdateState(resolver.State{ 1090 Addresses: []resolver.Address{{Addr: addr}}, 1091 }) 1092 if !verifyWaitForReadyEqualsTrue(cc) { 1093 t.Fatal("default service config failed to be applied after 1s") 1094 } 1095 } 1096 1097 // stayConnected makes cc stay connected by repeatedly calling cc.Connect() 1098 // until the state becomes Shutdown or until 10 seconds elapses. 1099 func stayConnected(cc *ClientConn) { 1100 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 1101 defer cancel() 1102 1103 for { 1104 state := cc.GetState() 1105 switch state { 1106 case connectivity.Idle: 1107 cc.Connect() 1108 case connectivity.Shutdown: 1109 return 1110 } 1111 if !cc.WaitForStateChange(ctx, state) { 1112 return 1113 } 1114 } 1115 }