Skip to content

Commit 43680eb

Browse files
authored
Add test cases for getSeriesRef (grafana/phlare#659)
This are additional test cases from the PR grafana/phlare#621, which we reverted.
1 parent ed05494 commit 43680eb

File tree

3 files changed

+88
-9
lines changed

3 files changed

+88
-9
lines changed

pkg/phlaredb/profile_store_test.go

Lines changed: 85 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package phlaredb
22

33
import (
44
"context"
5+
"crypto/md5"
56
"fmt"
7+
"io"
68
"os"
79
"strings"
810
"testing"
@@ -79,6 +81,53 @@ func sameProfileStream(i int) *testProfile {
7981
return tp
8082
}
8183

84+
// This will simulate a profile stream which ends and a new one starts at i > boundary
85+
func profileStreamEndingAndStarting(boundary int) func(int) *testProfile {
86+
return func(i int) *testProfile {
87+
tp := &testProfile{}
88+
89+
series := "at-beginning"
90+
if i > boundary {
91+
series = "at-end"
92+
}
93+
94+
tp.profileName = "process_cpu:cpu:nanoseconds:cpu:nanoseconds"
95+
tp.lbls = phlaremodel.LabelsFromStrings(
96+
phlaremodel.LabelNameProfileType, tp.profileName,
97+
"job", "test",
98+
"stream", series,
99+
)
100+
101+
tp.p.ID = uuid.MustParse(fmt.Sprintf("00000000-0000-0000-0000-%012d", i))
102+
tp.p.TimeNanos = time.Second.Nanoseconds() * int64(i)
103+
tp.p.Samples = []*schemav1.Sample{
104+
{
105+
StacktraceID: 0x1,
106+
Value: 10.0,
107+
},
108+
}
109+
tp.populateFingerprint()
110+
return tp
111+
}
112+
}
113+
114+
func nProfileStreams(n int) func(int) *testProfile {
115+
return func(i int) *testProfile {
116+
tp := sameProfileStream(i / n)
117+
118+
tp.lbls = phlaremodel.LabelsFromStrings(
119+
phlaremodel.LabelNameProfileType, tp.profileName,
120+
"job", "test",
121+
"stream", fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d", i%n)))),
122+
)
123+
tp.p.ID = uuid.MustParse(fmt.Sprintf("00000000-0000-0000-0000-%012d", i))
124+
125+
tp.populateFingerprint()
126+
return tp
127+
128+
}
129+
}
130+
82131
func readFullParquetFile[M any](t *testing.T, path string) ([]M, uint64) {
83132
f, err := os.Open(path)
84133
require.NoError(t, err)
@@ -95,8 +144,15 @@ func readFullParquetFile[M any](t *testing.T, path string) ([]M, uint64) {
95144
reader := parquet.NewGenericReader[M](f)
96145

97146
slice := make([]M, reader.NumRows())
98-
_, err = reader.Read(slice)
99-
require.NoError(t, err)
147+
offset := 0
148+
for {
149+
n, err := reader.Read(slice[offset:])
150+
if err == io.EOF {
151+
break
152+
}
153+
require.NoError(t, err)
154+
offset += n
155+
}
100156

101157
return slice, numRGs
102158
}
@@ -131,13 +187,27 @@ func TestProfileStore_RowGroupSplitting(t *testing.T) {
131187
expectedNumRows: 100,
132188
values: sameProfileStream,
133189
},
190+
{
191+
name: "a stream ending after half of the samples and a new one starting",
192+
cfg: &ParquetConfig{MaxRowGroupBytes: 1828, MaxBufferRowCount: 100000},
193+
expectedNumRGs: 10,
194+
expectedNumRows: 100,
195+
values: profileStreamEndingAndStarting(50),
196+
},
134197
{
135198
name: "multiple row groups because of maximum row num",
136199
cfg: &ParquetConfig{MaxRowGroupBytes: 128000, MaxBufferRowCount: 10},
137200
expectedNumRGs: 10,
138201
expectedNumRows: 100,
139202
values: sameProfileStream,
140203
},
204+
{
205+
name: "a single sample per series",
206+
cfg: &ParquetConfig{MaxRowGroupBytes: 1828, MaxBufferRowCount: 100000},
207+
expectedNumRGs: 10,
208+
expectedNumRows: 100,
209+
values: nProfileStreams(100),
210+
},
141211
} {
142212
t.Run(tc.name, func(t *testing.T) {
143213
path := t.TempDir()
@@ -164,9 +234,19 @@ func TestProfileStore_RowGroupSplitting(t *testing.T) {
164234
rows, numRGs := readFullParquetFile[*schemav1.Profile](t, path+"/profiles.parquet")
165235
require.Equal(t, int(tc.expectedNumRows), len(rows))
166236
assert.Equal(t, tc.expectedNumRGs, numRGs)
167-
assert.Equal(t, "00000000-0000-0000-0000-000000000000", rows[0].ID.String())
168-
assert.Equal(t, "00000000-0000-0000-0000-000000000001", rows[1].ID.String())
169-
assert.Equal(t, "00000000-0000-0000-0000-000000000002", rows[2].ID.String())
237+
238+
// ensure all profiles are there
239+
idExisting := make(map[uuid.UUID]int, tc.expectedNumRows)
240+
for i := range rows {
241+
_, ok := idExisting[rows[i].ID]
242+
assert.False(t, ok, "expected ID to not exists more than once")
243+
idExisting[rows[i].ID] = i
244+
}
245+
for i := 0; i < int(tc.expectedNumRows); i++ {
246+
id := uuid.MustParse(fmt.Sprintf("00000000-0000-0000-0000-%012d", i))
247+
_, ok := idExisting[id]
248+
assert.True(t, ok, fmt.Sprintf("expected ID %s to exist in output", id.String()))
249+
}
170250
})
171251
}
172252
}

pkg/phlaredb/profiles.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ type rowRangeWithSeriesIndex struct {
4141
type rowRangesWithSeriesIndex []rowRangeWithSeriesIndex
4242

4343
func (s rowRangesWithSeriesIndex) getSeriesIndex(rowNum int64) uint32 {
44-
// todo: binary search
4544
for _, rg := range s {
4645
// it is possible that the series is not existing
4746
if rg.rowRange == nil {

pkg/pprof/pprof.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,9 @@ func FromProfile(p *profile.Profile) (*profilev1.Profile, error) {
190190
r.Mapping = append(r.Mapping, &profilev1.Mapping{
191191
Id: m.ID,
192192
Filename: addString(strings, m.File),
193-
MemoryStart: (m.Start),
194-
MemoryLimit: (m.Limit),
195-
FileOffset: (m.Offset),
193+
MemoryStart: m.Start,
194+
MemoryLimit: m.Limit,
195+
FileOffset: m.Offset,
196196
BuildId: addString(strings, m.BuildID),
197197
HasFunctions: m.HasFunctions,
198198
HasFilenames: m.HasFilenames,

0 commit comments

Comments
 (0)