Repository: grpc/grpc-go
File: test/clientconn_state_transition_test.go (Go)

Code before:
	go rb.UpdateState(resolver.State{})

	// Verify the resulting states.
	for i, want := range wantStates {
		if i == len(sendStates) {
			// Trigger Shutdown to be sent by the channel.  Use a goroutine to
			// ensure the operation does not block.
			cc.Close()
		}
		select {
		case got := <-connCh:
			if got != want {
				t.Errorf("Update %v was %s; want %s", i, got, want)
			} else {
				t.Logf("Update %v was %s as expected", i, got)
			}
		case <-ctx.Done():
			t.Fatalf("Timed out waiting for state update %v: %s", i, want)
		}
	}
}

// TestChannelStateWaitingForFirstResolverUpdate verifies the initial
// state of the channel when a manual name resolver doesn't provide any updates.
func (s) TestChannelStateWaitingForFirstResolverUpdate(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping test in short mode.")
	}

	backend := stubserver.StartTestService(t, nil)
	defer backend.Stop()

	mr := manual.NewBuilderWithScheme("e2e-test")
	defer mr.Close()

	cc, err := grpc.NewClient(mr.Scheme()+":///", grpc.WithResolvers(mr), grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		t.Fatalf("Failed to create new client: %v", err)
	}
	defer cc.Close()

	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
	defer cancel()

	cc.Connect()

	testutils.AwaitState(ctx, t, cc, connectivity.Idle)

	mr.UpdateState(resolver.State{
		Addresses: []resolver.Address{{Addr: backend.Address}},
	})

Review comment (bug):
What is this and why?

I think we have a bug, which this test doesn't actually appear to be testing, but which is described in the issue that asked for this test.  IF there is a bug, we need to always skip the test.

Code after:
	// Send an update from the resolver that will trigger the LB policy's UpdateClientConnState.
	go rb.UpdateState(resolver.State{})

	// Verify the resulting states.
	for i, want := range wantStates {
		if i == len(sendStates) {
			// Trigger Shutdown to be sent by the channel.  Use a goroutine to
			// ensure the operation does not block.
			cc.Close()
		}
		select {
		case got := <-connCh:
			if got != want {
				t.Errorf("Update %v was %s; want %s", i, got, want)
			} else {
				t.Logf("Update %v was %s as expected", i, got)
			}
		case <-ctx.Done():
			t.Fatalf("Timed out waiting for state update %v: %s", i, want)
		}
	}
}

// TestChannelStateWaitingForFirstResolverUpdate verifies the initial
// state of the channel when a manual name resolver doesn't provide any updates.
func (s) TestChannelStateWaitingForFirstResolverUpdate(t *testing.T) {
	t.Skip("The channel remains in IDLE until the LB policy updates the state to CONNECTING. This is a bug and the channel should transition to CONNECTING as soon as Connect() is called. See issue #7686.")

	backend := stubserver.StartTestService(t, nil)
	defer backend.Stop()

	mr := manual.NewBuilderWithScheme("e2e-test")
	defer mr.Close()

	cc, err := grpc.NewClient(mr.Scheme()+":///", grpc.WithResolvers(mr), grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		t.Fatalf("Failed to create new client: %v", err)
	}
	defer cc.Close()

	if state := cc.GetState(); state != connectivity.Idle {
		t.Fatalf("Expected initial state to be IDLE, got %v", state)
	}

	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
	defer cancel()

	// The channel should transition to CONNECTING automatically when Connect()
	// is called.
	cc.Connect()
	testutils.AwaitState(ctx, t, cc, connectivity.Connecting)