github.com/grafana/pyroscope@v1.18.0/pkg/og/storage/tree/pprof_test.go (about)

     1  package tree
     2  
     3  import (
     4  	googlev1 "github.com/grafana/pyroscope/api/gen/proto/go/google/v1"
     5  	"time"
     6  
     7  	. "github.com/onsi/ginkgo/v2/dsl/core"
     8  	. "github.com/onsi/gomega"
     9  	"google.golang.org/protobuf/proto"
    10  )
    11  
    12  var _ = Describe("tree", func() {
    13  	var tree *Tree
    14  	var profile *googlev1.Profile
    15  	var fnNames []string
    16  
    17  	Describe("pprof", func() {
    18  		BeforeEach(func() {
    19  			tree = New()
    20  			tree.Insert([]byte("main;foo;1;2;3;4;5"), uint64(15))
    21  			tree.Insert([]byte("main;baz;1;2;3;4;5;6"), uint64(55))
    22  			tree.Insert([]byte("main;baz;1;2;3;4;5;6;8"), uint64(25))
    23  			tree.Insert([]byte("main;bar;1;2;3;4;5;6;8"), uint64(35))
    24  			tree.Insert([]byte("main;foo;1;2;3;4;5;6"), uint64(20))
    25  			tree.Insert([]byte("main;bar;1;2;3;4;5;6;9"), uint64(35))
    26  			tree.Insert([]byte("main;baz;1;2;3;4;5;6;7"), uint64(30))
    27  			tree.Insert([]byte("main;qux;1;2;3;4;5;6;7;8;9"), uint64(65))
    28  
    29  			profile = tree.Pprof(&PprofMetadata{
    30  				Type:      "cpu",
    31  				Unit:      "samples",
    32  				StartTime: time.Date(2021, 1, 1, 10, 0, 1, 0, time.UTC),
    33  				Duration:  time.Minute,
    34  			})
    35  			fnNames = []string{
    36  				"main",
    37  				"foo",
    38  				"bar",
    39  				"baz",
    40  				"qux",
    41  				"1",
    42  				"2",
    43  				"3",
    44  				"4",
    45  				"5",
    46  				"6",
    47  				"7",
    48  				"8",
    49  				"9",
    50  			}
    51  		})
    52  		It("Should serialize correctly", func() {
    53  			_, err := proto.Marshal(profile)
    54  			Expect(err).ToNot(HaveOccurred())
    55  		})
    56  		Describe("StringTable", func() {
    57  			It("Should build correctly", func() {
    58  				Expect(len(profile.StringTable)).To(Equal(17))
    59  				Expect(profile.StringTable).To(ConsistOf(
    60  					append(
    61  						fnNames,
    62  						"",
    63  						"cpu",
    64  						"samples",
    65  					),
    66  				))
    67  			})
    68  			It("Should have empty first element", func() {
    69  				profile = tree.Pprof(&PprofMetadata{})
    70  				Expect(profile.StringTable[0]).To(Equal(""))
    71  			})
    72  		})
    73  		Describe("Metadata", func() {
    74  			It("Should build correctly", func() {
    75  				Expect(profile.TimeNanos).To(Equal(int64(1609495201000000000)))
    76  				Expect(profile.DurationNanos).To(Equal(int64(60000000000)))
    77  				Expect(len(profile.SampleType)).To(Equal(1))
    78  				_type := profile.StringTable[profile.SampleType[0].Type]
    79  				unit := profile.StringTable[profile.SampleType[0].Unit]
    80  
    81  				Expect(_type).To(Equal("cpu"))
    82  				Expect(unit).To(Equal("samples"))
    83  			})
    84  		})
    85  		Describe("Function", func() {
    86  			It("Should build correctly", func() {
    87  				Expect(len(profile.Function)).To(Equal(14))
    88  				for _, fn := range profile.Function {
    89  					Expect(fn.Id).NotTo(BeZero())
    90  					Expect(fn.Name).NotTo(BeZero())
    91  					Expect(fn.SystemName).NotTo(BeZero())
    92  				}
    93  			})
    94  			Context("Name", func() {
    95  				It("Should have corresponding StringTable entries", func() {
    96  					var names []string
    97  					for _, fn := range profile.Function {
    98  						fnName := profile.StringTable[fn.Name]
    99  						names = append(names, fnName)
   100  					}
   101  					Expect(names).To(ConsistOf(fnNames))
   102  				})
   103  			})
   104  			Context("SystemName", func() {
   105  				It("Should have corresponding StringTable entries", func() {
   106  					var names []string
   107  					for _, fn := range profile.Function {
   108  						fnName := profile.StringTable[fn.SystemName]
   109  						names = append(names, fnName)
   110  					}
   111  					Expect(names).To(ConsistOf(fnNames))
   112  				})
   113  			})
   114  		})
   115  		Describe("Location", func() {
   116  			It("Should build correctly", func() {
   117  				Expect(len(profile.Location)).To(Equal(14))
   118  				for _, l := range profile.Location {
   119  					Expect(l.Id).NotTo(BeZero())
   120  					Expect(l.Line).NotTo(BeZero())
   121  					Expect(l.Line[0].FunctionId).NotTo(BeZero())
   122  				}
   123  			})
   124  			It("Should have corresponding functions", func() {
   125  				fnMap := make(map[uint64]*googlev1.Function)
   126  				for _, fn := range profile.Function {
   127  					fnMap[fn.Id] = fn
   128  				}
   129  				for _, l := range profile.Location {
   130  					fnID := l.Line[0].FunctionId
   131  					_, ok := fnMap[fnID]
   132  					Expect(ok).To(BeTrue())
   133  				}
   134  			})
   135  		})
   136  		Describe("Sample", func() {
   137  			It("Should build correctly", func() {
   138  				Expect(len(profile.Sample)).To(Equal(8))
   139  				for _, s := range profile.Sample {
   140  					Expect(s.LocationId).NotTo(BeZero())
   141  					Expect(s.Value).NotTo(BeZero())
   142  				}
   143  			})
   144  			It("Should have corresponding locations", func() {
   145  				lMap := make(map[uint64]*googlev1.Location)
   146  				for _, l := range profile.Location {
   147  					lMap[l.Id] = l
   148  				}
   149  				for _, s := range profile.Sample {
   150  					for _, l := range s.LocationId {
   151  						_, ok := lMap[l]
   152  						Expect(ok).To(BeTrue())
   153  					}
   154  				}
   155  			})
   156  		})
   157  	})
   158  })