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