Repository: grpc/grpc-go
File: balancer/weightedtarget/weightedtarget_test.go (Go)

Code before:
		if gotSCSt.SubConn != sc3 {
			t.Fatalf("picker.Pick, got %v, want SubConn=%v", gotSCSt, sc3)
		}
	}

	// Update the Weighted Target Balancer with an empty address list and no
	// targets. This should cause a Transient Failure State update to the Client
	// Conn.
	emptyConfig, err := wtbParser.ParseConfig([]byte(`{}`))
	if err != nil {
		t.Fatalf("Failed to parse balancer config: %v", err)
	}
	if err := wtb.UpdateClientConnState(balancer.ClientConnState{
		ResolverState:  resolver.State{},
		BalancerConfig: emptyConfig,
	}); err != nil {
		t.Fatalf("Failed to update ClientConn state: %v", err)
	}

	state := <-cc.NewStateCh
	if state != connectivity.TransientFailure {
		t.Fatalf("Empty target update should have triggered a TF state update, got: %v", state)
	}
	p = <-cc.NewPickerCh
	const wantErr = "no targets to pick from"
	if _, err := p.Pick(balancer.PickInfo{}); !strings.Contains(err.Error(), wantErr) {
		t.Fatalf("Pick() returned error: %v, want: %v", err, wantErr)
	}
}

// TestWeightedTarget_OneSubBalancer_AddRemoveBackend tests the case where we
// have a weighted target balancer will one sub-balancer, and we add and remove
// backends from the subBalancer.
func (s) TestWeightedTarget_OneSubBalancer_AddRemoveBackend(t *testing.T) {
	cc := testutils.NewBalancerClientConn(t)
	wtb := wtbBuilder.Build(cc, balancer.BuildOptions{})
	defer wtb.Close()

	// Start with "cluster_1: round_robin".
	config, err := wtbParser.ParseConfig([]byte(`
{
  "targets": {
    "cluster_1": {
      "weight":1,
      "childPolicy": [{"round_robin": ""}]
    }
  }
}`))
	if err != nil {
		t.Fatalf("failed to parse balancer config: %v", err)
	}

Review comment (suggestion):
If `err` is nil this will panic.

```suggestion
	if _, err := p.Pick(balancer.PickInfo{}); err == nil || !strings.Contains(err.Error(), wantErr) {
```

Or

```go
	if _, err := p.Pick(balancer.PickInfo{}); !strings.Contains(fmt.Sprint(err), wantErr) {
```


Code after:
	// are closed. Remove duplicate events.
	// TODO: https://github.com/grpc/grpc-go/issues/6472 - Remove this
	// workaround once pickfirst is the only leaf policy and responsible for
	// shutting down SubConns.
	<-cc.ShutdownSubConnCh

	if scShutdown != sc2 {
		t.Fatalf("ShutdownSubConn, want %v, got %v", sc2, scShutdown)
	}
	scShutdown.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Shutdown})

	// Send subconn state change.
	sc3 := <-cc.NewSubConnCh
	sc3.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
	<-cc.NewPickerCh
	sc3.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
	p = <-cc.NewPickerCh

	// Test pick with one backend.
	for i := 0; i < 5; i++ {
		gotSCSt, _ := p.Pick(balancer.PickInfo{})
		if gotSCSt.SubConn != sc3 {
			t.Fatalf("picker.Pick, got %v, want SubConn=%v", gotSCSt, sc3)
		}
	}

	// Update the Weighted Target Balancer with an empty address list and no
	// targets. This should cause a Transient Failure State update to the Client
	// Conn.
	emptyConfig, err := wtbParser.ParseConfig([]byte(`{}`))
	if err != nil {
		t.Fatalf("Failed to parse balancer config: %v", err)
	}
	if err := wtb.UpdateClientConnState(balancer.ClientConnState{
		ResolverState:  resolver.State{},
		BalancerConfig: emptyConfig,
	}); err != nil {
		t.Fatalf("Failed to update ClientConn state: %v", err)
	}

	state := <-cc.NewStateCh
	if state != connectivity.TransientFailure {
		t.Fatalf("Empty target update should have triggered a TF state update, got: %v", state)
	}
	p = <-cc.NewPickerCh
	const wantErr = "no targets to pick from"
	if _, err := p.Pick(balancer.PickInfo{}); err == nil || !strings.Contains(err.Error(), wantErr) {
		t.Fatalf("Pick() returned error: %v, want: %v", err, wantErr)
	}
}