Tests the case where the resolver reports an error to the channel before reporting an update. Verifies that the channel eventually moves to TransientFailure and subsequent RPCs returns the error reported by the resolver to the user.
(t *testing.T)
| 138 | // TransientFailure and subsequent RPCs returns the error reported by the |
| 139 | // resolver to the user. |
| 140 | func (s) TestResolverReportError(t *testing.T) { |
| 141 | const resolverErr = "test resolver error" |
| 142 | r := manual.NewBuilderWithScheme("whatever") |
| 143 | r.BuildCallback = func(_ resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) { |
| 144 | cc.ReportError(errors.New(resolverErr)) |
| 145 | } |
| 146 | |
| 147 | cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r)) |
| 148 | if err != nil { |
| 149 | t.Fatalf("Error creating client: %v", err) |
| 150 | } |
| 151 | defer cc.Close() |
| 152 | cc.Connect() |
| 153 | |
| 154 | ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) |
| 155 | defer cancel() |
| 156 | testutils.AwaitState(ctx, t, cc, connectivity.TransientFailure) |
| 157 | |
| 158 | client := testgrpc.NewTestServiceClient(cc) |
| 159 | for range 5 { |
| 160 | _, err = client.EmptyCall(ctx, &testpb.Empty{}) |
| 161 | if code := status.Code(err); code != codes.Unavailable { |
| 162 | t.Fatalf("EmptyCall() = %v, want %v", err, codes.Unavailable) |
| 163 | } |
| 164 | if err == nil || !strings.Contains(err.Error(), resolverErr) { |
| 165 | t.Fatalf("EmptyCall() = %q, want %q", err, resolverErr) |
| 166 | } |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | // TestEnterIdleDuringResolverUpdateState tests a scenario that used to deadlock |
| 171 | // while calling UpdateState at the same time as the resolver being closed while |
nothing calls this directly
no test coverage detected