| 305 | } |
| 306 | |
| 307 | func (e *Expecter) doMatchWithDeadline(ctx context.Context, name string, fn func(*bufio.Reader) error) error { |
| 308 | e.t.Helper() |
| 309 | |
| 310 | // A timeout is mandatory, caller can decide by passing a context |
| 311 | // that times out. |
| 312 | if _, ok := ctx.Deadline(); !ok { |
| 313 | timeout := testutil.WaitMedium |
| 314 | e.Logf("%s ctx has no deadline, using %s", name, timeout) |
| 315 | var cancel context.CancelFunc |
| 316 | //nolint:gocritic // Rule guard doesn't detect that we're using testutil.Wait*. |
| 317 | ctx, cancel = context.WithTimeout(ctx, timeout) |
| 318 | defer cancel() |
| 319 | } |
| 320 | |
| 321 | match := make(chan error, 1) |
| 322 | go func() { |
| 323 | defer close(match) |
| 324 | match <- fn(e.runeReader) |
| 325 | }() |
| 326 | select { |
| 327 | case err := <-match: |
| 328 | return err |
| 329 | case <-ctx.Done(): |
| 330 | // Ensure goroutine is cleaned up before test exit, do not call |
| 331 | // (*outExpecter).close here to let the caller decide. |
| 332 | _ = e.out.Close() |
| 333 | <-match |
| 334 | |
| 335 | return xerrors.Errorf("match deadline exceeded: %w", ctx.Err()) |
| 336 | } |
| 337 | } |
| 338 | |
| 339 | func (e *Expecter) Logf(format string, args ...interface{}) { |
| 340 | e.t.Helper() |