@@ -3,8 +3,11 @@ package cache
3
3
import (
4
4
"errors"
5
5
"fmt"
6
+ "math/rand"
7
+ "reflect"
6
8
"sort"
7
9
"testing"
10
+ "time"
8
11
9
12
"github.com/grafana/metrictank/mdata/cache/accnt"
10
13
"github.com/grafana/metrictank/mdata/chunk"
@@ -197,15 +200,101 @@ func TestCorruptionCase1(t *testing.T) {
197
200
chunks := generateChunks (t , 10 , 6 , 10 )
198
201
ccm .AddRange (0 , chunks [3 :6 ])
199
202
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 {
201
204
t .Fatal (err )
202
205
}
203
206
})
204
207
}
205
208
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
+
206
295
// verifyCcm verifies the integrity of a CCacheMetric
207
296
// it assumes that all itergens are span-aware
208
- func verifyCcm (ccm * CCacheMetric ) error {
297
+ func verifyCcm (ccm * CCacheMetric , expKeys [] uint32 ) error {
209
298
var chunk * CCacheChunk
210
299
var ok bool
211
300
@@ -217,6 +306,10 @@ func verifyCcm(ccm *CCacheMetric) error {
217
306
return errors .New ("keys are not sorted" )
218
307
}
219
308
309
+ if ! reflect .DeepEqual (ccm .keys , expKeys ) {
310
+ return fmt .Errorf ("keys mismatch. expected %v, got %v" , expKeys , ccm .keys )
311
+ }
312
+
220
313
for i , ts := range ccm .keys {
221
314
if chunk , ok = ccm .chunks [ts ]; ! ok {
222
315
return fmt .Errorf ("Ts %d is in ccm.keys but not in ccm.chunks" , ts )
0 commit comments