github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/storage/segment/segment_test.go (about) 1 package segment 2 3 import ( 4 "bufio" 5 "log" 6 "math/big" 7 "math/rand" 8 "os" 9 "strconv" 10 "strings" 11 "time" 12 13 . "github.com/onsi/ginkgo/v2" 14 . "github.com/onsi/gomega" 15 16 "github.com/pyroscope-io/pyroscope/pkg/testing" 17 ) 18 19 var putNoOp = func(depth int, t time.Time, r *big.Rat, addons []Addon) {} 20 21 func doGet(s *Segment, st, et time.Time) []time.Time { 22 res := []time.Time{} 23 s.Get(st, et, func(d int, samples, writes uint64, t time.Time, r *big.Rat) { 24 res = append(res, t) 25 }) 26 return res 27 } 28 29 func strip(val string) string { 30 ret := "" 31 scanner := bufio.NewScanner(strings.NewReader(val)) 32 for scanner.Scan() { 33 line := strings.TrimSpace(scanner.Text()) 34 if len(line) > 0 { 35 ret += line + "\n" 36 } 37 } 38 return ret 39 } 40 41 func expectChildrenSamplesAddUpToParentSamples(tn *streeNode) { 42 childrenSum := uint64(0) 43 if len(tn.children) == 0 { 44 return 45 } 46 for _, v := range tn.children { 47 if v != nil { 48 expectChildrenSamplesAddUpToParentSamples(v) 49 childrenSum += v.samples 50 } 51 } 52 Expect(childrenSum).To(Equal(tn.samples)) 53 } 54 55 var _ = Describe("stree", func() { 56 Context("Get", func() { 57 Context("When there's no root", func() { 58 It("get doesn't fail", func() { 59 s := New() 60 Expect(doGet(s, testing.SimpleTime(0), testing.SimpleTime(39))).To(HaveLen(0)) 61 }) 62 }) 63 }) 64 65 Context("StartTime", func() { 66 Context("empty segment", func() { 67 It("returns zero time", func() { 68 s := New() 69 Expect(s.StartTime().IsZero()).To(BeTrue()) 70 }) 71 }) 72 73 Context("fuzz test", func() { 74 It("always returns the right values", func() { 75 r := rand.New(rand.NewSource(6231912)) 76 77 // doesn't work with minTime = 0 78 minTime := 1023886146 79 maxTime := 1623886146 80 81 runs := 100 82 maxInsertionsPerTree := 100 83 84 for i := 0; i < runs; i++ { 85 s := New() 86 minSt := maxTime 87 for j := 0; j < 1+r.Intn(maxInsertionsPerTree); j++ { 88 st := (minTime + r.Intn(maxTime-minTime)) / 10 * 10 89 if st < minSt { 90 minSt = st 91 } 92 et := st + 10 + r.Intn(1000) 93 s.Put(testing.SimpleTime(st), testing.SimpleTime(et), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 94 } 95 96 Expect(s.StartTime()).To(Equal(testing.SimpleTime(minSt))) 97 } 98 }) 99 }) 100 }) 101 102 Context("DeleteDataBefore", func() { 103 Context("empty segment", func() { 104 It("returns true and no keys", func() { 105 s := New() 106 107 keys := []string{} 108 rp := &RetentionPolicy{AbsoluteTime: testing.SimpleTime(19)} 109 r, _ := s.WalkNodesToDelete(rp, func(depth int, t time.Time) error { 110 keys = append(keys, strconv.Itoa(depth)+":"+strconv.Itoa(int(t.Unix()))) 111 return nil 112 }) 113 114 Expect(r).To(BeTrue()) 115 Expect(keys).To(BeEmpty()) 116 }) 117 }) 118 119 Context("simple test 1", func() { 120 It("correctly deletes data", func() { 121 s := New() 122 s.Put(testing.SimpleUTime(10), testing.SimpleUTime(19), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 123 s.Put(testing.SimpleUTime(20), testing.SimpleUTime(29), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 124 125 keys := []string{} 126 rp := &RetentionPolicy{AbsoluteTime: testing.SimpleUTime(21)} 127 r, _ := s.WalkNodesToDelete(rp, func(depth int, t time.Time) error { 128 keys = append(keys, strconv.Itoa(depth)+":"+strconv.Itoa(int(t.Unix()))) 129 return nil 130 }) 131 132 Expect(r).To(BeFalse()) 133 Expect(keys).To(ConsistOf([]string{ 134 "0:10", 135 })) 136 }) 137 }) 138 139 Context("simple test 3", func() { 140 It("correctly deletes data", func() { 141 s := New() 142 s.Put(testing.SimpleUTime(10), testing.SimpleUTime(19), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 143 s.Put(testing.SimpleUTime(1020), testing.SimpleUTime(1029), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 144 145 keys := []string{} 146 rp := &RetentionPolicy{AbsoluteTime: testing.SimpleUTime(21)} 147 r, _ := s.WalkNodesToDelete(rp, func(depth int, t time.Time) error { 148 keys = append(keys, strconv.Itoa(depth)+":"+strconv.Itoa(int(t.Unix()))) 149 return nil 150 }) 151 152 Expect(r).To(BeFalse()) 153 Expect(keys).To(ConsistOf([]string{ 154 "0:10", 155 })) 156 }) 157 }) 158 159 Context("simple test 2", func() { 160 It("correctly deletes data", func() { 161 s := New() 162 s.Put(testing.SimpleUTime(10), testing.SimpleUTime(19), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 163 s.Put(testing.SimpleUTime(20), testing.SimpleUTime(29), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 164 165 keys := []string{} 166 rp := &RetentionPolicy{AbsoluteTime: testing.SimpleUTime(200)} 167 r, _ := s.WalkNodesToDelete(rp, func(depth int, t time.Time) error { 168 keys = append(keys, strconv.Itoa(depth)+":"+strconv.Itoa(int(t.Unix()))) 169 return nil 170 }) 171 172 Expect(r).To(BeTrue()) 173 Expect(keys).To(ConsistOf([]string{ 174 "1:0", 175 "0:10", 176 "0:20", 177 })) 178 }) 179 }) 180 181 Context("level-based retention", func() { 182 It("correctly deletes data partially", func() { 183 s := New() 184 s.Put(testing.SimpleUTime(10), testing.SimpleUTime(19), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 185 s.Put(testing.SimpleUTime(20), testing.SimpleUTime(29), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 186 187 keys := []string{} 188 rp := &RetentionPolicy{Levels: map[int]time.Time{0: time.Now()}} 189 r, _ := s.WalkNodesToDelete(rp, func(depth int, t time.Time) error { 190 keys = append(keys, strconv.Itoa(depth)+":"+strconv.Itoa(int(t.Unix()))) 191 return nil 192 }) 193 194 Expect(r).To(BeFalse()) 195 Expect(s.root).ToNot(BeNil()) 196 Expect(keys).To(ConsistOf([]string{ 197 "0:10", 198 "0:20", 199 })) 200 201 removed, err := s.DeleteNodesBefore(rp) 202 Expect(err).ToNot(HaveOccurred()) 203 Expect(removed).To(BeFalse()) 204 }) 205 206 It("correctly deletes data completely", func() { 207 s := New() 208 s.Put(testing.SimpleUTime(10), testing.SimpleUTime(19), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 209 s.Put(testing.SimpleUTime(20), testing.SimpleUTime(29), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 210 211 var keys []string 212 rp := &RetentionPolicy{Levels: map[int]time.Time{0: time.Now(), 1: time.Now()}} 213 r, _ := s.WalkNodesToDelete(rp, func(depth int, t time.Time) error { 214 keys = append(keys, strconv.Itoa(depth)+":"+strconv.Itoa(int(t.Unix()))) 215 return nil 216 }) 217 218 Expect(r).To(BeTrue()) 219 Expect(keys).To(ConsistOf([]string{ 220 "1:0", 221 "0:10", 222 "0:20", 223 })) 224 225 removed, err := s.DeleteNodesBefore(rp) 226 Expect(err).ToNot(HaveOccurred()) 227 Expect(removed).To(BeTrue()) 228 }) 229 230 Context("Issue 715", func() { 231 // See https://github.com/pyroscope-io/pyroscope/issues/715 232 It("does not return nodes affected by retention policy", func() { 233 b, err := os.Open("testdata/issue_715") 234 Expect(err).ToNot(HaveOccurred()) 235 s, err := Deserialize(b) 236 Expect(err).ToNot(HaveOccurred()) 237 238 var keys []string 239 st := time.Date(2022, time.January, 12, 9, 40, 0, 0, time.UTC) 240 et := time.Date(2022, time.January, 12, 10, 40, 0, 0, time.UTC) 241 s.Get(st, et, func(depth int, samples, writes uint64, t time.Time, r *big.Rat) { 242 keys = append(keys, strconv.Itoa(depth)+":"+strconv.Itoa(int(t.Unix()))+":"+r.String()) 243 }) 244 245 Expect(keys).To(BeEmpty()) 246 }) 247 248 It("correctly samples data", func() { 249 s := New() 250 st := time.Date(2021, time.December, 1, 0, 0, 0, 0, time.UTC) 251 et := time.Date(2022, time.January, 1, 0, 0, 0, 0, time.UTC) 252 rp := &RetentionPolicy{AbsoluteTime: et} 253 254 c := st 255 for c.Before(et) { 256 e := c.Add(time.Second * time.Duration(10)) 257 err := s.Put(c, e, 100, func(int, time.Time, *big.Rat, []Addon) {}) 258 Expect(err).ToNot(HaveOccurred()) 259 c = e 260 } 261 262 r, err := s.DeleteNodesBefore(rp) 263 Expect(r).To(BeFalse()) 264 Expect(err).ToNot(HaveOccurred()) 265 266 gSt := st.Add(-time.Hour) 267 gEt := et.Add(time.Hour) 268 269 var keys []string 270 s.Get(gSt, gEt, func(depth int, samples, writes uint64, t time.Time, r *big.Rat) { 271 keys = append(keys, strconv.Itoa(depth)+":"+strconv.Itoa(int(t.Unix()))+":"+r.String()) 272 }) 273 274 Expect(keys).To(BeEmpty()) 275 }) 276 277 It("correctly samples data with level retention period", func() { 278 s := New() 279 st := time.Date(2021, time.December, 1, 0, 0, 0, 0, time.UTC) 280 et := time.Date(2021, time.December, 2, 0, 0, 0, 0, time.UTC) 281 282 c := st 283 for c.Before(et) { 284 e := c.Add(time.Second * time.Duration(10)) 285 err := s.Put(c, e, 100, func(int, time.Time, *big.Rat, []Addon) {}) 286 Expect(err).ToNot(HaveOccurred()) 287 c = e 288 } 289 290 r, err := s.DeleteNodesBefore(&RetentionPolicy{Levels: map[int]time.Time{0: et}}) 291 Expect(r).To(BeFalse()) 292 Expect(err).ToNot(HaveOccurred()) 293 294 gSt := time.Date(2021, time.December, 1, 10, 0, 0, 0, time.UTC) 295 gEt := gSt.Add(time.Second * 30) 296 297 var keys []string 298 s.Get(gSt, gEt, func(depth int, samples, writes uint64, t time.Time, r *big.Rat) { 299 keys = append(keys, strconv.Itoa(depth)+":"+strconv.Itoa(int(t.Unix()))+":"+r.String()) 300 }) 301 302 Expect(keys).To(ConsistOf([]string{ 303 "1:1638352800:3/10", 304 })) 305 }) 306 }) 307 }) 308 }) 309 310 Context("Put", func() { 311 Context("When inserts are far apart", func() { 312 Context("When second insert is far in the future", func() { 313 It("sets root properly", func() { 314 log.Println("---") 315 s := New() 316 s.Put(testing.SimpleTime(1330), 317 testing.SimpleTime(1339), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 318 Expect(s.root).ToNot(BeNil()) 319 Expect(s.root.depth).To(Equal(0)) 320 s.Put(testing.SimpleTime(1110), 321 testing.SimpleTime(1119), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 322 expectChildrenSamplesAddUpToParentSamples(s.root) 323 }) 324 }) 325 Context("When second insert is far in the past", func() { 326 It("sets root properly", func() { 327 log.Println("---") 328 s := New() 329 s.Put(testing.SimpleTime(2030), 330 testing.SimpleTime(2039), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 331 Expect(s.root).ToNot(BeNil()) 332 Expect(s.root.depth).To(Equal(0)) 333 s.Put(testing.SimpleTime(0), 334 testing.SimpleTime(9), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 335 expectChildrenSamplesAddUpToParentSamples(s.root) 336 }) 337 }) 338 }) 339 340 Context("When empty", func() { 341 It("sets root properly", func() { 342 s := New() 343 s.Put(testing.SimpleTime(0), 344 testing.SimpleTime(9), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 345 Expect(s.root).ToNot(BeNil()) 346 Expect(s.root.depth).To(Equal(0)) 347 }) 348 349 It("sets root properly", func() { 350 s := New() 351 s.Put(testing.SimpleTime(0), 352 testing.SimpleTime(49), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 353 Expect(s.root).ToNot(BeNil()) 354 Expect(s.root.depth).To(Equal(1)) 355 }) 356 357 It("sets root properly", func() { 358 s := New() 359 s.Put(testing.SimpleTime(10), 360 testing.SimpleTime(109), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 361 Expect(s.root).ToNot(BeNil()) 362 Expect(s.root.depth).To(Equal(2)) 363 }) 364 365 It("sets root properly", func() { 366 s := New() 367 s.Put(testing.SimpleTime(10), 368 testing.SimpleTime(19), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 369 Expect(s.root).ToNot(BeNil()) 370 Expect(s.root.depth).To(Equal(0)) 371 s.Put(testing.SimpleTime(10), 372 testing.SimpleTime(19), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 373 expectChildrenSamplesAddUpToParentSamples(s.root) 374 }) 375 376 It("sets root properly", func() { 377 s := New() 378 s.Put(testing.SimpleTime(10), 379 testing.SimpleTime(19), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 380 Expect(s.root).ToNot(BeNil()) 381 Expect(s.root.depth).To(Equal(0)) 382 s.Put(testing.SimpleTime(20), 383 testing.SimpleTime(29), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 384 Expect(s.root).ToNot(BeNil()) 385 Expect(s.root.depth).To(Equal(1)) 386 expectChildrenSamplesAddUpToParentSamples(s.root) 387 }) 388 389 It("sets root properly", func() { 390 s := New() 391 s.Put(testing.SimpleTime(10), 392 testing.SimpleTime(19), 10, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 393 Expect(s.root).ToNot(BeNil()) 394 Expect(s.root.depth).To(Equal(0)) 395 s.Put(testing.SimpleTime(20), 396 testing.SimpleTime(39), 10, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 397 Expect(s.root).ToNot(BeNil()) 398 Expect(s.root.depth).To(Equal(1)) 399 expectChildrenSamplesAddUpToParentSamples(s.root) 400 }) 401 402 It("sets root properly", func() { 403 s := New() 404 s.Put(testing.SimpleTime(10), 405 testing.SimpleTime(19), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 406 Expect(s.root).ToNot(BeNil()) 407 Expect(s.root.depth).To(Equal(0)) 408 409 s.Put(testing.SimpleTime(20), 410 testing.SimpleTime(29), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 411 Expect(s.root).ToNot(BeNil()) 412 Expect(s.root.depth).To(Equal(1)) 413 414 s.Put(testing.SimpleTime(30), 415 testing.SimpleTime(39), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 416 Expect(s.root).ToNot(BeNil()) 417 Expect(s.root.depth).To(Equal(1)) 418 expectChildrenSamplesAddUpToParentSamples(s.root) 419 }) 420 421 It("sets root properly", func() { 422 s := New() 423 s.Put(testing.SimpleTime(30), 424 testing.SimpleTime(39), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 425 Expect(s.root).ToNot(BeNil()) 426 Expect(s.root.depth).To(Equal(0)) 427 428 s.Put(testing.SimpleTime(20), 429 testing.SimpleTime(29), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 430 Expect(s.root).ToNot(BeNil()) 431 Expect(s.root.depth).To(Equal(1)) 432 433 s.Put(testing.SimpleTime(10), 434 testing.SimpleTime(19), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 435 Expect(s.root).ToNot(BeNil()) 436 Expect(s.root.depth).To(Equal(1)) 437 438 Expect(doGet(s, testing.SimpleTime(0), testing.SimpleTime(39))).To(HaveLen(3)) 439 }) 440 441 It("works with 3 mins", func() { 442 s := New() 443 s.Put(testing.SimpleTime(10), 444 testing.SimpleTime(70), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 445 Expect(s.root).ToNot(BeNil()) 446 Expect(s.root.depth).To(Equal(1)) 447 // Expect(doGet(s, testing.SimpleTime(20, testing.SimpleTime(49))).To(HaveLen(3)) 448 }) 449 450 It("sets trie properly, gets work", func() { 451 s := New() 452 453 s.Put(testing.SimpleTime(0), 454 testing.SimpleTime(9), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 455 Expect(s.root).ToNot(BeNil()) 456 Expect(s.root.depth).To(Equal(0)) 457 458 s.Put(testing.SimpleTime(100), 459 testing.SimpleTime(109), 1, func(de int, t time.Time, r *big.Rat, a []Addon) {}) 460 expectChildrenSamplesAddUpToParentSamples(s.root) 461 Expect(s.root).ToNot(BeNil()) 462 Expect(s.root.depth).To(Equal(2)) 463 Expect(s.root.present).To(BeTrue()) 464 Expect(s.root.children[0]).ToNot(BeNil()) 465 Expect(s.root.children[0].present).ToNot(BeTrue()) 466 Expect(s.root.children[1]).ToNot(BeNil()) 467 Expect(s.root.children[1].present).ToNot(BeTrue()) 468 Expect(s.root.children[0].children[0].present).To(BeTrue()) 469 Expect(s.root.children[1].children[0].present).To(BeTrue()) 470 471 Expect(doGet(s, testing.SimpleTime(0), testing.SimpleTime(9))).To(HaveLen(1)) 472 Expect(doGet(s, testing.SimpleTime(10), testing.SimpleTime(19))).To(HaveLen(0)) 473 Expect(doGet(s, testing.SimpleTime(100), testing.SimpleTime(109))).To(HaveLen(1)) 474 Expect(doGet(s, testing.SimpleTime(0), testing.SimpleTime(109))).To(HaveLen(2)) 475 Expect(doGet(s, testing.SimpleTime(0), testing.SimpleTime(999))).To(HaveLen(1)) 476 Expect(doGet(s, testing.SimpleTime(0), testing.SimpleTime(1000))).To(HaveLen(1)) 477 Expect(doGet(s, testing.SimpleTime(0), testing.SimpleTime(1001))).To(HaveLen(1)) 478 Expect(doGet(s, testing.SimpleTime(0), testing.SimpleTime(989))).To(HaveLen(2)) 479 }) 480 }) 481 }) 482 })