github.com/grafana/pyroscope@v1.18.0/pkg/og/structs/flamebearer/flamebearer_test.go (about)

     1  package flamebearer
     2  
     3  import (
     4  	. "github.com/onsi/ginkgo/v2"
     5  	. "github.com/onsi/gomega"
     6  
     7  	"github.com/grafana/pyroscope/pkg/og/storage/metadata"
     8  	"github.com/grafana/pyroscope/pkg/og/storage/segment"
     9  	"github.com/grafana/pyroscope/pkg/og/storage/tree"
    10  )
    11  
    12  var (
    13  	startTime     = int64(1635508310)
    14  	durationDelta = int64(10)
    15  	samples       = []uint64{1}
    16  	watermarks    = map[int]int64{1: 1}
    17  	maxNodes      = 1024
    18  	spyName       = "spy-name"
    19  	sampleRate    = uint32(10)
    20  	units         = metadata.Units("units")
    21  )
    22  
    23  var _ = Describe("FlamebearerProfile", func() {
    24  	Context("single", func() {
    25  		It("sets all attributes correctly", func() {
    26  			// taken from tree package tests
    27  			tree := tree.New()
    28  			tree.Insert([]byte("a;b"), uint64(1))
    29  			tree.Insert([]byte("a;c"), uint64(2))
    30  
    31  			timeline := &segment.Timeline{
    32  				StartTime:               startTime,
    33  				Samples:                 samples,
    34  				DurationDeltaNormalized: durationDelta,
    35  				Watermarks:              watermarks,
    36  			}
    37  
    38  			p := NewProfile(ProfileConfig{
    39  				Name:     "name",
    40  				Tree:     tree,
    41  				MaxNodes: maxNodes,
    42  				Timeline: timeline,
    43  				Metadata: metadata.Metadata{
    44  					SpyName:    spyName,
    45  					SampleRate: sampleRate,
    46  					Units:      units,
    47  				},
    48  			})
    49  
    50  			// Flamebearer
    51  			Expect(p.Flamebearer.Names).To(Equal([]string{"total", "a", "c", "b"}))
    52  			Expect(p.Flamebearer.Levels).To(Equal([][]int{
    53  				{0, 3, 0, 0},
    54  				{0, 3, 0, 1},
    55  				{0, 1, 1, 3, 0, 2, 2, 2},
    56  			}))
    57  			Expect(p.Flamebearer.NumTicks).To(Equal(3))
    58  			Expect(p.Flamebearer.MaxSelf).To(Equal(2))
    59  
    60  			// Metadata
    61  			Expect(p.Metadata.Name).To(Equal("name"))
    62  			Expect(p.Metadata.Format).To(Equal("single"))
    63  			Expect(p.Metadata.SpyName).To(Equal(spyName))
    64  			Expect(p.Metadata.SampleRate).To(Equal(sampleRate))
    65  			Expect(p.Metadata.Units).To(Equal(units))
    66  
    67  			// Timeline
    68  			Expect(p.Timeline.StartTime).To(Equal(startTime))
    69  			Expect(p.Timeline.Samples).To(Equal(samples))
    70  			Expect(p.Timeline.DurationDelta).To(Equal(durationDelta))
    71  			Expect(p.Timeline.Watermarks).To(Equal(watermarks))
    72  
    73  			// Ticks
    74  			Expect(p.LeftTicks).To(BeZero())
    75  			Expect(p.RightTicks).To(BeZero())
    76  
    77  			// Validate
    78  			Expect(p.Validate()).To(BeNil())
    79  		})
    80  	})
    81  })
    82  
    83  var _ = Describe("Checking profile validation", func() {
    84  	When("the version is invalid", func() {
    85  		var fb FlamebearerProfile
    86  		BeforeEach(func() {
    87  			fb.Version = 2
    88  		})
    89  
    90  		Context("and we validate the profile", func() {
    91  			It("returns an error", func() {
    92  				Expect(fb.Validate()).To(MatchError("unsupported version 2"))
    93  			})
    94  		})
    95  	})
    96  
    97  	When("the format is unsupported", func() {
    98  		var fb FlamebearerProfile
    99  
   100  		Context("and we validate the profile", func() {
   101  			It("returns an error", func() {
   102  				Expect(fb.Validate()).To(MatchError("unsupported format "))
   103  			})
   104  		})
   105  	})
   106  
   107  	When("there are no names", func() {
   108  		var fb FlamebearerProfile
   109  		BeforeEach(func() {
   110  			fb.Metadata.Format = "single"
   111  		})
   112  
   113  		Context("and we validate the profile", func() {
   114  			It("returns an error", func() {
   115  				Expect(fb.Validate()).To(MatchError("a profile must have at least one symbol name"))
   116  			})
   117  		})
   118  	})
   119  
   120  	When("there are no levels", func() {
   121  		var fb FlamebearerProfile
   122  		BeforeEach(func() {
   123  			fb.Metadata.Format = "single"
   124  			fb.Flamebearer.Names = []string{"name"}
   125  		})
   126  
   127  		Context("and we validate the profile", func() {
   128  			It("returns an error", func() {
   129  				Expect(fb.Validate()).To(MatchError("a profile must have at least one profiling level"))
   130  			})
   131  		})
   132  	})
   133  
   134  	When("the level size is invalid for the profile format", func() {
   135  		Context("and we validate a single profile", func() {
   136  			var fb FlamebearerProfile
   137  			BeforeEach(func() {
   138  				fb.Metadata.Format = "single"
   139  				fb.Flamebearer.Names = []string{"name"}
   140  				fb.Flamebearer.Levels = [][]int{{0, 0, 0, 0, 0, 0, 0}}
   141  			})
   142  
   143  			It("returns an error", func() {
   144  				Expect(fb.Validate()).To(MatchError("a profile level should have a multiple of 4 values, but there's a level with 7 values"))
   145  			})
   146  		})
   147  
   148  		Context("and we validate a double profile", func() {
   149  			var fb FlamebearerProfile
   150  			BeforeEach(func() {
   151  				fb.Metadata.Format = "double"
   152  				fb.Flamebearer.Names = []string{"name"}
   153  				fb.Flamebearer.Levels = [][]int{{0, 0, 0, 0}}
   154  			})
   155  
   156  			It("returns an error", func() {
   157  				Expect(fb.Validate()).To(MatchError("a profile level should have a multiple of 7 values, but there's a level with 4 values"))
   158  			})
   159  		})
   160  	})
   161  
   162  	When("the name index is invalid", func() {
   163  		Context("and we validate a single profile", func() {
   164  			var fb FlamebearerProfile
   165  			BeforeEach(func() {
   166  				fb.Metadata.Format = "single"
   167  				fb.Flamebearer.Names = []string{"name"}
   168  				fb.Flamebearer.Levels = [][]int{{0, 0, 0, 1}}
   169  			})
   170  
   171  			It("returns an error", func() {
   172  				Expect(fb.Validate()).To(MatchError("invalid name index 1, it should be smaller than 1"))
   173  			})
   174  		})
   175  
   176  		Context("and we validate a double profile", func() {
   177  			var fb FlamebearerProfile
   178  			BeforeEach(func() {
   179  				fb.Metadata.Format = "double"
   180  				fb.Flamebearer.Names = []string{"name"}
   181  				fb.Flamebearer.Levels = [][]int{{0, 0, 0, 0, 0, 0, 1}}
   182  			})
   183  
   184  			It("returns an error", func() {
   185  				Expect(fb.Validate()).To(MatchError("invalid name index 1, it should be smaller than 1"))
   186  			})
   187  		})
   188  	})
   189  
   190  	When("the name index is negative", func() {
   191  		Context("and we validate a single profile", func() {
   192  			var fb FlamebearerProfile
   193  			BeforeEach(func() {
   194  				fb.Metadata.Format = "single"
   195  				fb.Flamebearer.Names = []string{"name"}
   196  				fb.Flamebearer.Levels = [][]int{{0, 0, 0, -1}}
   197  			})
   198  
   199  			It("returns an error", func() {
   200  				Expect(fb.Validate()).To(MatchError("invalid name index -1, it should be a non-negative value"))
   201  			})
   202  		})
   203  	})
   204  
   205  	When("everything is valid", func() {
   206  		Context("and we validate a single profile", func() {
   207  			var fb FlamebearerProfile
   208  			BeforeEach(func() {
   209  				fb.Metadata.Format = "single"
   210  				fb.Flamebearer.Names = []string{"name"}
   211  				fb.Flamebearer.Levels = [][]int{{0, 0, 0, 0}}
   212  			})
   213  
   214  			It("returns no error", func() {
   215  				Expect(fb.Validate()).To(BeNil())
   216  			})
   217  		})
   218  
   219  		Context("and we validate a double profile", func() {
   220  			var fb FlamebearerProfile
   221  			BeforeEach(func() {
   222  				fb.Metadata.Format = "double"
   223  				fb.Flamebearer.Names = []string{"name"}
   224  				fb.Flamebearer.Levels = [][]int{{0, 0, 0, 0, 0, 0, 0}}
   225  			})
   226  
   227  			It("returns an error", func() {
   228  				Expect(fb.Validate()).To(BeNil())
   229  			})
   230  		})
   231  	})
   232  })