Source file
src/cmd/trace/trace_test.go
1
2
3
4
5
6
7 package main
8
9 import (
10 "cmd/internal/traceviewer"
11 "context"
12 "internal/trace"
13 "io"
14 rtrace "runtime/trace"
15 "strings"
16 "sync"
17 "testing"
18 "time"
19 )
20
21
22 type stacks map[uint64][]*trace.Frame
23
24
25
26 func (s *stacks) add(fname string) uint64 {
27 if *s == nil {
28 *s = make(map[uint64][]*trace.Frame)
29 }
30
31 id := uint64(len(*s))
32 (*s)[id] = []*trace.Frame{{Fn: fname}}
33 return id
34 }
35
36
37
38
39
40 func TestGoroutineCount(t *testing.T) {
41 w := trace.NewWriter()
42 w.Emit(trace.EvBatch, 0, 0)
43 w.Emit(trace.EvFrequency, 1)
44
45 var s stacks
46
47
48
49
50
51 w.Emit(trace.EvGoCreate, 1, 10, s.add("pkg.f1"), s.add("main.f1"))
52 w.Emit(trace.EvGoWaiting, 1, 10)
53
54
55 w.Emit(trace.EvGoCreate, 1, 20, s.add("pkg.f2"), s.add("main.f2"))
56 w.Emit(trace.EvGoInSyscall, 1, 20)
57
58
59 w.Emit(trace.EvGoCreate, 1, 30, s.add("pkg.f3"), s.add("main.f3"))
60
61 w.Emit(trace.EvProcStart, 2, 0)
62
63
64 w.Emit(trace.EvGoCreate, 1, 40, s.add("pkg.f4"), s.add("main.f4"))
65 w.Emit(trace.EvGoStartLocal, 1, 40)
66 w.Emit(trace.EvGoSched, 1, s.add("main.f4"))
67
68 res, err := trace.Parse(w, "")
69 if err != nil {
70 t.Fatalf("failed to parse test trace: %v", err)
71 }
72 res.Stacks = s
73
74 params := &traceParams{
75 parsed: res,
76 endTime: int64(1<<63 - 1),
77 }
78
79
80
81 c := viewerDataTraceConsumer(io.Discard, 0, 1<<63-1)
82 c.consumeViewerEvent = func(ev *traceviewer.Event, _ bool) {
83 if ev.Name == "Goroutines" {
84 cnt := ev.Arg.(*goroutineCountersArg)
85 if cnt.Runnable+cnt.Running > 2 {
86 t.Errorf("goroutine count=%+v; want no more than 2 goroutines in runnable/running state", cnt)
87 }
88 t.Logf("read %+v %+v", ev, cnt)
89 }
90 }
91
92
93 if err := generateTrace(params, c); err != nil {
94 t.Fatalf("generateTrace failed: %v", err)
95 }
96 }
97
98 func TestGoroutineFilter(t *testing.T) {
99
100
101
102 var s stacks
103
104 w := trace.NewWriter()
105 w.Emit(trace.EvBatch, 0, 0)
106 w.Emit(trace.EvFrequency, 1)
107
108
109 w.Emit(trace.EvGoCreate, 1, 10, s.add("pkg.f1"), s.add("main.f1"))
110 w.Emit(trace.EvGoWaiting, 1, 10)
111
112
113 w.Emit(trace.EvGoCreate, 1, 20, s.add("pkg.f2"), s.add("main.f2"))
114 w.Emit(trace.EvGoStartLocal, 1, 20)
115 w.Emit(trace.EvGoUnblockLocal, 1, 10, s.add("pkg.f2"))
116 w.Emit(trace.EvGoEnd, 1)
117
118
119 w.Emit(trace.EvGoStartLocal, 1, 10)
120 w.Emit(trace.EvGoBlock, 1, s.add("pkg.f3"))
121
122 res, err := trace.Parse(w, "")
123 if err != nil {
124 t.Fatalf("failed to parse test trace: %v", err)
125 }
126 res.Stacks = s
127
128 params := &traceParams{
129 parsed: res,
130 endTime: int64(1<<63 - 1),
131 gs: map[uint64]bool{10: true},
132 }
133
134 c := viewerDataTraceConsumer(io.Discard, 0, 1<<63-1)
135 if err := generateTrace(params, c); err != nil {
136 t.Fatalf("generateTrace failed: %v", err)
137 }
138 }
139
140 func TestPreemptedMarkAssist(t *testing.T) {
141 w := trace.NewWriter()
142 w.Emit(trace.EvBatch, 0, 0)
143 w.Emit(trace.EvFrequency, 1)
144
145 var s stacks
146
147 w.Emit(trace.EvGoCreate, 1, 9999, s.add("pkg.f1"), s.add("main.f1"))
148 w.Emit(trace.EvGoStartLocal, 1, 9999)
149 w.Emit(trace.EvGCMarkAssistStart, 1, s.add("main.f1"))
150 w.Emit(trace.EvGoPreempt, 1, s.add("main.f1"))
151 w.Emit(trace.EvGoStartLocal, 1, 9999)
152 w.Emit(trace.EvGCMarkAssistDone, 1)
153 w.Emit(trace.EvGoBlock, 1, s.add("main.f2"))
154
155 res, err := trace.Parse(w, "")
156 if err != nil {
157 t.Fatalf("failed to parse test trace: %v", err)
158 }
159 res.Stacks = s
160
161 params := &traceParams{
162 parsed: res,
163 endTime: int64(1<<63 - 1),
164 }
165
166 c := viewerDataTraceConsumer(io.Discard, 0, 1<<63-1)
167
168 marks := 0
169 c.consumeViewerEvent = func(ev *traceviewer.Event, _ bool) {
170 if strings.Contains(ev.Name, "MARK ASSIST") {
171 marks++
172 }
173 }
174 if err := generateTrace(params, c); err != nil {
175 t.Fatalf("generateTrace failed: %v", err)
176 }
177
178 if marks != 2 {
179 t.Errorf("Got %v MARK ASSIST events, want %v", marks, 2)
180 }
181 }
182
183 func TestFoo(t *testing.T) {
184 prog0 := func() {
185 ctx, task := rtrace.NewTask(context.Background(), "ohHappyDay")
186 rtrace.Log(ctx, "", "log before task ends")
187 task.End()
188 rtrace.Log(ctx, "", "log after task ends")
189 }
190 if err := traceProgram(t, prog0, "TestFoo"); err != nil {
191 t.Fatalf("failed to trace the program: %v", err)
192 }
193 res, err := parseTrace()
194 if err != nil {
195 t.Fatalf("failed to parse the trace: %v", err)
196 }
197 annotRes, _ := analyzeAnnotations()
198 var task *taskDesc
199 for _, t := range annotRes.tasks {
200 if t.name == "ohHappyDay" {
201 task = t
202 break
203 }
204 }
205 if task == nil {
206 t.Fatal("failed to locate expected task event")
207 }
208
209 params := &traceParams{
210 parsed: res,
211 mode: modeTaskOriented,
212 startTime: task.firstTimestamp() - 1,
213 endTime: task.lastTimestamp() + 1,
214 tasks: []*taskDesc{task},
215 }
216
217 c := viewerDataTraceConsumer(io.Discard, 0, 1<<63-1)
218
219 var logBeforeTaskEnd, logAfterTaskEnd bool
220 c.consumeViewerEvent = func(ev *traceviewer.Event, _ bool) {
221 if ev.Name == "log before task ends" {
222 logBeforeTaskEnd = true
223 }
224 if ev.Name == "log after task ends" {
225 logAfterTaskEnd = true
226 }
227 }
228 if err := generateTrace(params, c); err != nil {
229 t.Fatalf("generateTrace failed: %v", err)
230 }
231 if !logBeforeTaskEnd {
232 t.Error("failed to find 'log before task ends'")
233 }
234 if !logAfterTaskEnd {
235 t.Error("failed to find 'log after task ends'")
236 }
237
238 }
239
240 func TestDirectSemaphoreHandoff(t *testing.T) {
241 prog0 := func() {
242 var mu sync.Mutex
243 var wg sync.WaitGroup
244 mu.Lock()
245
246
247
248 for i := 0; i < 2; i++ {
249 wg.Add(1)
250 go func() {
251 defer wg.Done()
252 for i := 0; i < 100; i++ {
253 mu.Lock()
254 time.Sleep(100 * time.Microsecond)
255 mu.Unlock()
256 }
257 }()
258 }
259 mu.Unlock()
260 wg.Wait()
261 }
262 if err := traceProgram(t, prog0, "TestDirectSemaphoreHandoff"); err != nil {
263 t.Fatalf("failed to trace the program: %v", err)
264 }
265 _, err := parseTrace()
266 if err != nil {
267 t.Fatalf("failed to parse the trace: %v", err)
268 }
269 }
270
View as plain text