StartWithWaiter runs the command in a goroutine but returns the error instead of asserting it. This is useful for testing error cases.
(t *testing.T, inv *serpent.Invocation)
| 267 | // StartWithWaiter runs the command in a goroutine but returns the error instead |
| 268 | // of asserting it. This is useful for testing error cases. |
| 269 | func StartWithWaiter(t *testing.T, inv *serpent.Invocation) *ErrorWaiter { |
| 270 | t.Helper() |
| 271 | |
| 272 | var ( |
| 273 | ctx = inv.Context() |
| 274 | cancel func() |
| 275 | |
| 276 | cleaningUp atomic.Bool |
| 277 | errCh = make(chan error, 1) |
| 278 | doneCh = make(chan struct{}) |
| 279 | ) |
| 280 | if _, ok := ctx.Deadline(); !ok { |
| 281 | ctx, cancel = context.WithDeadline(ctx, time.Now().Add(testutil.WaitMedium)) |
| 282 | } else { |
| 283 | ctx, cancel = context.WithCancel(inv.Context()) |
| 284 | } |
| 285 | |
| 286 | inv = inv.WithContext(ctx) |
| 287 | |
| 288 | go func() { |
| 289 | defer close(doneCh) |
| 290 | defer close(errCh) |
| 291 | err := inv.Run() |
| 292 | if cleaningUp.Load() && errors.Is(err, context.DeadlineExceeded) { |
| 293 | // If we're cleaning up, this error is likely related to the CLI |
| 294 | // teardown process. E.g., the server could be slow to shut down |
| 295 | // Postgres. |
| 296 | t.Logf("command %q timed out during test cleanup", inv.Command.FullName()) |
| 297 | } |
| 298 | // Whether or not this fails the test is left to the caller. |
| 299 | t.Logf("command %q exited with error: %v", inv.Command.FullName(), err) |
| 300 | errCh <- err |
| 301 | }() |
| 302 | |
| 303 | // Don't exit test routine until server is done. |
| 304 | t.Cleanup(func() { |
| 305 | cancel() |
| 306 | cleaningUp.Store(true) |
| 307 | <-doneCh |
| 308 | }) |
| 309 | return &ErrorWaiter{c: errCh, t: t, cancelFunc: cancel} |
| 310 | } |