zrepl/pruning/retentiongrid/retentiongrid_test.go

162 lines
4.2 KiB
Go
Raw Normal View History

2018-08-26 19:20:08 +02:00
package retentiongrid
2017-06-21 20:29:20 +02:00
import (
"fmt"
"strconv"
"strings"
"testing"
"time"
2019-03-22 19:41:12 +01:00
"github.com/stretchr/testify/assert"
2017-06-21 20:29:20 +02:00
)
2018-08-26 19:20:08 +02:00
type retentionIntervalStub struct {
length time.Duration
keepCount int
}
func (i *retentionIntervalStub) Length() time.Duration {
return i.length
}
func (i *retentionIntervalStub) KeepCount() int {
return i.keepCount
}
2018-09-24 17:30:03 +02:00
func gridFromString(gs string) (g *Grid) {
2017-06-21 20:29:20 +02:00
intervals := strings.Split(gs, "|")
2018-09-24 17:30:03 +02:00
g = &Grid{
intervals: make([]Interval, len(intervals)),
2017-06-21 20:29:20 +02:00
}
for idx, i := range intervals {
comps := strings.SplitN(i, ",", 2)
var durationStr, numSnapsStr string
durationStr = comps[0]
if len(comps) == 1 {
numSnapsStr = "1"
} else {
numSnapsStr = comps[1]
}
var err error
2018-08-26 19:20:08 +02:00
var interval retentionIntervalStub
2017-06-21 20:29:20 +02:00
2018-08-26 19:20:08 +02:00
if interval.keepCount, err = strconv.Atoi(numSnapsStr); err != nil {
2017-06-21 20:29:20 +02:00
panic(err)
}
2018-08-26 19:20:08 +02:00
if interval.length, err = time.ParseDuration(durationStr); err != nil {
2017-06-21 20:29:20 +02:00
panic(err)
}
2018-08-26 19:20:08 +02:00
g.intervals[idx] = &interval
2017-06-21 20:29:20 +02:00
}
return
}
type dummySnap struct {
Name string
ShouldKeep bool
date time.Time
}
func (ds dummySnap) Date() time.Time {
return ds.date
}
2018-09-24 17:30:03 +02:00
func (ds dummySnap) LessThan(b Entry) bool {
2017-06-21 20:29:20 +02:00
return ds.date.Before(b.(dummySnap).date) // don't have a txg here
}
2018-09-24 17:30:03 +02:00
func validateRetentionGridFitEntries(t *testing.T, now time.Time, input, keep, remove []Entry) {
2017-06-21 20:29:20 +02:00
snapDescr := func(d dummySnap) string {
return fmt.Sprintf("%s@%s", d.Name, d.date.Sub(now))
}
t.Logf("keep list:\n")
for k := range keep {
t.Logf("\t%s\n", snapDescr(keep[k].(dummySnap)))
}
t.Logf("remove list:\n")
for k := range remove {
t.Logf("\t%s\n", snapDescr(remove[k].(dummySnap)))
}
t.Logf("\n\n")
for _, s := range input {
d := s.(dummySnap)
descr := snapDescr(d)
t.Logf("testing %s\n", descr)
if d.ShouldKeep {
assert.Contains(t, keep, d, "expecting %s to be kept", descr)
} else {
assert.Contains(t, remove, d, "expecting %s to be removed", descr)
}
}
t.Logf("resulting list:\n")
for k := range keep {
t.Logf("\t%s\n", snapDescr(keep[k].(dummySnap)))
}
}
func TestRetentionGridFitEntriesEmptyInput(t *testing.T) {
2018-09-24 17:30:03 +02:00
g := gridFromString("10m|10m|10m|1h")
keep, remove := g.FitEntries(time.Now(), []Entry{})
2017-06-21 20:29:20 +02:00
assert.Empty(t, keep)
assert.Empty(t, remove)
}
func TestRetentionGridFitEntriesIntervalBoundariesAndAlignment(t *testing.T) {
// Intervals are (duration], i.e. 10min is in the first interval, not in the second
2018-09-24 17:30:03 +02:00
g := gridFromString("10m|10m|10m")
2017-06-21 20:29:20 +02:00
t.Logf("%#v\n", g)
now := time.Unix(0, 0)
2018-09-24 17:30:03 +02:00
snaps := []Entry{
2017-06-21 20:29:20 +02:00
dummySnap{"0", true, now.Add(1 * time.Minute)}, // before now
dummySnap{"1", true, now}, // before now
dummySnap{"2", true, now.Add(-10 * time.Minute)}, // 1st interval
dummySnap{"3", true, now.Add(-20 * time.Minute)}, // 2nd interval
dummySnap{"4", true, now.Add(-30 * time.Minute)}, // 3rd interval
dummySnap{"5", false, now.Add(-40 * time.Minute)}, // after last interval
}
keep, remove := g.FitEntries(now, snaps)
validateRetentionGridFitEntries(t, now, snaps, keep, remove)
}
func TestRetentionGridFitEntries(t *testing.T) {
2018-09-24 17:30:03 +02:00
g := gridFromString("10m,-1|10m|10m,2|1h")
2017-06-21 20:29:20 +02:00
t.Logf("%#v\n", g)
now := time.Unix(0, 0)
2018-09-24 17:30:03 +02:00
snaps := []Entry{
2017-06-21 20:29:20 +02:00
dummySnap{"1", true, now.Add(3 * time.Minute)}, // pre-now must always be kept
dummySnap{"b1", true, now.Add(-6 * time.Minute)}, // 1st interval allows unlimited entries
dummySnap{"b3", true, now.Add(-8 * time.Minute)}, // 1st interval allows unlimited entries
dummySnap{"b2", true, now.Add(-9 * time.Minute)}, // 1st interval allows unlimited entries
dummySnap{"a", false, now.Add(-11 * time.Minute)},
dummySnap{"c", true, now.Add(-19 * time.Minute)}, // 2nd interval allows 1 entry
dummySnap{"foo", false, now.Add(-25 * time.Minute)},
dummySnap{"bar", true, now.Add(-26 * time.Minute)}, // 3rd interval allows 2 entries
dummySnap{"border", true, now.Add(-30 * time.Minute)},
dummySnap{"d", true, now.Add(-1*time.Hour - 15*time.Minute)},
dummySnap{"e", false, now.Add(-1*time.Hour - 31*time.Minute)}, // before earliest interval must always be deleted
dummySnap{"f", false, now.Add(-2 * time.Hour)},
}
keep, remove := g.FitEntries(now, snaps)
validateRetentionGridFitEntries(t, now, snaps, keep, remove)
}