aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/trace/trace_stack_test.go
diff options
context:
space:
mode:
authorCarlos Amedee <carlos@golang.org>2024-04-02 18:16:07 -0400
committerCarlos Amedee <carlos@golang.org>2024-04-15 16:44:47 +0000
commit2c5849dc40152cef6b7c3465ba0a1d6eb8f3c985 (patch)
treeac6c040c7b5ee797ca0bf35d3762001f7745ec0a /src/runtime/trace/trace_stack_test.go
parent8e987fadb57fa1fc98975ca2fcb3a4751f7f55ff (diff)
downloadgo-2c5849dc40152cef6b7c3465ba0a1d6eb8f3c985.tar.xz
runtime, cmd/trace: remove code paths that include v1 tracer
This change makes the new execution tracer described in #60773, the default tracer. This change attempts to make the smallest amount of changes for a single CL. Updates #66703 For #60773 Change-Id: I3742f3419c54f07d7c020ae5e1c18d29d8bcae6d Reviewed-on: https://go-review.googlesource.com/c/go/+/576256 Reviewed-by: Michael Knyszek <mknyszek@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/runtime/trace/trace_stack_test.go')
-rw-r--r--src/runtime/trace/trace_stack_test.go338
1 files changed, 0 insertions, 338 deletions
diff --git a/src/runtime/trace/trace_stack_test.go b/src/runtime/trace/trace_stack_test.go
deleted file mode 100644
index f427e578dc..0000000000
--- a/src/runtime/trace/trace_stack_test.go
+++ /dev/null
@@ -1,338 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package trace_test
-
-import (
- "bytes"
- "fmt"
- "internal/goexperiment"
- "internal/testenv"
- "internal/trace"
- "net"
- "os"
- "runtime"
- . "runtime/trace"
- "strings"
- "sync"
- "testing"
- "text/tabwriter"
- "time"
-)
-
-// TestTraceSymbolize tests symbolization and that events has proper stacks.
-// In particular that we strip bottom uninteresting frames like goexit,
-// top uninteresting frames (runtime guts).
-func TestTraceSymbolize(t *testing.T) {
- skipTraceSymbolizeTestIfNecessary(t)
-
- buf := new(bytes.Buffer)
- if err := Start(buf); err != nil {
- t.Fatalf("failed to start tracing: %v", err)
- }
- defer Stop() // in case of early return
-
- // Now we will do a bunch of things for which we verify stacks later.
- // It is impossible to ensure that a goroutine has actually blocked
- // on a channel, in a select or otherwise. So we kick off goroutines
- // that need to block first in the hope that while we are executing
- // the rest of the test, they will block.
- go func() { // func1
- select {}
- }()
- go func() { // func2
- var c chan int
- c <- 0
- }()
- go func() { // func3
- var c chan int
- <-c
- }()
- done1 := make(chan bool)
- go func() { // func4
- <-done1
- }()
- done2 := make(chan bool)
- go func() { // func5
- done2 <- true
- }()
- c1 := make(chan int)
- c2 := make(chan int)
- go func() { // func6
- select {
- case <-c1:
- case <-c2:
- }
- }()
- var mu sync.Mutex
- mu.Lock()
- go func() { // func7
- mu.Lock()
- mu.Unlock()
- }()
- var wg sync.WaitGroup
- wg.Add(1)
- go func() { // func8
- wg.Wait()
- }()
- cv := sync.NewCond(&sync.Mutex{})
- go func() { // func9
- cv.L.Lock()
- cv.Wait()
- cv.L.Unlock()
- }()
- ln, err := net.Listen("tcp", "127.0.0.1:0")
- if err != nil {
- t.Fatalf("failed to listen: %v", err)
- }
- go func() { // func10
- c, err := ln.Accept()
- if err != nil {
- t.Errorf("failed to accept: %v", err)
- return
- }
- c.Close()
- }()
- rp, wp, err := os.Pipe()
- if err != nil {
- t.Fatalf("failed to create a pipe: %v", err)
- }
- defer rp.Close()
- defer wp.Close()
- pipeReadDone := make(chan bool)
- go func() { // func11
- var data [1]byte
- rp.Read(data[:])
- pipeReadDone <- true
- }()
-
- time.Sleep(100 * time.Millisecond)
- runtime.GC()
- runtime.Gosched()
- time.Sleep(100 * time.Millisecond) // the last chance for the goroutines above to block
- done1 <- true
- <-done2
- select {
- case c1 <- 0:
- case c2 <- 0:
- }
- mu.Unlock()
- wg.Done()
- cv.Signal()
- c, err := net.Dial("tcp", ln.Addr().String())
- if err != nil {
- t.Fatalf("failed to dial: %v", err)
- }
- c.Close()
- var data [1]byte
- wp.Write(data[:])
- <-pipeReadDone
-
- oldGoMaxProcs := runtime.GOMAXPROCS(0)
- runtime.GOMAXPROCS(oldGoMaxProcs + 1)
-
- Stop()
-
- runtime.GOMAXPROCS(oldGoMaxProcs)
-
- events, _ := parseTrace(t, buf)
-
- // Now check that the stacks are correct.
- type eventDesc struct {
- Type byte
- Stk []frame
- }
- want := []eventDesc{
- {trace.EvGCStart, []frame{
- {"runtime.GC", 0},
- {"runtime/trace_test.TestTraceSymbolize", 0},
- {"testing.tRunner", 0},
- }},
- {trace.EvGoStart, []frame{
- {"runtime/trace_test.TestTraceSymbolize.func1", 0},
- }},
- {trace.EvGoSched, []frame{
- {"runtime/trace_test.TestTraceSymbolize", 112},
- {"testing.tRunner", 0},
- }},
- {trace.EvGoCreate, []frame{
- {"runtime/trace_test.TestTraceSymbolize", 41},
- {"testing.tRunner", 0},
- }},
- {trace.EvGoStop, []frame{
- {"runtime.block", 0},
- {"runtime/trace_test.TestTraceSymbolize.func1", 0},
- }},
- {trace.EvGoStop, []frame{
- {"runtime.chansend1", 0},
- {"runtime/trace_test.TestTraceSymbolize.func2", 0},
- }},
- {trace.EvGoStop, []frame{
- {"runtime.chanrecv1", 0},
- {"runtime/trace_test.TestTraceSymbolize.func3", 0},
- }},
- {trace.EvGoBlockRecv, []frame{
- {"runtime.chanrecv1", 0},
- {"runtime/trace_test.TestTraceSymbolize.func4", 0},
- }},
- {trace.EvGoUnblock, []frame{
- {"runtime.chansend1", 0},
- {"runtime/trace_test.TestTraceSymbolize", 114},
- {"testing.tRunner", 0},
- }},
- {trace.EvGoBlockSend, []frame{
- {"runtime.chansend1", 0},
- {"runtime/trace_test.TestTraceSymbolize.func5", 0},
- }},
- {trace.EvGoUnblock, []frame{
- {"runtime.chanrecv1", 0},
- {"runtime/trace_test.TestTraceSymbolize", 115},
- {"testing.tRunner", 0},
- }},
- {trace.EvGoBlockSelect, []frame{
- {"runtime.selectgo", 0},
- {"runtime/trace_test.TestTraceSymbolize.func6", 0},
- }},
- {trace.EvGoUnblock, []frame{
- {"runtime.selectgo", 0},
- {"runtime/trace_test.TestTraceSymbolize", 116},
- {"testing.tRunner", 0},
- }},
- {trace.EvGoBlockSync, []frame{
- {"sync.(*Mutex).Lock", 0},
- {"runtime/trace_test.TestTraceSymbolize.func7", 0},
- }},
- {trace.EvGoUnblock, []frame{
- {"sync.(*Mutex).Unlock", 0},
- {"runtime/trace_test.TestTraceSymbolize", 0},
- {"testing.tRunner", 0},
- }},
- {trace.EvGoBlockSync, []frame{
- {"sync.(*WaitGroup).Wait", 0},
- {"runtime/trace_test.TestTraceSymbolize.func8", 0},
- }},
- {trace.EvGoUnblock, []frame{
- {"sync.(*WaitGroup).Add", 0},
- {"sync.(*WaitGroup).Done", 0},
- {"runtime/trace_test.TestTraceSymbolize", 121},
- {"testing.tRunner", 0},
- }},
- {trace.EvGoBlockCond, []frame{
- {"sync.(*Cond).Wait", 0},
- {"runtime/trace_test.TestTraceSymbolize.func9", 0},
- }},
- {trace.EvGoUnblock, []frame{
- {"sync.(*Cond).Signal", 0},
- {"runtime/trace_test.TestTraceSymbolize", 0},
- {"testing.tRunner", 0},
- }},
- {trace.EvGoSleep, []frame{
- {"time.Sleep", 0},
- {"runtime/trace_test.TestTraceSymbolize", 0},
- {"testing.tRunner", 0},
- }},
- {trace.EvGomaxprocs, []frame{
- {"runtime.startTheWorld", 0}, // this is when the current gomaxprocs is logged.
- {"runtime.startTheWorldGC", 0},
- {"runtime.GOMAXPROCS", 0},
- {"runtime/trace_test.TestTraceSymbolize", 0},
- {"testing.tRunner", 0},
- }},
- }
- // Stacks for the following events are OS-dependent due to OS-specific code in net package.
- if runtime.GOOS != "windows" && runtime.GOOS != "plan9" {
- want = append(want, []eventDesc{
- {trace.EvGoBlockNet, []frame{
- {"internal/poll.(*FD).Accept", 0},
- {"net.(*netFD).accept", 0},
- {"net.(*TCPListener).accept", 0},
- {"net.(*TCPListener).Accept", 0},
- {"runtime/trace_test.TestTraceSymbolize.func10", 0},
- }},
- {trace.EvGoSysCall, []frame{
- {"syscall.read", 0},
- {"syscall.Read", 0},
- {"internal/poll.ignoringEINTRIO", 0},
- {"internal/poll.(*FD).Read", 0},
- {"os.(*File).read", 0},
- {"os.(*File).Read", 0},
- {"runtime/trace_test.TestTraceSymbolize.func11", 0},
- }},
- }...)
- }
- matched := make([]bool, len(want))
- for _, ev := range events {
- wantLoop:
- for i, w := range want {
- if matched[i] || w.Type != ev.Type || len(w.Stk) != len(ev.Stk) {
- continue
- }
-
- for fi, f := range ev.Stk {
- wf := w.Stk[fi]
- if wf.Fn != f.Fn || wf.Line != 0 && wf.Line != f.Line {
- continue wantLoop
- }
- }
- matched[i] = true
- }
- }
- for i, w := range want {
- if matched[i] {
- continue
- }
- seen, n := dumpEventStacks(w.Type, events)
- t.Errorf("Did not match event %v with stack\n%s\nSeen %d events of the type\n%s",
- trace.EventDescriptions[w.Type].Name, dumpFrames(w.Stk), n, seen)
- }
-}
-
-func skipTraceSymbolizeTestIfNecessary(t *testing.T) {
- testenv.MustHaveGoBuild(t)
- if goexperiment.ExecTracer2 {
- // An equivalent test exists in internal/trace/v2.
- t.Skip("skipping because this test is incompatible with the new tracer")
- }
- if IsEnabled() {
- t.Skip("skipping because -test.trace is set")
- }
-}
-
-func dumpEventStacks(typ byte, events []*trace.Event) ([]byte, int) {
- matched := 0
- o := new(bytes.Buffer)
- tw := tabwriter.NewWriter(o, 0, 8, 0, '\t', 0)
- for _, ev := range events {
- if ev.Type != typ {
- continue
- }
- matched++
- fmt.Fprintf(tw, "Offset %d\n", ev.Off)
- for _, f := range ev.Stk {
- fname := f.File
- if idx := strings.Index(fname, "/go/src/"); idx > 0 {
- fname = fname[idx:]
- }
- fmt.Fprintf(tw, " %v\t%s:%d\n", f.Fn, fname, f.Line)
- }
- }
- tw.Flush()
- return o.Bytes(), matched
-}
-
-type frame struct {
- Fn string
- Line int
-}
-
-func dumpFrames(frames []frame) []byte {
- o := new(bytes.Buffer)
- tw := tabwriter.NewWriter(o, 0, 8, 0, '\t', 0)
-
- for _, f := range frames {
- fmt.Fprintf(tw, " %v\t :%d\n", f.Fn, f.Line)
- }
- tw.Flush()
- return o.Bytes()
-}