Repository: grpc/grpc-go

Issue:
ringhash: Update ringhash to handle conditions under which to make child balancers exit idle state
While working on https://github.com/grpc/grpc-go/pull/8047,  a boolean `endpointEnteredTF` was added based on the the pseudocode in [A61](https://github.com/grpc/proposal/blob/master/A61-IPv4-IPv6-dualstack-backends.md#ring-hash):
```cpp
if (in_transient_failure && endpoint_entered_transient_failure) {
``` 
During a [discussion](https://github.com/grpc/grpc-go/pull/8047#discussion_r1952051077) it was found that `endpoint_entered_transient_failure` condition can cause the ring hash to remain in TF in certain situations where the aggregated state is TF, but no endpoint actually enters TF:
* Scenario 1: There are four endpoints in the following states: TF, TF, READY, and IDLE. If the READY endpoint fails, it transitions to IDLE, resulting in the new states: TF, TF, IDLE, IDLE.
* Scenario 2: There are four endpoints in the following states: TF, TF, CONNECTING, and IDLE. If the CONNECTING endpoint is removed, the new states become: TF, TF, IDLE.

A discussion was started with other language maintainers to discuss the optimal fix. In Go, the `endpoint_entered_transient_failure` check was removed and new a endpoint is tried every time ringhash finds no connecting endpoints. This maintains the  behaviour before dualstack changes. Depending on the discussion with other maintainers, the ringhash implementation may need to be updated.


Hints from issue comments:
@arjan-bal: The gRFC has been updated: https://github.com/grpc/proposal/pull/475

Solution patch:
diff --git a/internal/xds/bootstrap/bootstrap.go b/internal/xds/bootstrap/bootstrap.go
index 120374d2..69b7ee80 100644
--- a/internal/xds/bootstrap/bootstrap.go
+++ b/internal/xds/bootstrap/bootstrap.go
@@ -22,11 +22,9 @@ package bootstrap
 
 import (
 	"bytes"
-	"context"
 	"encoding/json"
 	"fmt"
 	"maps"
-	"net"
 	"net/url"
 	"os"
 	"slices"
@@ -281,13 +279,6 @@ func (sc *ServerConfig) MarshalJSON() ([]byte, error) {
 	return json.Marshal(server)
 }
 
-// dialer captures the Dialer method specified via the credentials bundle.
-// Deprecated: use extradDialOptions. Will take precedence over this.
-type dialer interface {
-	// Dialer specifies how to dial the xDS server.
-	Dialer(context.Context, string) (net.Conn, error)
-}
-
 // extraDialOptions captures custom dial options specified via
 // credentials.Bundle.
 type extraDialOptions interface {
@@ -319,8 +310,6 @@ func (sc *ServerConfig) UnmarshalJSON(data []byte) error {
 		sc.credsDialOption = grpc.WithCredentialsBundle(bundle)
 		if d, ok := bundle.(extraDialOptions); ok {
 			sc.extraDialOptions = d.DialOptions()
-		} else if d, ok := bundle.(dialer); ok {
-			sc.extraDialOptions = []grpc.DialOption{grpc.WithContextDialer(d.Dialer)}
 		}
 		sc.cleanups = append(sc.cleanups, cancel)
 		break
diff --git a/xds/internal/balancer/ringhash/ringhash.go b/xds/internal/balancer/ringhash/ringhash.go
index 96fddac1..b1de5db7 100644
--- a/xds/internal/balancer/ringhash/ringhash.go
+++ b/xds/internal/balancer/ringhash/ringhash.go
@@ -231,17 +231,6 @@ func (b *ringhashBalancer) updatePickerLocked() {
 		// TF. Since there must be at least one endpoint attempting to connect,
 		// we need to trigger one.
 		//
-		// TODO: https://github.com/grpc/grpc-go/issues/8085 - Restrict the
-		// condition under which an endpoint is connected. The pseudocode
-		// mentioned in A61 doesn't handle the following edge cases where the
-		// aggregated state is TF, but no endpoint actually enters TF:
-		// 1. There are four endpoints in the following states: TF, TF, READY,
-		//    and IDLE. If the READY endpoint fails, it transitions to IDLE,
-		//    resulting in the new states: TF, TF, IDLE, IDLE.
-		// 2. There are four endpoints in the following states: TF, TF,
-		//    CONNECTING, and IDLE. If the CONNECTING endpoint is removed, the
-		//    new states become: TF, TF, IDLE.
-
 		// After calling `ExitIdle` on a child balancer, the child will send a
 		// picker update asynchronously. A race condition may occur if another
 		// picker update from endpointsharding arrives before the child's



Test patch:
diff --git a/clientconn_test.go b/clientconn_test.go
index 0a2ca3bc..f1bddde0 100644
--- a/clientconn_test.go
+++ b/clientconn_test.go
@@ -1041,7 +1041,7 @@ func (s) TestUpdateAddresses_NoopIfCalledWithSameAddresses(t *testing.T) {
 	rb := manual.NewBuilderWithScheme("whatever")
 	rb.InitialState(resolver.State{Addresses: addrsList})
 
-	client, err := Dial("whatever:///this-gets-overwritten",
+	client, err := NewClient("whatever:///this-gets-overwritten",
 		WithTransportCredentials(insecure.NewCredentials()),
 		WithResolvers(rb),
 		WithConnectParams(ConnectParams{
diff --git a/security/advancedtls/advancedtls_integration_test.go b/security/advancedtls/advancedtls_integration_test.go
index 16c0f278..e1e70140 100644
--- a/security/advancedtls/advancedtls_integration_test.go
+++ b/security/advancedtls/advancedtls_integration_test.go
@@ -86,9 +86,7 @@ func (greeterServer) SayHello(_ context.Context, in *pb.HelloRequest) (*pb.Hello
 
 // TODO(ZhenLian): remove shouldFail to the function signature to provider
 // tests.
-func callAndVerify(msg string, client pb.GreeterClient, shouldFail bool) error {
-	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
-	defer cancel()
+func callAndVerify(ctx context.Context, msg string, client pb.GreeterClient, shouldFail bool) error {
 	_, err := client.SayHello(ctx, &pb.HelloRequest{Name: msg})
 	if want, got := shouldFail == true, err != nil; got != want {
 		return fmt.Errorf("want and got mismatch,  want shouldFail=%v, got fail=%v, rpc error: %v", want, got, err)
@@ -98,24 +96,24 @@ func callAndVerify(msg string, client pb.GreeterClient, shouldFail bool) error {
 
 // TODO(ZhenLian): remove shouldFail and add ...DialOption to the function
 // signature to provider cleaner tests.
-func callAndVerifyWithClientConn(connCtx context.Context, address string, msg string, creds credentials.TransportCredentials, shouldFail bool) (*grpc.ClientConn, pb.GreeterClient, error) {
+func callAndVerifyWithClientConn(ctx context.Context, address string, msg string, creds credentials.TransportCredentials, shouldFail bool) (*grpc.ClientConn, pb.GreeterClient, error) {
 	var conn *grpc.ClientConn
 	var err error
 	// If we want the test to fail, we establish a non-blocking connection to
 	// avoid it hangs and killed by the context.
 	if shouldFail {
-		conn, err = grpc.DialContext(connCtx, address, grpc.WithTransportCredentials(creds))
+		conn, err = grpc.NewClient(address, grpc.WithTransportCredentials(creds))
 		if err != nil {
 			return nil, nil, fmt.Errorf("client failed to connect to %s. Error: %v", address, err)
 		}
 	} else {
-		conn, err = grpc.DialContext(connCtx, address, grpc.WithTransportCredentials(creds), grpc.WithBlock())
+		conn, err = grpc.NewClient(address, grpc.WithTransportCredentials(creds), grpc.WithBlock())
 		if err != nil {
 			return nil, nil, fmt.Errorf("client failed to connect to %s. Error: %v", address, err)
 		}
 	}
 	greetClient := pb.NewGreeterClient(conn)
-	err = callAndVerify(msg, greetClient, shouldFail)
+	err = callAndVerify(ctx, msg, greetClient, shouldFail)
 	if err != nil {
 		return nil, nil, err
 	}
@@ -392,7 +390,7 @@ func (s) TestEnd2End(t *testing.T) {
 			stage.increase()
 			// ------------------------Scenario 2------------------------------------
 			// stage = 1, previous connection should still succeed
-			err = callAndVerify("rpc call 2", greetClient, false)
+			err = callAndVerify(ctx, "rpc call 2", greetClient, false)
 			if err != nil {
 				t.Fatal(err)
 			}
@@ -684,7 +682,7 @@ func (s) TestPEMFileProviderEnd2End(t *testing.T) {
 			test.certUpdateFunc()
 			time.Sleep(sleepInterval)
 			// The already-established connection should not be affected.
-			err = callAndVerify("rpc call 2", greetClient, false)
+			err = callAndVerify(ctx, "rpc call 2", greetClient, false)
 			if err != nil {
 				t.Fatal(err)
 			}
diff --git a/server_ext_test.go b/server_ext_test.go
index e904ec46..f7bd45d2 100644
--- a/server_ext_test.go
+++ b/server_ext_test.go
@@ -111,7 +111,7 @@ func (s) TestServer_MaxHandlers(t *testing.T) {
 func (s) TestStreamWorkers_RPCsAndStop(t *testing.T) {
 	ss := stubserver.StartTestService(t, nil, grpc.NumStreamWorkers(uint32(runtime.NumCPU())))
 	// This deferred stop takes care of stopping the server when one of the
-	// below grpc.Dials fail, and the test exits early.
+	// below grpc.NewClient fail, and the test exits early.
 	defer ss.Stop()
 
 	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
diff --git a/test/balancer_switching_test.go b/test/balancer_switching_test.go
index 2e46fcdb..9b9b890a 100644
--- a/test/balancer_switching_test.go
+++ b/test/balancer_switching_test.go
@@ -26,7 +26,7 @@ import (
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/balancer"
 	grpclbstate "google.golang.org/grpc/balancer/grpclb/state"
-	pickfirst "google.golang.org/grpc/balancer/pickfirst"
+	"google.golang.org/grpc/balancer/pickfirst"
 	"google.golang.org/grpc/credentials/insecure"
 	"google.golang.org/grpc/internal"
 	"google.golang.org/grpc/internal/balancer/stub"
@@ -47,6 +47,7 @@ const (
 	wantGRPCLBTraceDesc     = `Channel switches to new LB policy "grpclb"`
 	wantRoundRobinTraceDesc = `Channel switches to new LB policy "round_robin"`
 	pickFirstServiceConfig  = `{"loadBalancingConfig": [{"pick_first":{}}]}`
+	grpclbServiceConfig     = `{"loadBalancingConfig": [{"grpclb":{}}]}`
 
 	// This is the number of stub backends set up at the start of each test. The
 	// first backend is used for the "grpclb" policy and the rest are used for
@@ -174,17 +175,18 @@ func (s) TestBalancerSwitch_grpclbToPickFirst(t *testing.T) {
 	addrs := stubBackendsToResolverAddrs(backends)
 	r := manual.NewBuilderWithScheme("whatever")
 	target := fmt.Sprintf("%s:///%s", r.Scheme(), loadBalancedServiceName)
-	cc, err := grpc.Dial(target, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
+	cc, err := grpc.NewClient(target, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
 	if err != nil {
-		t.Fatalf("grpc.Dial() failed: %v", err)
+		t.Fatalf("grpc.NewClient() failed: %v", err)
 	}
 	defer cc.Close()
+	cc.Connect()
 
 	// Push a resolver update with a GRPCLB service config and a single address
 	// pointing to the grpclb server we created above. This will cause the
 	// channel to switch to the "grpclb" balancer, which returns a single
 	// backend address.
-	grpclbConfig := parseServiceConfig(t, r, `{"loadBalancingPolicy": "grpclb"}`)
+	grpclbConfig := parseServiceConfig(t, r, grpclbServiceConfig)
 	state := resolver.State{ServiceConfig: grpclbConfig}
 	r.UpdateState(grpclbstate.Set(state, &grpclbstate.State{BalancerAddresses: []resolver.Address{{Addr: lbServer.Address()}}}))
 	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
@@ -223,15 +225,16 @@ func (s) TestBalancerSwitch_pickFirstToGRPCLB(t *testing.T) {
 	addrs := stubBackendsToResolverAddrs(backends)
 	r := manual.NewBuilderWithScheme("whatever")
 	target := fmt.Sprintf("%s:///%s", r.Scheme(), loadBalancedServiceName)
-	cc, err := grpc.Dial(target, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
+	cc, err := grpc.NewClient(target, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
 	if err != nil {
-		t.Fatalf("grpc.Dial() failed: %v", err)
+		t.Fatalf("grpc.NewClient() failed: %v", err)
 	}
 	defer cc.Close()
 
-	// Push a resolver update containing no grpclb server address. This should
-	// lead to the channel using the default LB policy which is pick_first.
-	r.UpdateState(resolver.State{Addresses: addrs[1:]})
+	// Set an empty initial resolver state. This should lead to the channel
+	// using the default LB policy which is pick_first.
+	r.InitialState(resolver.State{Addresses: addrs[1:]})
+
 	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
 	defer cancel()
 	if err := pfutil.CheckRPCsToBackend(ctx, cc, addrs[1]); err != nil {
@@ -241,7 +244,7 @@ func (s) TestBalancerSwitch_pickFirstToGRPCLB(t *testing.T) {
 	// Push a resolver update with no service config and a single address pointing
 	// to the grpclb server we created above. This will cause the channel to
 	// switch to the "grpclb" balancer, which returns a single backend address.
-	grpclbConfig := parseServiceConfig(t, r, `{"loadBalancingPolicy": "grpclb"}`)
+	grpclbConfig := parseServiceConfig(t, r, grpclbServiceConfig)
 	state := resolver.State{ServiceConfig: grpclbConfig}
 	r.UpdateState(grpclbstate.Set(state, &grpclbstate.State{BalancerAddresses: []resolver.Address{{Addr: lbServer.Address()}}}))
 	client := testgrpc.NewTestServiceClient(cc)
@@ -276,12 +279,12 @@ func (s) TestBalancerSwitch_RoundRobinToGRPCLB(t *testing.T) {
 	addrs := stubBackendsToResolverAddrs(backends)
 	r := manual.NewBuilderWithScheme("whatever")
 	target := fmt.Sprintf("%s:///%s", r.Scheme(), loadBalancedServiceName)
-	cc, err := grpc.Dial(target, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
+	cc, err := grpc.NewClient(target, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
 	if err != nil {
-		t.Fatalf("grpc.Dial() failed: %v", err)
+		t.Fatalf("grpc.NewClient() failed: %v", err)
 	}
 	defer cc.Close()
-
+	cc.Connect()
 	// Note the use of the deprecated `loadBalancingPolicy` field here instead
 	// of the now recommended `loadBalancingConfig` field. The logic in the
 	// ClientConn which decides which balancer to switch to looks at the
@@ -292,7 +295,7 @@ func (s) TestBalancerSwitch_RoundRobinToGRPCLB(t *testing.T) {
 	// If we use the `loadBalancingPolicy` field, the switch to "grpclb" later on
 	// in the test will not happen as the ClientConn will continue to use the LB
 	// policy received in the first update.
-	scpr := parseServiceConfig(t, r, `{"loadBalancingPolicy": "round_robin"}`)
+	scpr := parseServiceConfig(t, r, rrServiceConfig)
 
 	// Push a resolver update with the service config specifying "round_robin".
 	r.UpdateState(resolver.State{Addresses: addrs[1:], ServiceConfig: scpr})
@@ -307,7 +310,7 @@ func (s) TestBalancerSwitch_RoundRobinToGRPCLB(t *testing.T) {
 	// pointing to the grpclb server we created above. This will cause the
 	// channel to switch to the "grpclb" balancer, which returns a single
 	// backend address.
-	grpclbConfig := parseServiceConfig(t, r, `{"loadBalancingPolicy": "grpclb"}`)
+	grpclbConfig := parseServiceConfig(t, r, grpclbServiceConfig)
 	state := resolver.State{ServiceConfig: grpclbConfig}
 	r.UpdateState(grpclbstate.Set(state, &grpclbstate.State{BalancerAddresses: []resolver.Address{{Addr: lbServer.Address()}}}))
 	if err := rrutil.CheckRoundRobinRPCs(ctx, client, addrs[:1]); err != nil {
@@ -336,11 +339,12 @@ func (s) TestBalancerSwitch_grpclbNotRegistered(t *testing.T) {
 	addrs := stubBackendsToResolverAddrs(backends)
 
 	r := manual.NewBuilderWithScheme("whatever")
-	cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
+	cc, err := grpc.NewClient(r.Scheme()+":///test.server", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
 	if err != nil {
-		t.Fatalf("grpc.Dial() failed: %v", err)
+		t.Fatalf("grpc.NewClient() failed: %v", err)
 	}
 	defer cc.Close()
+	cc.Connect()
 
 	// Push a resolver update which contains a bunch of stub server backends and a
 	// grpclb server address. The latter should get the ClientConn to try and
@@ -355,7 +359,7 @@ func (s) TestBalancerSwitch_grpclbNotRegistered(t *testing.T) {
 	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
 	defer cancel()
 	if err := pfutil.CheckRPCsToBackend(ctx, cc, addrs[0]); err != nil {
-		t.Fatal(err)
+		t.Fatalf("Pick_first backend readiness check failed: %v", err)
 	}
 
 	// Push a resolver update with the same addresses, but with a service config
@@ -367,7 +371,7 @@ func (s) TestBalancerSwitch_grpclbNotRegistered(t *testing.T) {
 	})
 	client := testgrpc.NewTestServiceClient(cc)
 	if err := rrutil.CheckRoundRobinRPCs(ctx, client, addrs); err != nil {
-		t.Fatal(err)
+		t.Fatalf("Round robin RPCs failed: %v", err)
 	}
 }
 
@@ -394,10 +398,11 @@ func (s) TestBalancerSwitch_OldBalancerCallsShutdownInClose(t *testing.T) {
 	})
 
 	r := manual.NewBuilderWithScheme("whatever")
-	cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
+	cc, err := grpc.NewClient(r.Scheme()+":///test.server", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
 	if err != nil {
-		t.Fatalf("grpc.Dial() failed: %v", err)
+		t.Fatalf("grpc.NewClient() failed: %v", err)
 	}
+	cc.Connect()
 	defer cc.Close()
 
 	// Push a resolver update specifying our stub balancer as the LB policy.
@@ -453,12 +458,12 @@ func (s) TestBalancerSwitch_Graceful(t *testing.T) {
 	addrs := stubBackendsToResolverAddrs(backends)
 
 	r := manual.NewBuilderWithScheme("whatever")
-	cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
+	cc, err := grpc.NewClient(r.Scheme()+":///test.server", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
 	if err != nil {
-		t.Fatalf("grpc.Dial() failed: %v", err)
+		t.Fatalf("grpc.NewClient() failed: %v", err)
 	}
 	defer cc.Close()
-
+	cc.Connect()
 	// Push a resolver update with the service config specifying "round_robin".
 	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
 	defer cancel()
@@ -513,7 +518,7 @@ func (s) TestBalancerSwitch_Graceful(t *testing.T) {
 	case <-ccUpdateCh:
 	}
 	if err := rrutil.CheckRoundRobinRPCs(ctx, client, addrs[1:]); err != nil {
-		t.Fatal(err)
+		t.Fatalf("RPCs routed to old balancer failed: %v", err)
 	}
 
 	// Ask our stub balancer to forward the earlier received ccUpdate to the
@@ -521,6 +526,6 @@ func (s) TestBalancerSwitch_Graceful(t *testing.T) {
 	// being reported to the channel. RPCs should start using the new balancer.
 	close(waitToProceed)
 	if err := pfutil.CheckRPCsToBackend(ctx, cc, addrs[0]); err != nil {
-		t.Fatal(err)
+		t.Fatalf("RPCs routed to new balancer failed: %v", err)
 	}
 }
diff --git a/test/balancer_test.go b/test/balancer_test.go
index 9cb41e5a..9fe9a2c5 100644
--- a/test/balancer_test.go
+++ b/test/balancer_test.go
@@ -573,7 +573,7 @@ func (s) TestServersSwap(t *testing.T) {
 	// Initialize client
 	r := manual.NewBuilderWithScheme("whatever")
 	r.InitialState(resolver.State{Addresses: []resolver.Address{{Addr: addr1}}})
-	cc, err := grpc.DialContext(ctx, r.Scheme()+":///", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
+	cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
 	if err != nil {
 		t.Fatalf("Error creating client: %v", err)
 	}
@@ -622,11 +622,12 @@ func (s) TestWaitForReady(t *testing.T) {
 	// Initialize client
 	r := manual.NewBuilderWithScheme("whatever")
 
-	cc, err := grpc.DialContext(ctx, r.Scheme()+":///", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
+	cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
 	if err != nil {
 		t.Fatalf("Error creating client: %v", err)
 	}
 	defer cc.Close()
+	cc.Connect()
 	client := testgrpc.NewTestServiceClient(cc)
 
 	// Report an error so non-WFR RPCs will give up early.
diff --git a/test/clientconn_state_transition_test.go b/test/clientconn_state_transition_test.go
index 547b5ffb..87e47150 100644
--- a/test/clientconn_state_transition_test.go
+++ b/test/clientconn_state_transition_test.go
@@ -164,7 +164,7 @@ func testStateTransitionSingleAddress(t *testing.T, want []connectivity.State, s
 		connMu.Unlock()
 	}()
 
-	client, err := grpc.Dial("",
+	client, err := grpc.NewClient("passthrough:///",
 		grpc.WithTransportCredentials(insecure.NewCredentials()),
 		grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"loadBalancingConfig": [{"%s":{}}]}`, stateRecordingBalancerName)),
 		grpc.WithDialer(pl.Dialer()),
@@ -181,6 +181,9 @@ func testStateTransitionSingleAddress(t *testing.T, want []connectivity.State, s
 	defer cancel()
 	go testutils.StayConnected(ctx, client)
 
+	// Wait for the test balancer to be built before capturing it's state
+	// notification channel.
+	testutils.AwaitNotState(ctx, t, client, connectivity.Idle)
 	stateNotifications := testBalancerBuilder.nextStateNotifier()
 	for i := 0; i < len(want); i++ {
 		select {
diff --git a/test/end2end_test.go b/test/end2end_test.go
index 548bd68b..a09f43a1 100644
--- a/test/end2end_test.go
+++ b/test/end2end_test.go
@@ -840,9 +840,9 @@ func (te *test) clientConnWithConnControl() (*grpc.ClientConn, *dialerWrapper) {
 	// overwrite the dialer before
 	opts = append(opts, grpc.WithDialer(dw.dialer))
 	var err error
-	te.cc, err = grpc.Dial(scheme+te.srvAddr, opts...)
+	te.cc, err = grpc.NewClient(scheme+te.srvAddr, opts...)
 	if err != nil {
-		te.t.Fatalf("Dial(%q) = %v", scheme+te.srvAddr, err)
+		te.t.Fatalf("NewClient(%q) = %v", scheme+te.srvAddr, err)
 	}
 	return te.cc, dw
 }
@@ -3004,9 +3004,9 @@ func (s) TestTransparentRetry(t *testing.T) {
 		},
 	}
 	server.start(t, lis)
-	cc, err := grpc.Dial(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
+	cc, err := grpc.NewClient(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
 	if err != nil {
-		t.Fatalf("failed to dial due to err: %v", err)
+		t.Fatalf("failed to create a client for the server: %v", err)
 	}
 	defer cc.Close()
 
@@ -4252,9 +4252,9 @@ func (s) TestFailfastRPCFailOnFatalHandshakeError(t *testing.T) {
 	}
 	defer lis.Close()
 
-	cc, err := grpc.Dial("passthrough:///"+lis.Addr().String(), grpc.WithTransportCredentials(&clientFailCreds{}))
+	cc, err := grpc.NewClient("passthrough:///"+lis.Addr().String(), grpc.WithTransportCredentials(&clientFailCreds{}))
 	if err != nil {
-		t.Fatalf("grpc.Dial(_) = %v", err)
+		t.Fatalf("grpc.NewClient(_) = %v", err)
 	}
 	defer cc.Close()
 
@@ -4298,9 +4298,9 @@ func (s) TestFlowControlLogicalRace(t *testing.T) {
 
 	go s.Serve(lis)
 
-	cc, err := grpc.Dial(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
+	cc, err := grpc.NewClient(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
 	if err != nil {
-		t.Fatalf("grpc.Dial(%q) = %v", lis.Addr().String(), err)
+		t.Fatalf("grpc.NewClient(%q) = %v", lis.Addr().String(), err)
 	}
 	defer cc.Close()
 	cl := testgrpc.NewTestServiceClient(cc)
@@ -5070,9 +5070,9 @@ func (s) TestServeExitsWhenListenerClosed(t *testing.T) {
 		close(done)
 	}()
 
-	cc, err := grpc.Dial(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
+	cc, err := grpc.NewClient(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
 	if err != nil {
-		t.Fatalf("Failed to dial server: %v", err)
+		t.Fatalf("Failed to create a client for server: %v", err)
 	}
 	defer cc.Close()
 	c := testgrpc.NewTestServiceClient(cc)
@@ -5244,11 +5244,9 @@ func (s) TestDisabledIOBuffers(t *testing.T) {
 		s.Serve(lis)
 	}()
 	defer s.Stop()
-	dctx, dcancel := context.WithTimeout(context.Background(), defaultTestTimeout)
-	defer dcancel()
-	cc, err := grpc.DialContext(dctx, lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithWriteBufferSize(0), grpc.WithReadBufferSize(0))
+	cc, err := grpc.NewClient(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithWriteBufferSize(0), grpc.WithReadBufferSize(0))
 	if err != nil {
-		t.Fatalf("Failed to dial server")
+		t.Fatalf("Failed to create a client for server")
 	}
 	defer cc.Close()
 	c := testgrpc.NewTestServiceClient(cc)
@@ -5448,7 +5446,7 @@ func (s) TestNetPipeConn(t *testing.T) {
 	go s.Serve(pl)
 	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
 	defer cancel()
-	cc, err := grpc.DialContext(ctx, "", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDialer(pl.Dialer()))
+	cc, err := grpc.NewClient("passthrough:///", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDialer(pl.Dialer()))
 	if err != nil {
 		t.Fatalf("Error creating client: %v", err)
 	}
@@ -6426,9 +6424,9 @@ func (s) TestRPCBlockingOnPickerStatsCall(t *testing.T) {
 		ServiceConfig: sc,
 	})
 
-	cc, err := grpc.Dial(mr.Scheme()+":///", grpc.WithResolvers(mr), grpc.WithStatsHandler(sh), grpc.WithTransportCredentials(insecure.NewCredentials()))
+	cc, err := grpc.NewClient(mr.Scheme()+":///", grpc.WithResolvers(mr), grpc.WithStatsHandler(sh), grpc.WithTransportCredentials(insecure.NewCredentials()))
 	if err != nil {
-		t.Fatalf("grpc.Dial() failed: %v", err)
+		t.Fatalf("grpc.NewClient() failed: %v", err)
 	}
 	defer cc.Close()
 	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
diff --git a/test/healthcheck_test.go b/test/healthcheck_test.go
index 850b8e9a..0f7ec54a 100644
--- a/test/healthcheck_test.go
+++ b/test/healthcheck_test.go
@@ -182,10 +182,11 @@ func setupClient(t *testing.T, c *clientConfig) (*grpc.ClientConn, *manual.Resol
 		opts = append(opts, c.extraDialOption...)
 	}
 
-	cc, err := grpc.Dial(r.Scheme()+":///test.server", opts...)
+	cc, err := grpc.NewClient(r.Scheme()+":///test.server", opts...)
 	if err != nil {
-		t.Fatalf("grpc.Dial() failed: %v", err)
+		t.Fatalf("grpc.NewClient() failed: %v", err)
 	}
+	cc.Connect()
 	t.Cleanup(func() { cc.Close() })
 	return cc, r
 }
diff --git a/test/local_creds_test.go b/test/local_creds_test.go
index 9e64f23e..13dd4ae5 100644
--- a/test/local_creds_test.go
+++ b/test/local_creds_test.go
@@ -85,7 +85,7 @@ func testLocalCredsE2ESucceed(t *testing.T, network, address string) error {
 
 	switch network {
 	case "unix":
-		cc, err = grpc.Dial(lisAddr, grpc.WithTransportCredentials(local.NewCredentials()), grpc.WithContextDialer(
+		cc, err = grpc.NewClient("passthrough:///"+lisAddr, grpc.WithTransportCredentials(local.NewCredentials()), grpc.WithContextDialer(
 			func(_ context.Context, addr string) (net.Conn, error) {
 				return net.Dial("unix", addr)
 			}))
@@ -95,7 +95,7 @@ func testLocalCredsE2ESucceed(t *testing.T, network, address string) error {
 		return fmt.Errorf("unsupported network %q", network)
 	}
 	if err != nil {
-		return fmt.Errorf("Failed to dial server: %v, %v", err, lisAddr)
+		return fmt.Errorf("Failed to create a client for server: %v, %v", err, lisAddr)
 	}
 	defer cc.Close()
 
diff --git a/test/resolver_update_test.go b/test/resolver_update_test.go
index 619979b9..b8a2d443 100644
--- a/test/resolver_update_test.go
+++ b/test/resolver_update_test.go
@@ -112,10 +112,11 @@ func (s) TestResolverUpdateDuringBuild_ServiceConfigInvalidTypeError(t *testing.
 func (s) TestResolverUpdate_InvalidServiceConfigAsFirstUpdate(t *testing.T) {
 	r := manual.NewBuilderWithScheme("whatever")
 
-	cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
+	cc, err := grpc.NewClient(r.Scheme()+":///test.server", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
 	if err != nil {
-		t.Fatalf("Dial(_, _) = _, %v; want _, nil", err)
+		t.Fatalf("NewClient(_, _) = _, %v; want _, nil", err)
 	}
+	cc.Connect()
 	defer cc.Close()
 
 	scpr := r.CC.ParseServiceConfig("bad json service config")
@@ -195,12 +196,12 @@ func (s) TestResolverUpdate_InvalidServiceConfigAfterGoodUpdate(t *testing.T) {
 
 	r := manual.NewBuilderWithScheme("whatever")
 
-	cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
+	cc, err := grpc.NewClient(r.Scheme()+":///test.server", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
 	if err != nil {
-		t.Fatalf("Dial(_, _) = _, %v; want _, nil", err)
+		t.Fatalf("NewClient(_, _) = _, %v; want _, nil", err)
 	}
 	defer cc.Close()
-
+	cc.Connect()
 	// Push a resolver update and verify that our balancer receives the update.
 	addrs := []resolver.Address{{Addr: backend.Address}}
 	const lbCfg = "wrapping balancer LB policy config"
diff --git a/test/xds/xds_client_affinity_test.go b/test/xds/xds_client_affinity_test.go
index e7db416a..3a4b33e9 100644
--- a/test/xds/xds_client_affinity_test.go
+++ b/test/xds/xds_client_affinity_test.go
@@ -117,7 +117,7 @@ func (s) TestClientSideAffinitySanityCheck(t *testing.T) {
 	// Create a ClientConn and make a successful RPC.
 	cc, err := grpc.NewClient(fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(xdsResolver))
 	if err != nil {
-		t.Fatalf("failed to dial local test server: %v", err)
+		t.Fatalf("failed to create a client for server: %v", err)
 	}
 	defer cc.Close()
 
diff --git a/test/xds/xds_client_certificate_providers_test.go b/test/xds/xds_client_certificate_providers_test.go
index 283f81a4..0c562f4e 100644
--- a/test/xds/xds_client_certificate_providers_test.go
+++ b/test/xds/xds_client_certificate_providers_test.go
@@ -167,11 +167,12 @@ func (s) TestClientSideXDS_WithNoCertificateProvidersInBootstrap_Failure(t *test
 	}
 
 	// Create a ClientConn and ensure that it moves to TRANSIENT_FAILURE.
-	cc, err := grpc.Dial(fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(creds), grpc.WithResolvers(resolverBuilder))
+	cc, err := grpc.NewClient(fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(creds), grpc.WithResolvers(resolverBuilder))
 	if err != nil {
-		t.Fatalf("failed to dial local test server: %v", err)
+		t.Fatalf("failed to create a client for server: %v", err)
 	}
 	defer cc.Close()
+	cc.Connect()
 	testutils.AwaitState(ctx, t, cc, connectivity.TransientFailure)
 
 	// Make an RPC and ensure that expected error is returned.
diff --git a/test/xds/xds_client_custom_dialer_test.go b/test/xds/xds_client_custom_dialer_test.go
deleted file mode 100644
index f15543d6..00000000
--- a/test/xds/xds_client_custom_dialer_test.go
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- *
- * Copyright 2024 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package xds_test
-
-import (
-	"context"
-	"encoding/json"
-	"fmt"
-	"net"
-	"testing"
-
-	"github.com/google/uuid"
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/credentials"
-	"google.golang.org/grpc/credentials/insecure"
-	"google.golang.org/grpc/internal"
-	"google.golang.org/grpc/internal/stubserver"
-	"google.golang.org/grpc/internal/testutils"
-	"google.golang.org/grpc/internal/testutils/xds/e2e"
-	internalbootstrap "google.golang.org/grpc/internal/xds/bootstrap"
-	"google.golang.org/grpc/resolver"
-	"google.golang.org/grpc/xds/bootstrap"
-
-	testgrpc "google.golang.org/grpc/interop/grpc_testing"
-	testpb "google.golang.org/grpc/interop/grpc_testing"
-)
-
-const testDialerCredsBuilderName = "test_dialer_creds"
-
-// testDialerCredsBuilder implements the `Credentials` interface defined in
-// package `xds/bootstrap` and encapsulates an insecure credential with a
-// custom Dialer that specifies how to dial the xDS server.
-type testDialerCredsBuilder struct {
-	dialerCalled chan struct{}
-}
-
-func (t *testDialerCredsBuilder) Build(config json.RawMessage) (credentials.Bundle, func(), error) {
-	cfg := &struct {
-		MgmtServerAddress string `json:"mgmt_server_address"`
-	}{}
-	if err := json.Unmarshal(config, &cfg); err != nil {
-		return nil, func() {}, fmt.Errorf("failed to unmarshal config: %v", err)
-	}
-	return &testDialerCredsBundle{insecure.NewBundle(), t.dialerCalled, cfg.MgmtServerAddress}, func() {}, nil
-}
-
-func (t *testDialerCredsBuilder) Name() string {
-	return testDialerCredsBuilderName
-}
-
-// testDialerCredsBundle implements the `Bundle` interface defined in package
-// `credentials` and encapsulates an insecure credential with a custom Dialer
-// that specifies how to dial the xDS server.
-type testDialerCredsBundle struct {
-	credentials.Bundle
-	dialerCalled      chan struct{}
-	mgmtServerAddress string
-}
-
-// Dialer specifies how to dial the xDS management server.
-func (t *testDialerCredsBundle) Dialer(context.Context, string) (net.Conn, error) {
-	close(t.dialerCalled)
-	// Create a pass-through connection (no-op) to the xDS management server.
-	return net.Dial("tcp", t.mgmtServerAddress)
-}
-
-func (s) TestClientCustomDialerFromCredentialsBundle(t *testing.T) {
-	// Create and register the credentials bundle builder.
-	credsBuilder := &testDialerCredsBuilder{dialerCalled: make(chan struct{})}
-	bootstrap.RegisterCredentials(credsBuilder)
-
-	// Start an xDS management server.
-	mgmtServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{})
-
-	// Create bootstrap configuration pointing to the above management server.
-	nodeID := uuid.New().String()
-	bc, err := internalbootstrap.NewContentsForTesting(internalbootstrap.ConfigOptionsForTesting{
-		Servers: []byte(fmt.Sprintf(`[{
-			"server_uri": %q,
-			"channel_creds": [{
-				"type": %q,
-				"config": {"mgmt_server_address": %q}
-			}]
-		}]`, mgmtServer.Address, testDialerCredsBuilderName, mgmtServer.Address)),
-		Node: []byte(fmt.Sprintf(`{"id": "%s"}`, nodeID)),
-	})
-	if err != nil {
-		t.Fatalf("Failed to create bootstrap configuration: %v", err)
-	}
-
-	// Create an xDS resolver with the above bootstrap configuration.
-	if internal.NewXDSResolverWithConfigForTesting == nil {
-		t.Fatalf("internal.NewXDSResolverWithConfigForTesting is nil")
-	}
-	resolverBuilder, err := internal.NewXDSResolverWithConfigForTesting.(func([]byte) (resolver.Builder, error))(bc)
-	if err != nil {
-		t.Fatalf("Failed to create xDS resolver for testing: %v", err)
-	}
-
-	// Spin up a test backend.
-	server := stubserver.StartTestService(t, nil)
-	defer server.Stop()
-
-	// Configure client side xDS resources on the management server.
-	const serviceName = "my-service-client-side-xds"
-	resources := e2e.DefaultClientResources(e2e.ResourceParams{
-		DialTarget: serviceName,
-		NodeID:     nodeID,
-		Host:       "localhost",
-		Port:       testutils.ParsePort(t, server.Address),
-		SecLevel:   e2e.SecurityLevelNone,
-	})
-	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
-	defer cancel()
-	if err := mgmtServer.Update(ctx, resources); err != nil {
-		t.Fatal(err)
-	}
-
-	// Create a ClientConn and make a successful RPC. The insecure transport credentials passed into
-	// the gRPC.NewClient is the credentials for the data plane communication with the test backend.
-	cc, err := grpc.NewClient(fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(resolverBuilder))
-	if err != nil {
-		t.Fatalf("failed to dial local test server: %v", err)
-	}
-	defer cc.Close()
-
-	client := testgrpc.NewTestServiceClient(cc)
-	if _, err := client.EmptyCall(ctx, &testpb.Empty{}); err != nil {
-		t.Fatalf("EmptyCall() failed: %v", err)
-	}
-
-	// Verify that the custom dialer was called.
-	select {
-	case <-ctx.Done():
-		t.Fatalf("Timeout when waiting for custom dialer to be called")
-	case <-credsBuilder.dialerCalled:
-	}
-}
diff --git a/test/xds/xds_client_federation_test.go b/test/xds/xds_client_federation_test.go
index 0ebb2ec8..c91a0588 100644
--- a/test/xds/xds_client_federation_test.go
+++ b/test/xds/xds_client_federation_test.go
@@ -290,11 +290,17 @@ func (s) TestFederation_UnknownAuthorityInDialTarget(t *testing.T) {
 	t.Log("Successfully performed an EmptyCall RPC")
 
 	target = fmt.Sprintf("xds://unknown-authority/%s", serviceName)
-	t.Logf("Dialing target %q with unknown authority which is expected to fail", target)
+	t.Logf("Creating a channel with unknown authority %q, expecting failure", target)
 	wantErr := fmt.Sprintf("authority \"unknown-authority\" specified in dial target %q is not found in the bootstrap file", target)
-	_, err = grpc.Dial(target, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(xdsResolver))
+	cc, err = grpc.NewClient(target, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(xdsResolver))
+	if err != nil {
+		t.Fatalf("Unexpected error while creating ClientConn: %v", err)
+	}
+	defer cc.Close()
+	client = testgrpc.NewTestServiceClient(cc)
+	_, err = client.EmptyCall(ctx, &testpb.Empty{})
 	if err == nil || !strings.Contains(err.Error(), wantErr) {
-		t.Fatalf("grpc.Dial(%q) returned %v, want: %s", target, err, wantErr)
+		t.Fatalf("EmptyCall(_, _) = _, %v; want _, %q", err, wantErr)
 	}
 }
 
diff --git a/test/xds/xds_server_integration_test.go b/test/xds/xds_server_integration_test.go
index e97f727b..a63a7524 100644
--- a/test/xds/xds_server_integration_test.go
+++ b/test/xds/xds_server_integration_test.go
@@ -212,9 +212,9 @@ func (s) TestServerSideXDS_Fallback(t *testing.T) {
 	}
 
 	// Create a ClientConn with the xds scheme and make a successful RPC.
-	cc, err := grpc.DialContext(ctx, fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(creds), grpc.WithResolvers(xdsResolver))
+	cc, err := grpc.NewClient(fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(creds), grpc.WithResolvers(xdsResolver))
 	if err != nil {
-		t.Fatalf("failed to dial local test server: %v", err)
+		t.Fatalf("failed to create a client for server: %v", err)
 	}
 	defer cc.Close()
 
@@ -295,9 +295,9 @@ func (s) TestServerSideXDS_FileWatcherCerts(t *testing.T) {
 			}
 
 			// Create a ClientConn with the xds scheme and make an RPC.
-			cc, err := grpc.DialContext(ctx, fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(creds), grpc.WithResolvers(xdsResolver))
+			cc, err := grpc.NewClient(fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(creds), grpc.WithResolvers(xdsResolver))
 			if err != nil {
-				t.Fatalf("failed to dial local test server: %v", err)
+				t.Fatalf("failed to create a client for server: %v", err)
 			}
 			defer cc.Close()
 
@@ -375,9 +375,9 @@ func (s) TestServerSideXDS_SecurityConfigChange(t *testing.T) {
 	}
 
 	// Create a ClientConn with the xds scheme and make a successful RPC.
-	xdsCC, err := grpc.DialContext(ctx, fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(xdsCreds), grpc.WithResolvers(xdsResolver))
+	xdsCC, err := grpc.NewClient(fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(xdsCreds), grpc.WithResolvers(xdsResolver))
 	if err != nil {
-		t.Fatalf("failed to dial local test server: %v", err)
+		t.Fatalf("failed to create a client for server: %v", err)
 	}
 	defer xdsCC.Close()
 
@@ -389,9 +389,9 @@ func (s) TestServerSideXDS_SecurityConfigChange(t *testing.T) {
 	// Create a ClientConn with TLS creds. This should fail since the server is
 	// using fallback credentials which in this case in insecure creds.
 	tlsCreds := testutils.CreateClientTLSCredentials(t)
-	tlsCC, err := grpc.DialContext(ctx, lis.Addr().String(), grpc.WithTransportCredentials(tlsCreds))
+	tlsCC, err := grpc.NewClient(lis.Addr().String(), grpc.WithTransportCredentials(tlsCreds))
 	if err != nil {
-		t.Fatalf("failed to dial local test server: %v", err)
+		t.Fatalf("failed to create a client for server: %v", err)
 	}
 	defer tlsCC.Close()
 
diff --git a/xds/googledirectpath/googlec2p_test.go b/xds/googledirectpath/googlec2p_test.go
index 3876efaf..51f3fa4a 100644
--- a/xds/googledirectpath/googlec2p_test.go
+++ b/xds/googledirectpath/googlec2p_test.go
@@ -19,6 +19,7 @@
 package googledirectpath
 
 import (
+	"context"
 	"encoding/json"
 	"strconv"
 	"strings"
@@ -31,10 +32,14 @@ import (
 	"google.golang.org/grpc/internal/envconfig"
 	"google.golang.org/grpc/internal/grpctest"
 	"google.golang.org/grpc/internal/xds/bootstrap"
+	testgrpc "google.golang.org/grpc/interop/grpc_testing"
+	testpb "google.golang.org/grpc/interop/grpc_testing"
 	"google.golang.org/grpc/resolver"
 	"google.golang.org/grpc/xds/internal/xdsclient"
 )
 
+const defaultTestTimeout = 5 * time.Second
+
 type s struct {
 	grpctest.Tester
 }
@@ -329,15 +334,22 @@ func (s) TestBuildXDS(t *testing.T) {
 func (s) TestBuildFailsWhenCalledWithAuthority(t *testing.T) {
 	useCleanUniverseDomain(t)
 	uri := "google-c2p://an-authority/resource"
-	cc, err := grpc.Dial(uri, grpc.WithTransportCredentials(insecure.NewCredentials()))
+	cc, err := grpc.NewClient(uri, grpc.WithTransportCredentials(insecure.NewCredentials()))
+	if err != nil {
+		t.Fatalf("failed to create a client for server: %v", err)
+	}
 	defer func() {
 		if cc != nil {
 			cc.Close()
 		}
 	}()
+	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
+	defer cancel()
+	client := testgrpc.NewTestServiceClient(cc)
+	_, err = client.EmptyCall(ctx, &testpb.Empty{})
 	wantErr := "google-c2p URI scheme does not support authorities"
 	if err == nil || !strings.Contains(err.Error(), wantErr) {
-		t.Fatalf("grpc.Dial(%s) returned error: %v, want: %v", uri, err, wantErr)
+		t.Fatalf("client.EmptyCall(%s) returned error: %v, want: %v", uri, err, wantErr)
 	}
 }