-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcgotraceback_test.go
107 lines (99 loc) · 2.17 KB
/
cgotraceback_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//go:build cgo && (linux || darwin)
// +build cgo
// +build linux darwin
package cgotraceback_test
import (
"io"
"reflect"
"runtime"
"runtime/pprof"
"testing"
"time"
_ "github.com/nsrip-dd/cgotraceback"
"github.com/nsrip-dd/cgotraceback/internal"
)
func TestCgoTraceback(t *testing.T) {
var pcs []uintptr
internal.DoCallback(func() {
internal.DoCallback2(func() {
var pc [128]uintptr
n := runtime.Callers(0, pc[:])
pcs = pc[:n]
})
})
if len(pcs) == 0 {
t.Fatalf("no calls in stack")
}
frames := runtime.CallersFrames(pcs)
var got []string
var found1, found2 bool
for {
frame, ok := frames.Next()
if !ok {
break
}
function := frame.Function
if function == internal.CFuncName {
found1 = true
}
if function == internal.CFuncName2 {
found2 = true
}
got = append(got, function)
}
if !(found1 && found2) {
t.Log("did not find desired function, got functions:")
}
for _, function := range got {
t.Logf("\t%s", function)
}
t.Log("got pcs:")
for _, pc := range pcs {
t.Logf("\t%016x", pc)
}
if !(found1 && found2) {
t.FailNow()
}
}
func TestRepeatedUnwind(t *testing.T) {
pcs := make([][]uintptr, 2)
internal.DoCallback(func() {
internal.DoCallback2(func() {
var pc [128]uintptr
for i := 0; i < 2; i++ {
n := runtime.Callers(0, pc[:])
pcs[i] = pc[:n]
}
})
})
if !reflect.DeepEqual(pcs[0], pcs[1]) {
t.Errorf("unwound twice with different results")
t.Logf("first: %x", pcs[0])
t.Logf("second: %x", pcs[1])
}
}
// If the libunwind implementation is not signal-safe, then this test might
// induce a deadlock when run with the CPU profiler enabled.
func TestNoDeadlock(t *testing.T) {
if testing.Short() {
t.Skip("skipping long test")
}
runtime.SetCPUProfileRate(1000)
err := pprof.StartCPUProfile(io.Discard)
if err == nil {
// If CPU profiling was already started (e.g. running benchmarks
// with the CPU profile) then we don't need to stop it for this
// test
defer pprof.StopCPUProfile()
}
var pcs []uintptr
start := time.Now()
for time.Since(start) < 3*time.Second {
internal.DoCallback(func() {
var pc [128]uintptr
n := runtime.Callers(0, pc[:])
pcs = pc[:n]
})
}
_ = pcs
}