Source file src/cmd/trace/pprof_test.go

     1  // Copyright 2025 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.
     4  
     5  package main
     6  
     7  import (
     8  	"bytes"
     9  	"net/http"
    10  	"os"
    11  	"runtime/trace"
    12  	"strings"
    13  	"testing"
    14  	"testing/synctest"
    15  	"time"
    16  
    17  	"internal/trace/testtrace"
    18  )
    19  
    20  // Regression test for go.dev/issue/74850.
    21  func TestSyscallProfile74850(t *testing.T) {
    22  	testtrace.MustHaveSyscallEvents(t)
    23  
    24  	var buf bytes.Buffer
    25  	err := trace.Start(&buf)
    26  	if err != nil {
    27  		t.Fatalf("start tracing: %v", err)
    28  	}
    29  
    30  	synctest.Test(t, func(t *testing.T) {
    31  		go hidden1(t)
    32  		go hidden2(t)
    33  		go visible(t)
    34  		synctest.Wait()
    35  		time.Sleep(1 * time.Millisecond)
    36  		synctest.Wait()
    37  	})
    38  	trace.Stop()
    39  
    40  	if t.Failed() {
    41  		return
    42  	}
    43  
    44  	parsed, err := parseTrace(&buf, int64(buf.Len()))
    45  	if err != nil {
    46  		t.Fatalf("parsing trace: %v", err)
    47  	}
    48  
    49  	records, err := pprofByGoroutine(computePprofSyscall(), parsed)(&http.Request{})
    50  	if err != nil {
    51  		t.Fatalf("failed to generate pprof: %v\n", err)
    52  	}
    53  
    54  	for _, r := range records {
    55  		t.Logf("Record: n=%d, total=%v", r.Count, r.Time)
    56  		for _, f := range r.Stack {
    57  			t.Logf("\t%s", f.Func)
    58  			t.Logf("\t\t%s:%d @ 0x%x", f.File, f.Line, f.PC)
    59  		}
    60  	}
    61  	if len(records) == 0 {
    62  		t.Error("empty profile")
    63  	}
    64  
    65  	// Make sure we see the right frames.
    66  	wantSymbols := []string{"cmd/trace.visible", "cmd/trace.hidden1", "cmd/trace.hidden2"}
    67  	haveSymbols := make([]bool, len(wantSymbols))
    68  	for _, r := range records {
    69  		for _, f := range r.Stack {
    70  			for i, s := range wantSymbols {
    71  				if strings.Contains(f.Func, s) {
    72  					haveSymbols[i] = true
    73  				}
    74  			}
    75  		}
    76  	}
    77  	for i, have := range haveSymbols {
    78  		if !have {
    79  			t.Errorf("expected %s in syscall profile", wantSymbols[i])
    80  		}
    81  	}
    82  }
    83  
    84  func stat(t *testing.T) {
    85  	_, err := os.Stat(".")
    86  	if err != nil {
    87  		t.Errorf("os.Stat: %v", err)
    88  	}
    89  }
    90  
    91  func hidden1(t *testing.T) {
    92  	stat(t)
    93  }
    94  
    95  func hidden2(t *testing.T) {
    96  	stat(t)
    97  	stat(t)
    98  }
    99  
   100  func visible(t *testing.T) {
   101  	stat(t)
   102  	time.Sleep(1 * time.Millisecond)
   103  }
   104  

View as plain text