diff --git a/scenario/run.go b/scenario/run.go index a6e37fb..94b9542 100644 --- a/scenario/run.go +++ b/scenario/run.go @@ -93,7 +93,19 @@ func (s *Scenario) Run(ctx context.Context, t *testing.T) error { defer cancel() } - res, rterr := s.runSpec(specCtx, rt, to, idx, spec) + var res *api.Result + ch := make(chan runSpecRes, 1) + + go s.runSpec(specCtx, ch, rt, to, idx, spec) + + select { + case <-specCtx.Done(): + t.Fatalf("assertion failed: timeout exceeded (%s)", to.After) + break + case runres := <-ch: + res = runres.r + rterr = runres.err + } if rterr != nil { break } @@ -115,14 +127,20 @@ func (s *Scenario) Run(ctx context.Context, t *testing.T) error { return rterr } +type runSpecRes struct { + r *api.Result + err error +} + // runSpec executes an individual test spec func (s *Scenario) runSpec( ctx context.Context, + ch chan runSpecRes, retry *api.Retry, timeout *api.Timeout, idx int, spec api.Evaluable, -) (*api.Result, error) { +) { sb := spec.Base() specTraceMsg := strconv.Itoa(idx) if sb.Name != "" { @@ -136,13 +154,15 @@ func (s *Scenario) runSpec( // Just evaluate the test spec once res, err := spec.Eval(ctx) if err != nil { - return nil, err + ch <- runSpecRes{nil, err} + return } debug.Println( ctx, "run: single-shot (no retries) ok: %v", !res.Failed(), ) - return res, nil + ch <- runSpecRes{res, nil} + return } // retry the action and test the assertions until they succeed, @@ -187,7 +207,8 @@ func (s *Scenario) runSpec( res, err = spec.Eval(ctx) if err != nil { - return nil, err + ch <- runSpecRes{nil, err} + return } success = !res.Failed() debug.Println( @@ -200,13 +221,13 @@ func (s *Scenario) runSpec( } for _, f := range res.Failures() { debug.Println( - ctx, "run: attempt %d after %s failure: %s", - attempts, after, f, + ctx, "run: attempt %d failure: %s", + attempts, f, ) } attempts++ } - return res, nil + ch <- runSpecRes{res, nil} } // getTimeout returns the timeout configuration for the test spec. We check for