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 skipTraceTestsIfNeeded(t *testing.T) {
23 t.Skip("skipping: solaris timer can go backwards (https://golang.org/issue/8976)")
25 switch runtime.GOARCH {
27 // TODO(rsc): What does this have to do with the trace tests?
28 // There is no forking here.
29 t.Skipf("skipping on %s/%s, cannot fork", runtime.GOOS, runtime.GOARCH)
33 switch runtime.GOARCH {
35 t.Skip("skipping: arm tests fail with 'failed to parse trace' (https://golang.org/issue/9725)")
39 func TestTraceStartStop(t *testing.T) {
40 skipTraceTestsIfNeeded(t)
41 buf := new(bytes.Buffer)
42 if err := Start(buf); err != nil {
43 t.Fatalf("failed to start tracing: %v", err)
48 t.Fatalf("trace is empty")
50 time.Sleep(100 * time.Millisecond)
51 if size != buf.Len() {
52 t.Fatalf("trace writes after stop: %v -> %v", size, buf.Len())
56 func TestTraceDoubleStart(t *testing.T) {
57 skipTraceTestsIfNeeded(t)
59 buf := new(bytes.Buffer)
60 if err := Start(buf); err != nil {
61 t.Fatalf("failed to start tracing: %v", err)
63 if err := Start(buf); err == nil {
64 t.Fatalf("succeed to start tracing second time")
70 func TestTrace(t *testing.T) {
71 skipTraceTestsIfNeeded(t)
72 buf := new(bytes.Buffer)
73 if err := Start(buf); err != nil {
74 t.Fatalf("failed to start tracing: %v", err)
77 _, err := trace.Parse(buf)
78 if err == trace.ErrTimeOrder {
79 t.Skipf("skipping trace: %v", err)
82 t.Fatalf("failed to parse trace: %v", err)
86 func parseTrace(t *testing.T, r io.Reader) ([]*trace.Event, map[uint64]*trace.GDesc, error) {
87 events, err := trace.Parse(r)
88 if err == trace.ErrTimeOrder {
89 t.Skipf("skipping trace: %v", err)
94 gs := trace.GoroutineStats(events)
95 for goid := range gs {
96 // We don't do any particular checks on the result at the moment.
97 // But still check that RelatedGoroutines does not crash, hang, etc.
98 _ = trace.RelatedGoroutines(events, goid)
100 return events, gs, nil
103 func TestTraceStress(t *testing.T) {
104 skipTraceTestsIfNeeded(t)
106 var wg sync.WaitGroup
107 done := make(chan bool)
109 // Create a goroutine blocked before tracing.
116 // Create a goroutine blocked in syscall before tracing.
117 rp, wp, err := os.Pipe()
119 t.Fatalf("failed to create pipe: %v", err)
132 time.Sleep(time.Millisecond) // give the goroutine above time to block
134 buf := new(bytes.Buffer)
135 if err := Start(buf); err != nil {
136 t.Fatalf("failed to start tracing: %v", err)
139 procs := runtime.GOMAXPROCS(10)
140 time.Sleep(50 * time.Millisecond) // test proc stop/start events
143 runtime.LockOSThread()
155 // Trigger GC from malloc.
156 for i := 0; i < 1e3; i++ {
157 _ = make([]byte, 1<<20)
160 // Create a bunch of busy goroutines to load all Ps.
161 for p := 0; p < 10; p++ {
164 // Do something useful.
165 tmp := make([]byte, 1<<16)
185 timerDone := make(chan bool)
187 time.Sleep(time.Millisecond)
193 ln, err := net.Listen("tcp", "127.0.0.1:0")
195 t.Fatalf("listen failed: %v", err)
199 c, err := ln.Accept()
203 time.Sleep(time.Millisecond)
208 c, err := net.Dial("tcp", ln.Addr().String())
210 t.Fatalf("dial failed: %v", err)
221 // Unblock helper goroutines and wait them to finish.
227 runtime.GOMAXPROCS(procs)
230 _, _, err = parseTrace(t, buf)
232 t.Fatalf("failed to parse trace: %v", err)
236 // Do a bunch of various stuff (timers, GC, network, etc) in a separate goroutine.
237 // And concurrently with all that start/stop trace 3 times.
238 func TestTraceStressStartStop(t *testing.T) {
239 skipTraceTestsIfNeeded(t)
241 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(8))
242 outerDone := make(chan bool)
249 var wg sync.WaitGroup
250 done := make(chan bool)
258 rp, wp, err := os.Pipe()
260 t.Fatalf("failed to create pipe: %v", err)
273 time.Sleep(time.Millisecond)
276 runtime.LockOSThread()
288 // Trigger GC from malloc.
289 for i := 0; i < 1e3; i++ {
290 _ = make([]byte, 1<<20)
293 // Create a bunch of busy goroutines to load all Ps.
294 for p := 0; p < 10; p++ {
297 // Do something useful.
298 tmp := make([]byte, 1<<16)
317 runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
320 timerDone := make(chan bool)
322 time.Sleep(time.Millisecond)
328 ln, err := net.Listen("tcp", "127.0.0.1:0")
330 t.Fatalf("listen failed: %v", err)
334 c, err := ln.Accept()
338 time.Sleep(time.Millisecond)
343 c, err := net.Dial("tcp", ln.Addr().String())
345 t.Fatalf("dial failed: %v", err)
356 // Unblock helper goroutines and wait them to finish.
363 for i := 0; i < 3; i++ {
364 buf := new(bytes.Buffer)
365 if err := Start(buf); err != nil {
366 t.Fatalf("failed to start tracing: %v", err)
368 time.Sleep(time.Millisecond)
370 if _, _, err := parseTrace(t, buf); err != nil {
371 t.Fatalf("failed to parse trace: %v", err)
377 func TestTraceFutileWakeup(t *testing.T) {
378 // The test generates a full-load of futile wakeups on channels,
379 // and ensures that the trace is consistent after their removal.
380 skipTraceTestsIfNeeded(t)
381 if runtime.GOOS == "linux" && runtime.GOARCH == "ppc64le" {
382 t.Skip("test is unreliable; issue #10512")
385 buf := new(bytes.Buffer)
386 if err := Start(buf); err != nil {
387 t.Fatalf("failed to start tracing: %v", err)
390 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(8))
391 c0 := make(chan int, 1)
392 c1 := make(chan int, 1)
393 c2 := make(chan int, 1)
395 var done sync.WaitGroup
397 for p := 0; p < procs; p++ {
400 for i := 0; i < iters; i++ {
407 for i := 0; i < iters; i++ {
414 for i := 0; i < iters; i++ {
424 for i := 0; i < iters; i++ {
437 events, _, err := parseTrace(t, buf)
439 t.Fatalf("failed to parse trace: %v", err)
441 // Check that (1) trace does not contain EvFutileWakeup events and
442 // (2) there are no consecutive EvGoBlock/EvGCStart/EvGoBlock events
443 // (we call runtime.Gosched between all operations, so these would be futile wakeups).
444 gs := make(map[uint64]int)
445 for _, ev := range events {
447 case trace.EvFutileWakeup:
448 t.Fatalf("found EvFutileWakeup event")
449 case trace.EvGoBlockSend, trace.EvGoBlockRecv, trace.EvGoBlockSelect:
451 t.Fatalf("goroutine %v blocked on %v at %v right after start",
452 ev.G, trace.EventDescriptions[ev.Type].Name, ev.Ts)
455 t.Fatalf("goroutine %v blocked on %v at %v while blocked",
456 ev.G, trace.EventDescriptions[ev.Type].Name, ev.Ts)
459 case trace.EvGoStart: