Source file
src/runtime/trace_cgo_test.go
1
2
3
4
5
6
7 package runtime_test
8
9 import (
10 "bytes"
11 "fmt"
12 "internal/race"
13 "internal/testenv"
14 "internal/trace"
15 "io"
16 "os"
17 "runtime"
18 "strings"
19 "testing"
20 )
21
22
23
24
25 func TestTraceUnwindCGO(t *testing.T) {
26 if *flagQuick {
27 t.Skip("-quick")
28 }
29 testenv.MustHaveGoBuild(t)
30 if runtime.GOOS == "freebsd" && race.Enabled {
31 t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.")
32 }
33 t.Parallel()
34
35 exe, err := buildTestProg(t, "testprogcgo")
36 if err != nil {
37 t.Fatal(err)
38 }
39
40 wantLogs := []string{
41 "goCalledFromC",
42 "goCalledFromCThread",
43 }
44 logs := make(map[string]*trace.Event)
45 for _, category := range wantLogs {
46 logs[category] = nil
47 }
48 for _, tracefpunwindoff := range []int{1, 0} {
49 env := fmt.Sprintf("GODEBUG=tracefpunwindoff=%d", tracefpunwindoff)
50 got := runBuiltTestProg(t, exe, "Trace", env)
51 prefix, tracePath, found := strings.Cut(got, ":")
52 if !found || prefix != "trace path" {
53 t.Fatalf("unexpected output:\n%s\n", got)
54 }
55 defer os.Remove(tracePath)
56
57 traceData, err := os.ReadFile(tracePath)
58 if err != nil {
59 t.Fatalf("failed to read trace: %s", err)
60 }
61 for category := range logs {
62 event := mustFindLogV2(t, bytes.NewReader(traceData), category)
63 if wantEvent := logs[category]; wantEvent == nil {
64 logs[category] = &event
65 } else if got, want := dumpStackV2(&event), dumpStackV2(wantEvent); got != want {
66 t.Errorf("%q: got stack:\n%s\nwant stack:\n%s\n", category, got, want)
67 }
68 }
69 }
70 }
71
72 func mustFindLogV2(t *testing.T, trc io.Reader, category string) trace.Event {
73 r, err := trace.NewReader(trc)
74 if err != nil {
75 t.Fatalf("bad trace: %v", err)
76 }
77 var candidates []trace.Event
78 for {
79 ev, err := r.ReadEvent()
80 if err == io.EOF {
81 break
82 }
83 if err != nil {
84 t.Fatalf("failed to parse trace: %v", err)
85 }
86 if ev.Kind() == trace.EventLog && ev.Log().Category == category {
87 candidates = append(candidates, ev)
88 }
89 }
90 if len(candidates) == 0 {
91 t.Fatalf("could not find log with category: %q", category)
92 } else if len(candidates) > 1 {
93 t.Fatalf("found more than one log with category: %q", category)
94 }
95 return candidates[0]
96 }
97
98
99 func dumpStackV2(e *trace.Event) string {
100 var buf bytes.Buffer
101 for f := range e.Stack().Frames() {
102 file := strings.TrimPrefix(f.File, runtime.GOROOT())
103 fmt.Fprintf(&buf, "%s\n\t%s:%d\n", f.Func, file, f.Line)
104 }
105 return buf.String()
106 }
107
View as plain text