Repository: grpc/grpc-go
File: xds/internal/xdsclient/tests/fallback_test.go (Go)

Code before:
	if err != nil {
		t.Fatalf("Failed to create gRPC client: %v", err)
	}
	defer cc.Close()

	// Make an RPC (without the `wait_for_ready` call option) and expect it to
	// succeed since the fallback management server is up and running.
	client := testgrpc.NewTestServiceClient(cc)
	var peer peer.Peer
	if _, err := client.EmptyCall(ctx, &testpb.Empty{}, grpc.Peer(&peer)); err != nil {
		t.Fatalf("EmptyCall() failed: %v", err)
	}
	if got, want := peer.Addr.String(), backend2.Address; got != want {
		t.Fatalf("Unexpected peer address: got %q, want %q", got, want)
	}

	// Start the primary server. It can take a while before the xDS client
	// notices this, since the ADS stream implementation uses a backoff before
	// retrying the stream.
	primaryLis.Restart()
	if err := waitForRPCsToReachBackend(ctx, client, backend1.Address); err != nil {
		t.Fatal(err)
	}
}

// TestXDSFallback_ThreeServerPromotion verifies fallback and promotion
// behavior across three xDS servers in the following scenarios.
//  1. The primary server returns a partial config, triggering fallback to
//     secondary1.
//  2. Secondary1 also returns a partial config, triggering fallback to
//     secondary2.
//  3. Secondary2 returns a full config, so RPCs succeed to backend3.
//  4. Secondary1 recovers with a full config, promoting RPCs to backend2.
//  5. Primary finally recovers with a full config, promoting RPCs to backend1.
func (s) TestXDSFallback_ThreeServerPromotion(t *testing.T) {
	ctx, cancel := context.WithTimeout(context.Background(), defaultFallbackTestTimeout)
	defer cancel()

	// Create three listener wrappers for three management servers.
	primaryWrappedLis := testutils.NewListenerWrapper(t, nil)
	primaryLis := testutils.NewRestartableListener(primaryWrappedLis)

	secondary1WrappedLis := testutils.NewListenerWrapper(t, nil)
	secondary1Lis := testutils.NewRestartableListener(secondary1WrappedLis)

	secondary2WrappedLis := testutils.NewListenerWrapper(t, nil)
	secondary2Lis := testutils.NewRestartableListener(secondary2WrappedLis)

	// Start the three management servers.
	primaryManagementServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{Listener: primaryLis})
	secondary1ManagementServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{Listener: secondary1Lis})

Review comment (suggestion):
This could be changed to something like :
`The test verifies that when the primary management server is unavailable, the system attempts to connect to the first fallback server, and if that is also down, to the second fallback server. It also ensures that the system switches back to the first fallback server once it becomes available again, and eventually returns to the primary server when it comes back online, closing connections to the fallback servers accordingly.`

Code after:
	if err != nil {
		t.Fatalf("Failed to create gRPC client: %v", err)
	}
	defer cc.Close()

	// Make an RPC (without the `wait_for_ready` call option) and expect it to
	// succeed since the fallback management server is up and running.
	client := testgrpc.NewTestServiceClient(cc)
	var peer peer.Peer
	if _, err := client.EmptyCall(ctx, &testpb.Empty{}, grpc.Peer(&peer)); err != nil {
		t.Fatalf("EmptyCall() failed: %v", err)
	}
	if got, want := peer.Addr.String(), backend2.Address; got != want {
		t.Fatalf("Unexpected peer address: got %q, want %q", got, want)
	}

	// Start the primary server. It can take a while before the xDS client
	// notices this, since the ADS stream implementation uses a backoff before
	// retrying the stream.
	primaryLis.Restart()
	if err := waitForRPCsToReachBackend(ctx, client, backend1.Address); err != nil {
		t.Fatal(err)
	}
}

// TestXDSFallback_ThreeServerPromotion verifies that when the primary
// management server is unavailable, the system attempts to connect to the
// first fallback server, and if that is also down, to the second fallback
// server. It also ensures that the system switches back to the first fallback
// server once it becomes available again, and eventually returns to the
// primary server when it comes back online, closing connections to the
// fallback servers accordingly.
func (s) TestXDSFallback_ThreeServerPromotion(t *testing.T) {
	ctx, cancel := context.WithTimeout(context.Background(), defaultFallbackTestTimeout)
	defer cancel()

	// Create three listener wrappers for three management servers.
	primaryWrappedLis := testutils.NewListenerWrapper(t, nil)
	primaryLis := testutils.NewRestartableListener(primaryWrappedLis)

	secondaryWrappedLis := testutils.NewListenerWrapper(t, nil)
	secondaryLis := testutils.NewRestartableListener(secondaryWrappedLis)

	tertiaryWrappedLis := testutils.NewListenerWrapper(t, nil)
	tertiaryLis := testutils.NewRestartableListener(tertiaryWrappedLis)

	// Start the three management servers.
	primaryManagementServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{Listener: primaryLis})
	secondaryManagementServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{Listener: secondaryLis})
	tertiaryManagementServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{Listener: tertiaryLis})