339 lines
6.5 KiB
Go
339 lines
6.5 KiB
Go
package storage
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func TestKeyIndexGet(t *testing.T) {
|
|
// key: "foo"
|
|
// rev: 12
|
|
// generations:
|
|
// {empty}
|
|
// {8[1], 10[2], 12(t)[3]}
|
|
// {4[2], 6(t)[3]}
|
|
ki := newTestKeyIndex()
|
|
ki.compact(4, make(map[reversion]struct{}))
|
|
|
|
tests := []struct {
|
|
rev int64
|
|
|
|
wrev int64
|
|
werr error
|
|
}{
|
|
{13, 12, nil},
|
|
{13, 12, nil},
|
|
|
|
// get on generation 2
|
|
{12, 12, nil},
|
|
{11, 10, nil},
|
|
{10, 10, nil},
|
|
{9, 8, nil},
|
|
{8, 8, nil},
|
|
{7, 6, nil},
|
|
|
|
// get on generation 1
|
|
{6, 6, nil},
|
|
{5, 4, nil},
|
|
{4, 4, nil},
|
|
}
|
|
|
|
for i, tt := range tests {
|
|
rev, err := ki.get(tt.rev)
|
|
if err != tt.werr {
|
|
t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
|
|
}
|
|
if rev.main != tt.wrev {
|
|
t.Errorf("#%d: rev = %d, want %d", i, rev.main, tt.rev)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestKeyIndexPut(t *testing.T) {
|
|
ki := &keyIndex{key: []byte("foo")}
|
|
ki.put(5, 0)
|
|
|
|
wki := &keyIndex{
|
|
key: []byte("foo"),
|
|
rev: 5,
|
|
generations: []generation{{ver: 1, revs: []reversion{{main: 5}}}},
|
|
}
|
|
if !reflect.DeepEqual(ki, wki) {
|
|
t.Errorf("ki = %+v, want %+v", ki, wki)
|
|
}
|
|
|
|
ki.put(7, 0)
|
|
|
|
wki = &keyIndex{
|
|
key: []byte("foo"),
|
|
rev: 7,
|
|
generations: []generation{{ver: 2, revs: []reversion{{main: 5}, {main: 7}}}},
|
|
}
|
|
if !reflect.DeepEqual(ki, wki) {
|
|
t.Errorf("ki = %+v, want %+v", ki, wki)
|
|
}
|
|
}
|
|
|
|
func TestKeyIndexTombstone(t *testing.T) {
|
|
ki := &keyIndex{key: []byte("foo")}
|
|
ki.put(5, 0)
|
|
|
|
ki.tombstone(7, 0)
|
|
|
|
wki := &keyIndex{
|
|
key: []byte("foo"),
|
|
rev: 7,
|
|
generations: []generation{{ver: 2, revs: []reversion{{main: 5}, {main: 7}}}, {}},
|
|
}
|
|
if !reflect.DeepEqual(ki, wki) {
|
|
t.Errorf("ki = %+v, want %+v", ki, wki)
|
|
}
|
|
|
|
ki.put(8, 0)
|
|
ki.put(9, 0)
|
|
ki.tombstone(15, 0)
|
|
|
|
wki = &keyIndex{
|
|
key: []byte("foo"),
|
|
rev: 15,
|
|
generations: []generation{
|
|
{ver: 2, revs: []reversion{{main: 5}, {main: 7}}},
|
|
{ver: 3, revs: []reversion{{main: 8}, {main: 9}, {main: 15}}},
|
|
{},
|
|
},
|
|
}
|
|
if !reflect.DeepEqual(ki, wki) {
|
|
t.Errorf("ki = %+v, want %+v", ki, wki)
|
|
}
|
|
}
|
|
|
|
func TestKeyIndexCompact(t *testing.T) {
|
|
tests := []struct {
|
|
compact int64
|
|
|
|
wki *keyIndex
|
|
wam map[reversion]struct{}
|
|
}{
|
|
{
|
|
1,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
rev: 12,
|
|
generations: []generation{
|
|
{ver: 3, revs: []reversion{{main: 2}, {main: 4}, {main: 6}}},
|
|
{ver: 3, revs: []reversion{{main: 8}, {main: 10}, {main: 12}}},
|
|
{},
|
|
},
|
|
},
|
|
map[reversion]struct{}{},
|
|
},
|
|
{
|
|
2,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
rev: 12,
|
|
generations: []generation{
|
|
{ver: 3, revs: []reversion{{main: 2}, {main: 4}, {main: 6}}},
|
|
{ver: 3, revs: []reversion{{main: 8}, {main: 10}, {main: 12}}},
|
|
{},
|
|
},
|
|
},
|
|
map[reversion]struct{}{
|
|
reversion{main: 2}: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
3,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
rev: 12,
|
|
generations: []generation{
|
|
{ver: 3, revs: []reversion{{main: 2}, {main: 4}, {main: 6}}},
|
|
{ver: 3, revs: []reversion{{main: 8}, {main: 10}, {main: 12}}},
|
|
{},
|
|
},
|
|
},
|
|
map[reversion]struct{}{
|
|
reversion{main: 2}: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
4,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
rev: 12,
|
|
generations: []generation{
|
|
{ver: 3, revs: []reversion{{main: 4}, {main: 6}}},
|
|
{ver: 3, revs: []reversion{{main: 8}, {main: 10}, {main: 12}}},
|
|
{},
|
|
},
|
|
},
|
|
map[reversion]struct{}{
|
|
reversion{main: 4}: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
5,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
rev: 12,
|
|
generations: []generation{
|
|
{ver: 3, revs: []reversion{{main: 4}, {main: 6}}},
|
|
{ver: 3, revs: []reversion{{main: 8}, {main: 10}, {main: 12}}},
|
|
{},
|
|
},
|
|
},
|
|
map[reversion]struct{}{
|
|
reversion{main: 4}: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
6,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
rev: 12,
|
|
generations: []generation{
|
|
{ver: 3, revs: []reversion{{main: 8}, {main: 10}, {main: 12}}},
|
|
{},
|
|
},
|
|
},
|
|
map[reversion]struct{}{},
|
|
},
|
|
{
|
|
7,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
rev: 12,
|
|
generations: []generation{
|
|
{ver: 3, revs: []reversion{{main: 8}, {main: 10}, {main: 12}}},
|
|
{},
|
|
},
|
|
},
|
|
map[reversion]struct{}{},
|
|
},
|
|
{
|
|
8,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
rev: 12,
|
|
generations: []generation{
|
|
{ver: 3, revs: []reversion{{main: 8}, {main: 10}, {main: 12}}},
|
|
{},
|
|
},
|
|
},
|
|
map[reversion]struct{}{
|
|
reversion{main: 8}: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
9,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
rev: 12,
|
|
generations: []generation{
|
|
{ver: 3, revs: []reversion{{main: 8}, {main: 10}, {main: 12}}},
|
|
{},
|
|
},
|
|
},
|
|
map[reversion]struct{}{
|
|
reversion{main: 8}: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
10,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
rev: 12,
|
|
generations: []generation{
|
|
{ver: 3, revs: []reversion{{main: 10}, {main: 12}}},
|
|
{},
|
|
},
|
|
},
|
|
map[reversion]struct{}{
|
|
reversion{main: 10}: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
11,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
rev: 12,
|
|
generations: []generation{
|
|
{ver: 3, revs: []reversion{{main: 10}, {main: 12}}},
|
|
{},
|
|
},
|
|
},
|
|
map[reversion]struct{}{
|
|
reversion{main: 10}: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
12,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
rev: 12,
|
|
generations: []generation{{}},
|
|
},
|
|
map[reversion]struct{}{},
|
|
},
|
|
}
|
|
|
|
// Continous Compaction
|
|
ki := newTestKeyIndex()
|
|
for i, tt := range tests {
|
|
am := make(map[reversion]struct{})
|
|
ki.compact(tt.compact, am)
|
|
if !reflect.DeepEqual(ki, tt.wki) {
|
|
t.Errorf("#%d: ki = %+v, want %+v", i, ki, tt.wki)
|
|
}
|
|
if !reflect.DeepEqual(am, tt.wam) {
|
|
t.Errorf("#%d: am = %+v, want %+v", i, am, tt.wam)
|
|
}
|
|
}
|
|
|
|
// Jump Compaction
|
|
for i, tt := range tests {
|
|
if (i%2 == 0 && i < 6) && (i%2 == 1 && i > 6) {
|
|
am := make(map[reversion]struct{})
|
|
ki.compact(tt.compact, am)
|
|
if !reflect.DeepEqual(ki, tt.wki) {
|
|
t.Errorf("#%d: ki = %+v, want %+v", i, ki, tt.wki)
|
|
}
|
|
if !reflect.DeepEqual(am, tt.wam) {
|
|
t.Errorf("#%d: am = %+v, want %+v", am, tt.wam)
|
|
}
|
|
}
|
|
}
|
|
|
|
// OnceCompaction
|
|
for i, tt := range tests {
|
|
ki := newTestKeyIndex()
|
|
am := make(map[reversion]struct{})
|
|
ki.compact(tt.compact, am)
|
|
if !reflect.DeepEqual(ki, tt.wki) {
|
|
t.Errorf("#%d: ki = %+v, want %+v", i, ki, tt.wki)
|
|
}
|
|
if !reflect.DeepEqual(am, tt.wam) {
|
|
t.Errorf("#%d: am = %+v, want %+v", i, am, tt.wam)
|
|
}
|
|
}
|
|
}
|
|
|
|
func newTestKeyIndex() *keyIndex {
|
|
// key: "foo"
|
|
// rev: 12
|
|
// generations:
|
|
// {empty}
|
|
// {8[1], 10[2], 12(t)[3]}
|
|
// {2[1], 4[2], 6(t)[3]}
|
|
|
|
ki := &keyIndex{key: []byte("foo")}
|
|
ki.put(2, 0)
|
|
ki.put(4, 0)
|
|
ki.tombstone(6, 0)
|
|
ki.put(8, 0)
|
|
ki.put(10, 0)
|
|
ki.tombstone(12, 0)
|
|
return ki
|
|
}
|