Skip to content
This repository was archived by the owner on Aug 23, 2023. It is now read-only.

Commit ff9c8e1

Browse files
authored
Merge pull request #1009 from grafana/find_random_corruptions
Find random corruptions
2 parents f94e836 + d6e6b05 commit ff9c8e1

File tree

1 file changed

+95
-2
lines changed

1 file changed

+95
-2
lines changed

mdata/cache/ccache_metric_test.go

+95-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ package cache
33
import (
44
"errors"
55
"fmt"
6+
"math/rand"
7+
"reflect"
68
"sort"
79
"testing"
10+
"time"
811

912
"github.com/grafana/metrictank/mdata/cache/accnt"
1013
"github.com/grafana/metrictank/mdata/chunk"
@@ -197,15 +200,101 @@ func TestCorruptionCase1(t *testing.T) {
197200
chunks := generateChunks(t, 10, 6, 10)
198201
ccm.AddRange(0, chunks[3:6])
199202
ccm.AddRange(0, chunks[0:4])
200-
if err := verifyCcm(ccm); err != nil {
203+
if err := verifyCcm(ccm, []uint32{10, 20, 30, 40, 50, 60}); err != nil {
201204
t.Fatal(err)
202205
}
203206
})
204207
}
205208

209+
func getRandomNumber(min, max int) int {
210+
return rand.Intn(max-min) + min
211+
}
212+
213+
// getRandomRange returns a range start-end so that
214+
// end >= start and both numbers drawn from [min, max)
215+
func getRandomRange(min, max int) (int, int) {
216+
number1 := getRandomNumber(min, max)
217+
number2 := getRandomNumber(min, max)
218+
if number1 > number2 {
219+
return number2, number1
220+
} else {
221+
return number1, number2
222+
}
223+
}
224+
225+
func TestCorruptionCase2(t *testing.T) {
226+
rand.Seed(time.Now().Unix())
227+
_, ccm := getCCM()
228+
iterations := 100000
229+
var cached [100]bool // tracks which chunks should be cached
230+
var expKeys []uint32 // tracks which keys should be in the CCM
231+
232+
// 100 chunks, first t0=10, last is t0=1000
233+
chunks := generateChunks(t, 10, 100, 10)
234+
235+
var opAdd, opAddRange, opDel, opDelRange int
236+
var adds, dels int
237+
238+
for i := 0; i < iterations; i++ {
239+
// 0 = Add
240+
// 1 = AddRange
241+
// 2 = Del
242+
// 3 = Del range (via multi del cals)
243+
action := getRandomNumber(0, 4)
244+
switch action {
245+
case 0:
246+
chunk := getRandomNumber(0, 100)
247+
t.Logf("adding chunk %d", chunk)
248+
ccm.Add(0, chunks[chunk])
249+
cached[chunk] = true
250+
opAdd++
251+
adds++
252+
case 1:
253+
from, to := getRandomRange(0, 100)
254+
t.Logf("adding range %d-%d", from, to)
255+
ccm.AddRange(0, chunks[from:to])
256+
for chunk := from; chunk < to; chunk++ {
257+
cached[chunk] = true
258+
}
259+
adds += (to - from)
260+
opAddRange++
261+
case 2:
262+
chunk := getRandomNumber(0, 100)
263+
t.Logf("deleting chunk %d", chunk)
264+
ccm.Del(chunks[chunk].Ts) // note: chunk may not exist
265+
cached[chunk] = false
266+
opDel++
267+
dels++
268+
case 3:
269+
from, to := getRandomRange(0, 100)
270+
t.Logf("deleting range %d-%d", from, to)
271+
for chunk := from; chunk < to; chunk++ {
272+
ccm.Del(chunks[chunk].Ts) // note: chunk may not exist
273+
cached[chunk] = false
274+
}
275+
opDelRange++
276+
dels += (to - from)
277+
}
278+
279+
expKeys = expKeys[:0]
280+
for i, c := range cached {
281+
if c {
282+
expKeys = append(expKeys, uint32((i+1)*10))
283+
}
284+
}
285+
286+
if err := verifyCcm(ccm, expKeys); err != nil {
287+
t.Fatal(err)
288+
}
289+
}
290+
291+
fmt.Printf("operations: add %d - addRange %d - del %d - delRange %d\n", opAdd, opAddRange, opDel, opDelRange)
292+
fmt.Printf("total chunk adds %d - total chunk deletes %d\n", adds, dels)
293+
}
294+
206295
// verifyCcm verifies the integrity of a CCacheMetric
207296
// it assumes that all itergens are span-aware
208-
func verifyCcm(ccm *CCacheMetric) error {
297+
func verifyCcm(ccm *CCacheMetric, expKeys []uint32) error {
209298
var chunk *CCacheChunk
210299
var ok bool
211300

@@ -217,6 +306,10 @@ func verifyCcm(ccm *CCacheMetric) error {
217306
return errors.New("keys are not sorted")
218307
}
219308

309+
if !reflect.DeepEqual(ccm.keys, expKeys) {
310+
return fmt.Errorf("keys mismatch. expected %v, got %v", expKeys, ccm.keys)
311+
}
312+
220313
for i, ts := range ccm.keys {
221314
if chunk, ok = ccm.chunks[ts]; !ok {
222315
return fmt.Errorf("Ts %d is in ccm.keys but not in ccm.chunks", ts)

0 commit comments

Comments
 (0)