]> git.feebdaed.xyz Git - 0xmirror/go.git/commitdiff
runtime: add extra subtest layer to TestFinalizerOrCleanupDeadlock
authorMichael Anthony Knyszek <mknyszek@google.com>
Wed, 10 Dec 2025 02:35:15 +0000 (02:35 +0000)
committerGopher Robot <gobot@golang.org>
Thu, 11 Dec 2025 20:30:44 +0000 (12:30 -0800)
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 <carlos@golang.org>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Bypass: Michael Knyszek <mknyszek@google.com>

src/runtime/crash_test.go

index 91f9740616f04ab178f42edf94e8e4e1cb144e5b..77afdc069005d4c52c01bc124fd64321ff1c6b98 100644 (file)
@@ -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)
+                               }
+                       })
                })
        }
 }