From: Michael Anthony Knyszek Date: Wed, 10 Dec 2025 02:35:15 +0000 (+0000) Subject: runtime: add extra subtest layer to TestFinalizerOrCleanupDeadlock X-Git-Tag: go1.26rc1~1^2~15 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=245bcdd478a8481b8c94b57d9234d3e4bf1b76b6;p=gostls13.git runtime: add extra subtest layer to TestFinalizerOrCleanupDeadlock Currently TestFinalizerOrCleanupDeadlock runs a bunch of tests for both cleanups and finalizers. However, it doesn't actually distinguish these two cases in the subtest names. This change adds another layer of subtest to distinguish them. For #76523. Change-Id: I18c2857e970cde43c18cbbcbc44e4d4ada3b2628 Reviewed-on: https://go-review.googlesource.com/c/go/+/728821 Reviewed-by: Carlos Amedee Auto-Submit: Michael Knyszek Reviewed-by: Cherry Mui TryBot-Bypass: Michael Knyszek --- diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go index 91f9740616..77afdc0690 100644 --- a/src/runtime/crash_test.go +++ b/src/runtime/crash_test.go @@ -1173,75 +1173,76 @@ func TestFinalizerOrCleanupDeadlock(t *testing.T) { progName = "Cleanup" want = "runtime.runCleanups" } - - // The runtime.runFinalizers/runtime.runCleanups frame should appear in panics, even if - // runtime frames are normally hidden (GOTRACEBACK=all). - t.Run("Panic", func(t *testing.T) { - t.Parallel() - output := runTestProg(t, "testprog", progName+"Deadlock", "GOTRACEBACK=all", "GO_TEST_FINALIZER_DEADLOCK=panic") - want := want + "()" - if !strings.Contains(output, want) { - t.Errorf("output does not contain %q:\n%s", want, output) - } - }) - - // The runtime.runFinalizers/runtime.Cleanups frame should appear in runtime.Stack, - // even though runtime frames are normally hidden. - t.Run("Stack", func(t *testing.T) { - t.Parallel() - output := runTestProg(t, "testprog", progName+"Deadlock", "GO_TEST_FINALIZER_DEADLOCK=stack") - want := want + "()" - if !strings.Contains(output, want) { - t.Errorf("output does not contain %q:\n%s", want, output) - } - }) - - // The runtime.runFinalizers/runtime.Cleanups frame should appear in goroutine - // profiles. - t.Run("PprofProto", func(t *testing.T) { - t.Parallel() - output := runTestProg(t, "testprog", progName+"Deadlock", "GO_TEST_FINALIZER_DEADLOCK=pprof_proto") - - p, err := profile.Parse(strings.NewReader(output)) - if err != nil { - // Logging the binary proto data is not very nice, but it might - // be a text error message instead. - t.Logf("Output: %s", output) - t.Fatalf("Error parsing proto output: %v", err) - } - for _, s := range p.Sample { - for _, loc := range s.Location { - for _, line := range loc.Line { - if line.Function.Name == want { - // Done! - return + t.Run(progName, func(t *testing.T) { + // The runtime.runFinalizers/runtime.runCleanups frame should appear in panics, even if + // runtime frames are normally hidden (GOTRACEBACK=all). + t.Run("Panic", func(t *testing.T) { + t.Parallel() + output := runTestProg(t, "testprog", progName+"Deadlock", "GOTRACEBACK=all", "GO_TEST_FINALIZER_DEADLOCK=panic") + want := want + "()" + if !strings.Contains(output, want) { + t.Errorf("output does not contain %q:\n%s", want, output) + } + }) + + // The runtime.runFinalizers/runtime.Cleanups frame should appear in runtime.Stack, + // even though runtime frames are normally hidden. + t.Run("Stack", func(t *testing.T) { + t.Parallel() + output := runTestProg(t, "testprog", progName+"Deadlock", "GO_TEST_FINALIZER_DEADLOCK=stack") + want := want + "()" + if !strings.Contains(output, want) { + t.Errorf("output does not contain %q:\n%s", want, output) + } + }) + + // The runtime.runFinalizers/runtime.Cleanups frame should appear in goroutine + // profiles. + t.Run("PprofProto", func(t *testing.T) { + t.Parallel() + output := runTestProg(t, "testprog", progName+"Deadlock", "GO_TEST_FINALIZER_DEADLOCK=pprof_proto") + + p, err := profile.Parse(strings.NewReader(output)) + if err != nil { + // Logging the binary proto data is not very nice, but it might + // be a text error message instead. + t.Logf("Output: %s", output) + t.Fatalf("Error parsing proto output: %v", err) + } + for _, s := range p.Sample { + for _, loc := range s.Location { + for _, line := range loc.Line { + if line.Function.Name == want { + // Done! + return + } } } } - } - t.Errorf("Profile does not contain %q:\n%s", want, p) - }) - - // The runtime.runFinalizers/runtime.runCleanups frame should appear in goroutine - // profiles (debug=1). - t.Run("PprofDebug1", func(t *testing.T) { - t.Parallel() - output := runTestProg(t, "testprog", progName+"Deadlock", "GO_TEST_FINALIZER_DEADLOCK=pprof_debug1") - want := want + "+" - if !strings.Contains(output, want) { - t.Errorf("output does not contain %q:\n%s", want, output) - } - }) - - // The runtime.runFinalizers/runtime.runCleanups frame should appear in goroutine - // profiles (debug=2). - t.Run("PprofDebug2", func(t *testing.T) { - t.Parallel() - output := runTestProg(t, "testprog", progName+"Deadlock", "GO_TEST_FINALIZER_DEADLOCK=pprof_debug2") - want := want + "()" - if !strings.Contains(output, want) { - t.Errorf("output does not contain %q:\n%s", want, output) - } + t.Errorf("Profile does not contain %q:\n%s", want, p) + }) + + // The runtime.runFinalizers/runtime.runCleanups frame should appear in goroutine + // profiles (debug=1). + t.Run("PprofDebug1", func(t *testing.T) { + t.Parallel() + output := runTestProg(t, "testprog", progName+"Deadlock", "GO_TEST_FINALIZER_DEADLOCK=pprof_debug1") + want := want + "+" + if !strings.Contains(output, want) { + t.Errorf("output does not contain %q:\n%s", want, output) + } + }) + + // The runtime.runFinalizers/runtime.runCleanups frame should appear in goroutine + // profiles (debug=2). + t.Run("PprofDebug2", func(t *testing.T) { + t.Parallel() + output := runTestProg(t, "testprog", progName+"Deadlock", "GO_TEST_FINALIZER_DEADLOCK=pprof_debug2") + want := want + "()" + if !strings.Contains(output, want) { + t.Errorf("output does not contain %q:\n%s", want, output) + } + }) }) } }