TestMessageLoopIdleTimeoutClosesConnection proves the mechanism the control-plane idle default relies on: with IdleTimeout configured, a connection that sends nothing hits the read deadline and the message loop returns nil (a clean close), which in the CP triggers DestroySession → worker back to hot
(t *testing.T)
| 17 | QueryExecutor |
| 18 | entered chan struct{} |
| 19 | release chan struct{} |
| 20 | } |
| 21 | |
| 22 | type blockAfterFirstRead struct { |
| 23 | first []byte |
| 24 | firstDelivered bool |
| 25 | secondReadStarted chan struct{} |
| 26 | releaseSecondRead chan struct{} |
| 27 | secondReadOnce sync.Once |
| 28 | } |
| 29 | |
| 30 | func (r *blockAfterFirstRead) Read(p []byte) (int, error) { |
| 31 | if !r.firstDelivered { |
| 32 | r.firstDelivered = true |
| 33 | return copy(p, r.first), nil |
| 34 | } |
| 35 | r.secondReadOnce.Do(func() { close(r.secondReadStarted) }) |
| 36 | <-r.releaseSecondRead |
| 37 | return 0, io.EOF |
| 38 | } |
| 39 | |
| 40 | func (e *blockingDrainExecutor) LastProfilingOutput() string { return "" } |
| 41 | |
| 42 | func (e *blockingDrainExecutor) ExecContext(ctx context.Context, _ string, _ ...any) (ExecResult, error) { |
| 43 | close(e.entered) |
| 44 | select { |
| 45 | case <-e.release: |
| 46 | return nil, nil |
| 47 | case <-ctx.Done(): |
| 48 | return nil, ctx.Err() |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | // TestMessageLoopIdleTimeoutClosesConnection proves the mechanism the |
| 53 | // control-plane idle default relies on: with IdleTimeout configured, a |
| 54 | // connection that sends nothing hits the read deadline and the message loop |
nothing calls this directly
no test coverage detected