...

Source file src/github.com/google/pprof/internal/report/stacks_test.go

Documentation: github.com/google/pprof/internal/report

     1  package report
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/google/pprof/profile"
     9  )
    10  
    11  // makeTestStacks generates a StackSet from a supplied list of samples.
    12  func makeTestStacks(samples ...*profile.Sample) StackSet {
    13  	prof := makeTestProfile(samples...)
    14  	rpt := NewDefault(prof, Options{OutputFormat: Tree, CallTree: true})
    15  	return rpt.Stacks()
    16  }
    17  
    18  func TestStacks(t *testing.T) {
    19  	// See report_test.go for the functions available to use in tests.
    20  	main, foo, bar, tee := testL[0], testL[1], testL[2], testL[3]
    21  
    22  	// stack holds an expected stack value found in StackSet.
    23  	type stack struct {
    24  		value int64
    25  		names []string
    26  	}
    27  	makeStack := func(value int64, names ...string) stack {
    28  		return stack{value, names}
    29  	}
    30  
    31  	for _, c := range []struct {
    32  		name   string
    33  		stacks StackSet
    34  		expect []stack
    35  	}{
    36  		{
    37  			"simple",
    38  			makeTestStacks(
    39  				testSample(100, bar, foo, main),
    40  				testSample(200, tee, foo, main),
    41  			),
    42  			[]stack{
    43  				makeStack(100, "0:root", "1:main", "2:foo", "3:bar"),
    44  				makeStack(200, "0:root", "1:main", "2:foo", "4:tee"),
    45  			},
    46  		},
    47  		{
    48  			"recursion",
    49  			makeTestStacks(
    50  				testSample(100, bar, foo, foo, foo, main),
    51  				testSample(200, bar, foo, foo, main),
    52  			),
    53  			[]stack{
    54  				// Note: Recursive calls to foo have different source indices.
    55  				makeStack(100, "0:root", "1:main", "2:foo", "2:foo", "2:foo", "3:bar"),
    56  				makeStack(200, "0:root", "1:main", "2:foo", "2:foo", "3:bar"),
    57  			},
    58  		},
    59  	} {
    60  		t.Run(c.name, func(t *testing.T) {
    61  			var got []stack
    62  			for _, s := range c.stacks.Stacks {
    63  				stk := stack{
    64  					value: s.Value,
    65  					names: make([]string, len(s.Sources)),
    66  				}
    67  				for i, src := range s.Sources {
    68  					stk.names[i] = fmt.Sprint(src, ":", c.stacks.Sources[src].FullName)
    69  				}
    70  				got = append(got, stk)
    71  			}
    72  			if !reflect.DeepEqual(c.expect, got) {
    73  				t.Errorf("expecting source %+v, got %+v", c.expect, got)
    74  			}
    75  		})
    76  	}
    77  }
    78  
    79  func TestStackSources(t *testing.T) {
    80  	// See report_test.go for the functions available to use in tests.
    81  	main, foo, bar, tee, inl := testL[0], testL[1], testL[2], testL[3], testL[5]
    82  
    83  	type srcInfo struct {
    84  		name    string
    85  		self    int64
    86  		inlined bool
    87  	}
    88  
    89  	source := func(stacks StackSet, name string) srcInfo {
    90  		src := findSource(stacks, name)
    91  		return srcInfo{src.FullName, src.Self, src.Inlined}
    92  	}
    93  
    94  	for _, c := range []struct {
    95  		name   string
    96  		stacks StackSet
    97  		srcs   []srcInfo
    98  	}{
    99  		{
   100  			"empty",
   101  			makeTestStacks(),
   102  			[]srcInfo{},
   103  		},
   104  		{
   105  			"two-leaves",
   106  			makeTestStacks(
   107  				testSample(100, bar, foo, main),
   108  				testSample(200, tee, bar, foo, main),
   109  				testSample(1000, tee, main),
   110  			),
   111  			[]srcInfo{
   112  				{"main", 0, false},
   113  				{"bar", 100, false},
   114  				{"foo", 0, false},
   115  				{"tee", 1200, false},
   116  			},
   117  		},
   118  		{
   119  			"inlined",
   120  			makeTestStacks(
   121  				testSample(100, inl),
   122  				testSample(200, inl),
   123  			),
   124  			[]srcInfo{
   125  				// inl has bar->tee
   126  				{"tee", 300, true},
   127  			},
   128  		},
   129  		{
   130  			"recursion",
   131  			makeTestStacks(
   132  				testSample(100, foo, foo, foo, main),
   133  				testSample(100, foo, foo, main),
   134  			),
   135  			[]srcInfo{
   136  				{"main", 0, false},
   137  				{"foo", 200, false},
   138  			},
   139  		},
   140  		{
   141  			"flat",
   142  			makeTestStacks(
   143  				testSample(100, main),
   144  				testSample(100, foo),
   145  				testSample(100, bar),
   146  				testSample(100, tee),
   147  			),
   148  			[]srcInfo{
   149  				{"main", 100, false},
   150  				{"bar", 100, false},
   151  				{"foo", 100, false},
   152  				{"tee", 100, false},
   153  			},
   154  		},
   155  	} {
   156  		t.Run(c.name, func(t *testing.T) {
   157  			for _, expect := range c.srcs {
   158  				got := source(c.stacks, expect.name)
   159  				if !reflect.DeepEqual(expect, got) {
   160  					t.Errorf("expecting source %+v, got %+v", expect, got)
   161  				}
   162  			}
   163  		})
   164  	}
   165  }
   166  
   167  func findSource(stacks StackSet, name string) StackSource {
   168  	for _, src := range stacks.Sources {
   169  		if src.FullName == name {
   170  			return src
   171  		}
   172  	}
   173  	return StackSource{}
   174  }
   175  

View as plain text