1// Copyright 2014 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package debug_test
6
7import (
8	"os"
9	"runtime"
10	. "runtime/debug"
11	"testing"
12)
13
14func TestWriteHeapDumpNonempty(t *testing.T) {
15	if runtime.GOOS == "js" {
16		t.Skipf("WriteHeapDump is not available on %s.", runtime.GOOS)
17	}
18	f, err := os.CreateTemp("", "heapdumptest")
19	if err != nil {
20		t.Fatalf("TempFile failed: %v", err)
21	}
22	defer os.Remove(f.Name())
23	defer f.Close()
24	WriteHeapDump(f.Fd())
25	fi, err := f.Stat()
26	if err != nil {
27		t.Fatalf("Stat failed: %v", err)
28	}
29	const minSize = 1
30	if size := fi.Size(); size < minSize {
31		t.Fatalf("Heap dump size %d bytes, expected at least %d bytes", size, minSize)
32	}
33}
34
35type Obj struct {
36	x, y int
37}
38
39func objfin(x *Obj) {
40	//println("finalized", x)
41}
42
43func TestWriteHeapDumpFinalizers(t *testing.T) {
44	if runtime.GOOS == "js" {
45		t.Skipf("WriteHeapDump is not available on %s.", runtime.GOOS)
46	}
47	f, err := os.CreateTemp("", "heapdumptest")
48	if err != nil {
49		t.Fatalf("TempFile failed: %v", err)
50	}
51	defer os.Remove(f.Name())
52	defer f.Close()
53
54	// bug 9172: WriteHeapDump couldn't handle more than one finalizer
55	println("allocating objects")
56	x := &Obj{}
57	runtime.SetFinalizer(x, objfin)
58	y := &Obj{}
59	runtime.SetFinalizer(y, objfin)
60
61	// Trigger collection of x and y, queueing of their finalizers.
62	println("starting gc")
63	runtime.GC()
64
65	// Make sure WriteHeapDump doesn't fail with multiple queued finalizers.
66	println("starting dump")
67	WriteHeapDump(f.Fd())
68	println("done dump")
69}
70
71type G[T any] struct{}
72type I interface {
73	M()
74}
75
76//go:noinline
77func (g G[T]) M() {}
78
79var dummy I = G[int]{}
80var dummy2 I = G[G[int]]{}
81
82func TestWriteHeapDumpTypeName(t *testing.T) {
83	if runtime.GOOS == "js" {
84		t.Skipf("WriteHeapDump is not available on %s.", runtime.GOOS)
85	}
86	f, err := os.CreateTemp("", "heapdumptest")
87	if err != nil {
88		t.Fatalf("TempFile failed: %v", err)
89	}
90	defer os.Remove(f.Name())
91	defer f.Close()
92	WriteHeapDump(f.Fd())
93	dummy.M()
94	dummy2.M()
95}
96