TestEnterIdleDuringResolverUpdateState tests a scenario that used to deadlock while calling UpdateState at the same time as the resolver being closed while the channel enters idle mode.
(t *testing.T)
| 171 | // while calling UpdateState at the same time as the resolver being closed while |
| 172 | // the channel enters idle mode. |
| 173 | func (s) TestEnterIdleDuringResolverUpdateState(t *testing.T) { |
| 174 | enterIdle := internal.EnterIdleModeForTesting.(func(*grpc.ClientConn)) |
| 175 | name := strings.ReplaceAll(strings.ToLower(t.Name()), "/", "") |
| 176 | |
| 177 | // Create a manual resolver that spams UpdateState calls until it is closed. |
| 178 | rb := manual.NewBuilderWithScheme(name) |
| 179 | var cancel context.CancelFunc |
| 180 | rb.BuildCallback = func(_ resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) { |
| 181 | var ctx context.Context |
| 182 | ctx, cancel = context.WithCancel(context.Background()) |
| 183 | go func() { |
| 184 | for ctx.Err() == nil { |
| 185 | cc.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: "test"}}}) |
| 186 | } |
| 187 | }() |
| 188 | } |
| 189 | rb.CloseCallback = func() { |
| 190 | cancel() |
| 191 | } |
| 192 | resolver.Register(rb) |
| 193 | |
| 194 | cc, err := grpc.NewClient(name+":///", grpc.WithTransportCredentials(insecure.NewCredentials())) |
| 195 | if err != nil { |
| 196 | t.Fatalf("grpc.NewClient error: %v", err) |
| 197 | } |
| 198 | defer cc.Close() |
| 199 | |
| 200 | // Enter/exit idle mode repeatedly. |
| 201 | for i := 0; i < 2000; i++ { |
| 202 | // Start a timer so we panic out of the deadlock and can see all the |
| 203 | // stack traces to debug the problem. |
| 204 | p := time.AfterFunc(time.Second, func() { |
| 205 | buf := make([]byte, 8192) |
| 206 | buf = buf[0:runtime.Stack(buf, true)] |
| 207 | t.Error("Timed out waiting for enterIdle") |
| 208 | panic(fmt.Sprint("Stack trace:\n", string(buf))) |
| 209 | }) |
| 210 | enterIdle(cc) |
| 211 | p.Stop() |
| 212 | cc.Connect() |
| 213 | } |
| 214 | } |
| 215 | |
| 216 | // TestEnterIdleDuringBalancerUpdateState tests calling UpdateState at the same |
| 217 | // time as the balancer being closed while the channel enters idle mode. |
nothing calls this directly
no test coverage detected