diff options
| author | Carlos Amedee <carlos@golang.org> | 2024-04-02 18:16:07 -0400 |
|---|---|---|
| committer | Carlos Amedee <carlos@golang.org> | 2024-04-15 16:44:47 +0000 |
| commit | 2c5849dc40152cef6b7c3465ba0a1d6eb8f3c985 (patch) | |
| tree | ac6c040c7b5ee797ca0bf35d3762001f7745ec0a /src/runtime/trace/trace_stack_test.go | |
| parent | 8e987fadb57fa1fc98975ca2fcb3a4751f7f55ff (diff) | |
| download | go-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.go | 338 |
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() -} |
