TestRoundRobin_NewAddressWhileBlocking tests the case where round_robin is configured on a channel, things are working as expected and then a resolver updates removes all addresses. An RPC attempted at this point in time will be blocked because there are no valid ¡ds. This test verifies that when ne
(t *testing.T)
| 133 | // blocked because there are no valid ¡ds. This test verifies that when new |
| 134 | // backends are added, the RPC is able to complete. |
| 135 | func (s) TestRoundRobin_NewAddressWhileBlocking(t *testing.T) { |
| 136 | ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) |
| 137 | defer cancel() |
| 138 | cc, r, backends := testRoundRobinBasic(ctx, t) |
| 139 | |
| 140 | // Send a resolver update with no addresses. This should push the channel into |
| 141 | // TransientFailure. |
| 142 | r.UpdateState(resolver.State{Addresses: []resolver.Address{}}) |
| 143 | testutils.AwaitState(ctx, t, cc, connectivity.TransientFailure) |
| 144 | |
| 145 | client := testgrpc.NewTestServiceClient(cc) |
| 146 | doneCh := make(chan struct{}) |
| 147 | go func() { |
| 148 | // The channel is currently in TransientFailure and this RPC will block |
| 149 | // until the channel becomes Ready, which will only happen when we push a |
| 150 | // resolver update with a valid backend address. |
| 151 | if _, err := client.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); err != nil { |
| 152 | t.Errorf("EmptyCall() = %v, want <nil>", err) |
| 153 | } |
| 154 | close(doneCh) |
| 155 | }() |
| 156 | |
| 157 | // Make sure that there is one pending RPC on the ClientConn before attempting |
| 158 | // to push new addresses through the name resolver. If we don't do this, the |
| 159 | // resolver update can happen before the above goroutine gets to make the RPC. |
| 160 | for { |
| 161 | if err := ctx.Err(); err != nil { |
| 162 | t.Fatal(err) |
| 163 | } |
| 164 | tcs, _ := channelz.GetTopChannels(0, 0) |
| 165 | if len(tcs) != 1 { |
| 166 | t.Fatalf("there should only be one top channel, not %d", len(tcs)) |
| 167 | } |
| 168 | started := tcs[0].ChannelMetrics.CallsStarted.Load() |
| 169 | completed := tcs[0].ChannelMetrics.CallsSucceeded.Load() + tcs[0].ChannelMetrics.CallsFailed.Load() |
| 170 | if (started - completed) == 1 { |
| 171 | break |
| 172 | } |
| 173 | time.Sleep(defaultTestShortTimeout) |
| 174 | } |
| 175 | |
| 176 | // Send a resolver update with a valid backend to push the channel to Ready |
| 177 | // and unblock the above RPC. |
| 178 | r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: backends[0].Address}}}) |
| 179 | |
| 180 | select { |
| 181 | case <-ctx.Done(): |
| 182 | t.Fatal("Timeout when waiting for blocked RPC to complete") |
| 183 | case <-doneCh: |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | // TestRoundRobin_OneServerDown tests the scenario where a channel is configured |
| 188 | // to round robin across a set of backends, and things are working correctly. |
nothing calls this directly
no test coverage detected