Skip to content

testing: parent B.Cleanup() functions do not run if a sub-benchmark panics #60129

@evanj

Description

@evanj

What version of Go are you using (go version)?

$ go version
go version go1.20.4 darwin/arm64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env

GO111MODULE=""
GOARCH="arm64"
GOBIN=""
GOCACHE="/Users/evan.jones/Library/Caches/go-build"
GOENV="/Users/evan.jones/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/evan.jones/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/evan.jones/go"
GOPRIVATE=""
GOPROXY=""
GOROOT="/opt/homebrew/Cellar/go/1.20.4/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/opt/homebrew/Cellar/go/1.20.4/libexec/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.20.4"
GCCGO="gccgo"
AR="ar"
CC="cc"
CXX="c++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-O2 -g"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-O2 -g"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-O2 -g"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/g1/97d8s0r57hj4nv4_qd3fqcrm0000gp/T/go-build3259637153=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

The following benchmark named BenchmarkSubBenchPanicNeverRunsCleanup calls b.Cleanup, then panics in a sub-benchmark. The "higher level" Cleanup functions never run, but the ones in the specific benchmark do. The equivalent code for a Test calling T.Cleanup(), the cleanup functions are run correctly. This is similar to bug as #41355, which had similar problems when panicing in a sub-test. I believe the parent functions should run.

package benchcleanup

import (
	"testing"
)

func BenchmarkSubBenchPanicNeverRunsCleanup(b *testing.B) {
	b.Cleanup(func() {
		println("top-level benchmark cleanup is never called")
	})
	b.Run("subbench_level_1", func(b *testing.B) {
		b.Cleanup(func() {
			println("sub-benchmark level 1 cleanup is never called")
		})
		b.Run("subbench_level_2", func(b *testing.B) {
			b.Cleanup(func() {
				println("sub-benchmark level 2 cleanup IS called")
			})
			panic("sub-benchmark level 2 panic")
		})
	})
}

func TestSubTestPanicNeverRunsCleanup(t *testing.T) {
	t.Cleanup(func() {
		println("top-level test cleanup is called")
	})
	t.Run("subbench_level_1", func(t *testing.T) {
		t.Cleanup(func() {
			println("sub-test level 1 cleanup is called")
		})
		t.Run("subbench_level_2", func(t *testing.T) {
			t.Cleanup(func() {
				println("sub-test level 2 cleanup is called")
			})
			panic("sub-test level 2 panic")
		})
	})
}

What did you expect to see?

The cleanup functions should be called.

What did you see instead?

Only the cleanup function in the same benchmark are called.

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.help wanted

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions