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)
79 t.Fatalf("failed to parse trace: %v", err)
83 func parseTrace(r io.Reader) ([]*trace.Event, map[uint64]*trace.GDesc, error) {
84 events, err := trace.Parse(r)
88 gs := trace.GoroutineStats(events)
89 for goid := range gs {
90 // We don't do any particular checks on the result at the moment.
91 // But still check that RelatedGoroutines does not crash, hang, etc.
92 _ = trace.RelatedGoroutines(events, goid)
94 return events, gs, nil
97 func TestTraceStress(t *testing.T) {
98 skipTraceTestsIfNeeded(t)
100 var wg sync.WaitGroup
101 done := make(chan bool)
103 // Create a goroutine blocked before tracing.
110 // Create a goroutine blocked in syscall before tracing.
111 rp, wp, err := os.Pipe()
113 t.Fatalf("failed to create pipe: %v", err)
126 time.Sleep(time.Millisecond) // give the goroutine above time to block
128 buf := new(bytes.Buffer)
129 if err := Start(buf); err != nil {
130 t.Fatalf("failed to start tracing: %v", err)
133 procs := runtime.GOMAXPROCS(10)
134 time.Sleep(50 * time.Millisecond) // test proc stop/start events
137 runtime.LockOSThread()
149 // Trigger GC from malloc.
150 for i := 0; i < 1e3; i++ {
151 _ = make([]byte, 1<<20)
154 // Create a bunch of busy goroutines to load all Ps.
155 for p := 0; p < 10; p++ {
158 // Do something useful.
159 tmp := make([]byte, 1<<16)
179 timerDone := make(chan bool)
181 time.Sleep(time.Millisecond)
187 ln, err := net.Listen("tcp", "127.0.0.1:0")
189 t.Fatalf("listen failed: %v", err)
193 c, err := ln.Accept()
197 time.Sleep(time.Millisecond)
202 c, err := net.Dial("tcp", ln.Addr().String())
204 t.Fatalf("dial failed: %v", err)
215 // Unblock helper goroutines and wait them to finish.
221 runtime.GOMAXPROCS(procs)
224 _, _, err = parseTrace(buf)
226 t.Fatalf("failed to parse trace: %v", err)
230 // Do a bunch of various stuff (timers, GC, network, etc) in a separate goroutine.
231 // And concurrently with all that start/stop trace 3 times.
232 func TestTraceStressStartStop(t *testing.T) {
233 skipTraceTestsIfNeeded(t)
235 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(8))
236 outerDone := make(chan bool)
243 var wg sync.WaitGroup
244 done := make(chan bool)
252 rp, wp, err := os.Pipe()
254 t.Fatalf("failed to create pipe: %v", err)
267 time.Sleep(time.Millisecond)
270 runtime.LockOSThread()
282 // Trigger GC from malloc.
283 for i := 0; i < 1e3; i++ {
284 _ = make([]byte, 1<<20)
287 // Create a bunch of busy goroutines to load all Ps.
288 for p := 0; p < 10; p++ {
291 // Do something useful.
292 tmp := make([]byte, 1<<16)
311 runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
314 timerDone := make(chan bool)
316 time.Sleep(time.Millisecond)
322 ln, err := net.Listen("tcp", "127.0.0.1:0")
324 t.Fatalf("listen failed: %v", err)
328 c, err := ln.Accept()
332 time.Sleep(time.Millisecond)
337 c, err := net.Dial("tcp", ln.Addr().String())
339 t.Fatalf("dial failed: %v", err)
350 // Unblock helper goroutines and wait them to finish.
357 for i := 0; i < 3; i++ {
358 buf := new(bytes.Buffer)
359 if err := Start(buf); err != nil {
360 t.Fatalf("failed to start tracing: %v", err)
362 time.Sleep(time.Millisecond)
364 if _, _, err := parseTrace(buf); err != nil {
365 t.Fatalf("failed to parse trace: %v", err)
371 func TestTraceFutileWakeup(t *testing.T) {
372 // The test generates a full-load of futile wakeups on channels,
373 // and ensures that the trace is consistent after their removal.
374 skipTraceTestsIfNeeded(t)
375 if runtime.GOOS == "linux" && runtime.GOARCH == "ppc64le" {
376 t.Skip("test is unreliable; issue #10512")
379 buf := new(bytes.Buffer)
380 if err := Start(buf); err != nil {
381 t.Fatalf("failed to start tracing: %v", err)
384 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(8))
385 c0 := make(chan int, 1)
386 c1 := make(chan int, 1)
387 c2 := make(chan int, 1)
389 var done sync.WaitGroup
391 for p := 0; p < procs; p++ {
394 for i := 0; i < iters; i++ {
401 for i := 0; i < iters; i++ {
408 for i := 0; i < iters; i++ {
418 for i := 0; i < iters; i++ {
431 events, _, err := parseTrace(buf)
433 t.Fatalf("failed to parse trace: %v", err)
435 // Check that (1) trace does not contain EvFutileWakeup events and
436 // (2) there are no consecutive EvGoBlock/EvGCStart/EvGoBlock events
437 // (we call runtime.Gosched between all operations, so these would be futile wakeups).
438 gs := make(map[uint64]int)
439 for _, ev := range events {
441 case trace.EvFutileWakeup:
442 t.Fatalf("found EvFutileWakeup event")
443 case trace.EvGoBlockSend, trace.EvGoBlockRecv, trace.EvGoBlockSelect:
445 t.Fatalf("goroutine %v blocked on %v at %v right after start",
446 ev.G, trace.EventDescriptions[ev.Type].Name, ev.Ts)
449 t.Fatalf("goroutine %v blocked on %v at %v while blocked",
450 ev.G, trace.EventDescriptions[ev.Type].Name, ev.Ts)
453 case trace.EvGoStart: