"context"
"flag"
"fmt"
+ "internal/goexperiment"
"internal/profile"
"internal/race"
"internal/trace"
if testing.Short() {
t.Skip("skipping in short mode")
}
+ if goexperiment.ExecTracer2 {
+ t.Skip("skipping because this test is incompatible with the new tracer")
+ }
// During Start, bunch of records are written to reflect the current
// snapshot of the program, including state of each goroutines.
// And some string constants are written to the trace to aid trace
if IsEnabled() {
t.Skip("skipping because -test.trace is set")
}
+ if goexperiment.ExecTracer2 {
+ // An equivalent test exists in internal/trace/v2.
+ t.Skip("skipping because this test is incompatible with the new tracer")
+ }
buf := new(bytes.Buffer)
if err := Start(buf); err != nil {
t.Fatalf("failed to start tracing: %v", err)
}
func TestTraceStress(t *testing.T) {
- if runtime.GOOS == "js" {
- t.Skip("no os.Pipe on js")
+ switch runtime.GOOS {
+ case "js", "wasip1":
+ t.Skip("no os.Pipe on " + runtime.GOOS)
}
if IsEnabled() {
t.Skip("skipping because -test.trace is set")
if testing.Short() {
t.Skip("skipping in -short mode")
}
+ if goexperiment.ExecTracer2 {
+ // An equivalent test exists in internal/trace/v2.
+ t.Skip("skipping because this test is incompatible with the new tracer")
+ }
var wg sync.WaitGroup
done := make(chan bool)
// Do a bunch of various stuff (timers, GC, network, etc) in a separate goroutine.
// And concurrently with all that start/stop trace 3 times.
func TestTraceStressStartStop(t *testing.T) {
- if runtime.GOOS == "js" {
- t.Skip("no os.Pipe on js")
+ switch runtime.GOOS {
+ case "js", "wasip1":
+ t.Skip("no os.Pipe on " + runtime.GOOS)
}
if IsEnabled() {
t.Skip("skipping because -test.trace is set")
}
+ if goexperiment.ExecTracer2 {
+ // An equivalent test exists in internal/trace/v2.
+ t.Skip("skipping because this test is incompatible with the new tracer")
+ }
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(8))
outerDone := make(chan bool)
if IsEnabled() {
t.Skip("skipping because -test.trace is set")
}
+ if goexperiment.ExecTracer2 {
+ t.Skip("skipping because this test is incompatible with the new tracer")
+ }
buf := new(bytes.Buffer)
if err := Start(buf); err != nil {
t.Fatalf("failed to start tracing: %v", err)
if IsEnabled() {
t.Skip("skipping because -test.trace is set")
}
+ if goexperiment.ExecTracer2 {
+ // An equivalent test exists in internal/trace/v2.
+ t.Skip("skipping because this test is incompatible with the new tracer")
+ }
cpuBuf := new(bytes.Buffer)
if err := pprof.StartCPUProfile(cpuBuf); err != nil {
pprofStacks := make(map[string]int)
for _, s := range prof.Sample {
if s.Label["tracing"] != nil {
- samples := int(s.Value[0])
- pprofSamples += samples
var fns []string
+ var leaf string
for _, loc := range s.Location {
for _, line := range loc.Line {
fns = append(fns, fmt.Sprintf("%s:%d", line.Function.Name, line.Line))
+ leaf = line.Function.Name
}
}
+ // runtime.sigprof synthesizes call stacks when "normal traceback is
+ // impossible or has failed", using particular placeholder functions
+ // to represent common failure cases. Look for those functions in
+ // the leaf position as a sign that the call stack and its
+ // symbolization are more complex than this test can handle.
+ //
+ // TODO: Make the symbolization done by the execution tracer and CPU
+ // profiler match up even in these harder cases. See #53378.
+ switch leaf {
+ case "runtime._System", "runtime._GC", "runtime._ExternalCode", "runtime._VDSO":
+ continue
+ }
stack := strings.Join(fns, " ")
+ samples := int(s.Value[0])
+ pprofSamples += samples
pprofStacks[stack] += samples
}
}
// of CPU samples, so we'll call that success.
overflowed := totalTraceSamples >= 1900
if traceSamples < pprofSamples {
- t.Logf("exectution trace did not include all CPU profile samples; %d in profile, %d in trace", pprofSamples, traceSamples)
+ t.Logf("execution trace did not include all CPU profile samples; %d in profile, %d in trace", pprofSamples, traceSamples)
if !overflowed {
t.Fail()
}