Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions cmd/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,47 @@ func TestRun_RerunFails_PanicPreventsRerun(t *testing.T) {
assert.ErrorContains(t, err, "rerun aborted because previous run had a suspected panic", out.String())
}

func TestRun_RerunFails_RuntimeGoexitPreventsRerun(t *testing.T) {
goexitOutput := `{"Package": "pkg", "Test": "TestOne/Subtest", "Action": "output",` +
`"Output":" testing.go:1913: test executed panic(nil) or runtime.Goexit:` +
` subtest may have called FailNow on a parent test\n"}`
jsonFailed := `{"Package": "pkg", "Action": "run"}
{"Package": "pkg", "Test": "TestOne", "Action": "run"}
{"Package": "pkg", "Test": "TestOne/Subtest", "Action": "run"}
` + goexitOutput + `
{"Package": "pkg", "Test": "TestOne/Subtest", "Action": "fail"}
{"Package": "pkg", "Test": "TestOne", "Action": "fail"}
{"Package": "pkg", "Action": "fail"}
`

var calls int
fn := func([]string) *proc {
calls++
return &proc{
cmd: fakeWaiter{result: newExitCode("failed", 1)},
stdout: strings.NewReader(jsonFailed),
stderr: bytes.NewReader(nil),
}
}
reset := patchStartGoTestFn(fn)
defer reset()

out := new(bytes.Buffer)
opts := &options{
rawCommand: true,
args: []string{"./test.test"},
format: "testname",
rerunFailsMaxAttempts: 3,
rerunFailsMaxInitialFailures: 1,
stdout: out,
stderr: os.Stderr,
hideSummary: newHideSummaryValue(),
}
err := run(opts)
assert.ErrorContains(t, err, "rerun aborted because previous run had a suspected panic", out.String())
assert.Equal(t, calls, 1)
}

func TestRun_InputFromStdin(t *testing.T) {
stdin := os.Stdin
t.Cleanup(func() { os.Stdin = stdin })
Expand Down
3 changes: 2 additions & 1 deletion cmd/rerunfails.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ func hasErrors(err error, exec *testjson.Execution, opts *options) error {
case ExitCodeWithDefault(err) > 1:
return fmt.Errorf("unexpected go test exit code: %v", err)
case exec.HasPanic():
return fmt.Errorf("rerun aborted because previous run had a suspected panic and some test may not have run")
return fmt.Errorf("rerun aborted because previous run had a suspected panic or runtime.Goexit" +
" and some test may not have run")
case exec.HasDataRace() && opts.rerunFailsMaxAttempts > 0 && opts.rerunFailsAbortOnDataRace:
return fmt.Errorf("rerun aborted because previous run had a data race")
default:
Expand Down
16 changes: 11 additions & 5 deletions testjson/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ type Package struct {
// cached is true if the package was marked as (cached)
cached bool
// panicked is true if the package, or one of the tests in the package,
// contained output that looked like a panic. This is used to mitigate
// github.com/golang/go/issues/45508. This field may be removed in the future
// if the issue is fixed in Go.
// contained output that looked like a panic or parent-test Goexit. This is
// used to mitigate github.com/golang/go/issues/45508. This field may be
// removed in the future if the issue is fixed in Go.
panicked bool
// hasDataRace is true if the package, or one of the tests in the package,
// contained output that looked like a data race.
Expand Down Expand Up @@ -202,8 +202,14 @@ func (p *Package) OutputLines(tc TestCase) []string {
return result
}

const runtimeGoexitOutput = "test executed panic(nil) or runtime.Goexit"

func outputLooksLikePanic(output string) bool {
return strings.HasPrefix(output, "panic: ") || strings.Contains(output, runtimeGoexitOutput)
}

func (p *Package) addOutput(id int, output string) {
if strings.HasPrefix(output, "panic: ") {
if outputLooksLikePanic(output) {
p.panicked = true
}
if strings.HasPrefix(output, "WARNING: DATA RACE") {
Expand Down Expand Up @@ -682,7 +688,7 @@ func (e *Execution) Errors() []string {
}

// HasPanic returns true if at least one package had output that looked like a
// panic.
// panic or parent-test Goexit.
func (e *Execution) HasPanic() bool {
for _, pkg := range e.packages {
if pkg.panicked {
Expand Down