Source file
src/cmd/trace/trace_test.go
1
2
3
4
5
6
7 package main
8
9 import (
10 "internal/trace"
11 "internal/trace/traceviewer"
12 "internal/trace/traceviewer/format"
13 "io"
14 "strings"
15 "testing"
16 )
17
18
19 type stacks map[uint64][]*trace.Frame
20
21
22
23 func (s *stacks) add(fname string) uint64 {
24 if *s == nil {
25 *s = make(map[uint64][]*trace.Frame)
26 }
27
28 id := uint64(len(*s))
29 (*s)[id] = []*trace.Frame{{Fn: fname}}
30 return id
31 }
32
33
34
35
36
37 func TestGoroutineCount(t *testing.T) {
38 w := trace.NewWriter()
39 w.Emit(trace.EvBatch, 0, 0)
40 w.Emit(trace.EvFrequency, 1)
41
42 var s stacks
43
44
45
46
47
48 w.Emit(trace.EvGoCreate, 1, 10, s.add("pkg.f1"), s.add("main.f1"))
49 w.Emit(trace.EvGoWaiting, 1, 10)
50
51
52 w.Emit(trace.EvGoCreate, 1, 20, s.add("pkg.f2"), s.add("main.f2"))
53 w.Emit(trace.EvGoInSyscall, 1, 20)
54
55
56 w.Emit(trace.EvGoCreate, 1, 30, s.add("pkg.f3"), s.add("main.f3"))
57
58 w.Emit(trace.EvProcStart, 2, 0)
59
60
61 w.Emit(trace.EvGoCreate, 1, 40, s.add("pkg.f4"), s.add("main.f4"))
62 w.Emit(trace.EvGoStartLocal, 1, 40)
63 w.Emit(trace.EvGoSched, 1, s.add("main.f4"))
64
65 res, err := trace.Parse(w, "")
66 if err != nil {
67 t.Fatalf("failed to parse test trace: %v", err)
68 }
69 res.Stacks = s
70
71 params := &traceParams{
72 parsed: res,
73 endTime: int64(1<<63 - 1),
74 }
75
76
77
78 c := traceviewer.ViewerDataTraceConsumer(io.Discard, 0, 1<<63-1)
79 c.ConsumeViewerEvent = func(ev *format.Event, _ bool) {
80 if ev.Name == "Goroutines" {
81 cnt := ev.Arg.(*format.GoroutineCountersArg)
82 if cnt.Runnable+cnt.Running > 2 {
83 t.Errorf("goroutine count=%+v; want no more than 2 goroutines in runnable/running state", cnt)
84 }
85 t.Logf("read %+v %+v", ev, cnt)
86 }
87 }
88
89
90 if err := generateTrace(params, c); err != nil {
91 t.Fatalf("generateTrace failed: %v", err)
92 }
93 }
94
95 func TestGoroutineFilter(t *testing.T) {
96
97
98
99 var s stacks
100
101 w := trace.NewWriter()
102 w.Emit(trace.EvBatch, 0, 0)
103 w.Emit(trace.EvFrequency, 1)
104
105
106 w.Emit(trace.EvGoCreate, 1, 10, s.add("pkg.f1"), s.add("main.f1"))
107 w.Emit(trace.EvGoWaiting, 1, 10)
108
109
110 w.Emit(trace.EvGoCreate, 1, 20, s.add("pkg.f2"), s.add("main.f2"))
111 w.Emit(trace.EvGoStartLocal, 1, 20)
112 w.Emit(trace.EvGoUnblockLocal, 1, 10, s.add("pkg.f2"))
113 w.Emit(trace.EvGoEnd, 1)
114
115
116 w.Emit(trace.EvGoStartLocal, 1, 10)
117 w.Emit(trace.EvGoBlock, 1, s.add("pkg.f3"))
118
119 res, err := trace.Parse(w, "")
120 if err != nil {
121 t.Fatalf("failed to parse test trace: %v", err)
122 }
123 res.Stacks = s
124
125 params := &traceParams{
126 parsed: res,
127 endTime: int64(1<<63 - 1),
128 gs: map[uint64]bool{10: true},
129 }
130
131 c := traceviewer.ViewerDataTraceConsumer(io.Discard, 0, 1<<63-1)
132 if err := generateTrace(params, c); err != nil {
133 t.Fatalf("generateTrace failed: %v", err)
134 }
135 }
136
137 func TestPreemptedMarkAssist(t *testing.T) {
138 w := trace.NewWriter()
139 w.Emit(trace.EvBatch, 0, 0)
140 w.Emit(trace.EvFrequency, 1)
141
142 var s stacks
143
144 w.Emit(trace.EvGoCreate, 1, 9999, s.add("pkg.f1"), s.add("main.f1"))
145 w.Emit(trace.EvGoStartLocal, 1, 9999)
146 w.Emit(trace.EvGCMarkAssistStart, 1, s.add("main.f1"))
147 w.Emit(trace.EvGoPreempt, 1, s.add("main.f1"))
148 w.Emit(trace.EvGoStartLocal, 1, 9999)
149 w.Emit(trace.EvGCMarkAssistDone, 1)
150 w.Emit(trace.EvGoBlock, 1, s.add("main.f2"))
151
152 res, err := trace.Parse(w, "")
153 if err != nil {
154 t.Fatalf("failed to parse test trace: %v", err)
155 }
156 res.Stacks = s
157
158 params := &traceParams{
159 parsed: res,
160 endTime: int64(1<<63 - 1),
161 }
162
163 c := traceviewer.ViewerDataTraceConsumer(io.Discard, 0, 1<<63-1)
164
165 marks := 0
166 c.ConsumeViewerEvent = func(ev *format.Event, _ bool) {
167 if strings.Contains(ev.Name, "MARK ASSIST") {
168 marks++
169 }
170 }
171 if err := generateTrace(params, c); err != nil {
172 t.Fatalf("generateTrace failed: %v", err)
173 }
174
175 if marks != 2 {
176 t.Errorf("Got %v MARK ASSIST events, want %v", marks, 2)
177 }
178 }
179
View as plain text