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