1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
20 func TestTraceStartStop(t *testing.T) {
21 buf := new(bytes.Buffer)
22 if err := Start(buf); err != nil {
23 t.Fatalf("failed to start tracing: %v", err)
28 t.Fatalf("trace is empty")
30 time.Sleep(100 * time.Millisecond)
31 if size != buf.Len() {
32 t.Fatalf("trace writes after stop: %v -> %v", size, buf.Len())
36 func TestTraceDoubleStart(t *testing.T) {
38 buf := new(bytes.Buffer)
39 if err := Start(buf); err != nil {
40 t.Fatalf("failed to start tracing: %v", err)
42 if err := Start(buf); err == nil {
43 t.Fatalf("succeed to start tracing second time")
49 func TestTrace(t *testing.T) {
50 buf := new(bytes.Buffer)
51 if err := Start(buf); err != nil {
52 t.Fatalf("failed to start tracing: %v", err)
55 _, err := trace.Parse(buf)
56 if err == trace.ErrTimeOrder {
57 t.Skipf("skipping trace: %v", err)
60 t.Fatalf("failed to parse trace: %v", err)
64 func parseTrace(t *testing.T, r io.Reader) ([]*trace.Event, map[uint64]*trace.GDesc, error) {
65 events, err := trace.Parse(r)
66 if err == trace.ErrTimeOrder {
67 t.Skipf("skipping trace: %v", err)
72 gs := trace.GoroutineStats(events)
73 for goid := range gs {
74 // We don't do any particular checks on the result at the moment.
75 // But still check that RelatedGoroutines does not crash, hang, etc.
76 _ = trace.RelatedGoroutines(events, goid)
78 return events, gs, nil
81 func TestTraceStress(t *testing.T) {
83 done := make(chan bool)
85 // Create a goroutine blocked before tracing.
92 // Create a goroutine blocked in syscall before tracing.
93 rp, wp, err := os.Pipe()
95 t.Fatalf("failed to create pipe: %v", err)
108 time.Sleep(time.Millisecond) // give the goroutine above time to block
110 buf := new(bytes.Buffer)
111 if err := Start(buf); err != nil {
112 t.Fatalf("failed to start tracing: %v", err)
115 procs := runtime.GOMAXPROCS(10)
116 time.Sleep(50 * time.Millisecond) // test proc stop/start events
119 runtime.LockOSThread()
131 // Trigger GC from malloc.
133 if runtime.GOOS == "openbsd" && runtime.GOARCH == "arm" {
134 // Reduce allocation to avoid running out of
135 // memory on the builder - see issue/12032.
138 for i := 0; i < n; i++ {
139 _ = make([]byte, 1<<20)
142 // Create a bunch of busy goroutines to load all Ps.
143 for p := 0; p < 10; p++ {
146 // Do something useful.
147 tmp := make([]byte, 1<<16)
167 timerDone := make(chan bool)
169 time.Sleep(time.Millisecond)
175 ln, err := net.Listen("tcp", "127.0.0.1:0")
177 t.Fatalf("listen failed: %v", err)
181 c, err := ln.Accept()
185 time.Sleep(time.Millisecond)
190 c, err := net.Dial("tcp", ln.Addr().String())
192 t.Fatalf("dial failed: %v", err)
203 // Unblock helper goroutines and wait them to finish.
209 runtime.GOMAXPROCS(procs)
212 _, _, err = parseTrace(t, buf)
214 t.Fatalf("failed to parse trace: %v", err)
218 // Do a bunch of various stuff (timers, GC, network, etc) in a separate goroutine.
219 // And concurrently with all that start/stop trace 3 times.
220 func TestTraceStressStartStop(t *testing.T) {
221 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(8))
222 outerDone := make(chan bool)
229 var wg sync.WaitGroup
230 done := make(chan bool)
238 rp, wp, err := os.Pipe()
240 t.Fatalf("failed to create pipe: %v", err)
253 time.Sleep(time.Millisecond)
256 runtime.LockOSThread()
268 // Trigger GC from malloc.
270 if runtime.GOOS == "openbsd" && runtime.GOARCH == "arm" {
271 // Reduce allocation to avoid running out of
272 // memory on the builder - see issue/12032.
275 for i := 0; i < n; i++ {
276 _ = make([]byte, 1<<20)
279 // Create a bunch of busy goroutines to load all Ps.
280 for p := 0; p < 10; p++ {
283 // Do something useful.
284 tmp := make([]byte, 1<<16)
303 runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
306 timerDone := make(chan bool)
308 time.Sleep(time.Millisecond)
314 ln, err := net.Listen("tcp", "127.0.0.1:0")
316 t.Fatalf("listen failed: %v", err)
320 c, err := ln.Accept()
324 time.Sleep(time.Millisecond)
329 c, err := net.Dial("tcp", ln.Addr().String())
331 t.Fatalf("dial failed: %v", err)
342 // Unblock helper goroutines and wait them to finish.
349 for i := 0; i < 3; i++ {
350 buf := new(bytes.Buffer)
351 if err := Start(buf); err != nil {
352 t.Fatalf("failed to start tracing: %v", err)
354 time.Sleep(time.Millisecond)
356 if _, _, err := parseTrace(t, buf); err != nil {
357 t.Fatalf("failed to parse trace: %v", err)
363 func TestTraceFutileWakeup(t *testing.T) {
364 buf := new(bytes.Buffer)
365 if err := Start(buf); err != nil {
366 t.Fatalf("failed to start tracing: %v", err)
369 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(8))
370 c0 := make(chan int, 1)
371 c1 := make(chan int, 1)
372 c2 := make(chan int, 1)
374 var done sync.WaitGroup
376 for p := 0; p < procs; p++ {
379 for i := 0; i < iters; i++ {
386 for i := 0; i < iters; i++ {
393 for i := 0; i < iters; i++ {
403 for i := 0; i < iters; i++ {
416 events, _, err := parseTrace(t, buf)
418 t.Fatalf("failed to parse trace: %v", err)
420 // Check that (1) trace does not contain EvFutileWakeup events and
421 // (2) there are no consecutive EvGoBlock/EvGCStart/EvGoBlock events
422 // (we call runtime.Gosched between all operations, so these would be futile wakeups).
423 gs := make(map[uint64]int)
424 for _, ev := range events {
426 case trace.EvFutileWakeup:
427 t.Fatalf("found EvFutileWakeup event")
428 case trace.EvGoBlockSend, trace.EvGoBlockRecv, trace.EvGoBlockSelect:
430 t.Fatalf("goroutine %v blocked on %v at %v right after start",
431 ev.G, trace.EventDescriptions[ev.Type].Name, ev.Ts)
434 t.Fatalf("goroutine %v blocked on %v at %v while blocked",
435 ev.G, trace.EventDescriptions[ev.Type].Name, ev.Ts)
438 case trace.EvGoStart: