mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
365 lines
6.8 KiB
Go
365 lines
6.8 KiB
Go
package storage
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func TestKeyIndexGet(t *testing.T) {
|
|
// key: "foo"
|
|
// index: 12
|
|
// generations:
|
|
// {empty}
|
|
// {8[1], 10[2], 12(t)[3]}
|
|
// {4[2], 6(t)[3]}
|
|
ki := newTestKeyIndex()
|
|
ki.compact(4, make(map[uint64]struct{}))
|
|
|
|
tests := []struct {
|
|
index uint64
|
|
|
|
windex uint64
|
|
werr error
|
|
}{
|
|
// expected not exist on an index that is greater than the last tombstone
|
|
{13, 0, ErrIndexNotFound},
|
|
{13, 0, ErrIndexNotFound},
|
|
|
|
// get on generation 2
|
|
{12, 12, nil},
|
|
{11, 10, nil},
|
|
{10, 10, nil},
|
|
{9, 8, nil},
|
|
{8, 8, nil},
|
|
{7, 0, ErrIndexNotFound},
|
|
|
|
// get on generation 1
|
|
{6, 6, nil},
|
|
{5, 4, nil},
|
|
{4, 4, nil},
|
|
}
|
|
|
|
for i, tt := range tests {
|
|
index, err := ki.get(tt.index)
|
|
if err != tt.werr {
|
|
t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
|
|
}
|
|
if index != tt.windex {
|
|
t.Errorf("#%d: index = %d, want %d", i, index, tt.index)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestKeyIndexPut(t *testing.T) {
|
|
ki := &keyIndex{key: []byte("foo")}
|
|
ki.put(5)
|
|
|
|
wki := &keyIndex{
|
|
key: []byte("foo"),
|
|
index: 5,
|
|
generations: []generation{{ver: 1, cont: []uint64{5}}},
|
|
}
|
|
if !reflect.DeepEqual(ki, wki) {
|
|
t.Errorf("ki = %+v, want %+v", ki, wki)
|
|
}
|
|
|
|
ki.put(7)
|
|
|
|
wki = &keyIndex{
|
|
key: []byte("foo"),
|
|
index: 7,
|
|
generations: []generation{{ver: 2, cont: []uint64{5, 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)
|
|
|
|
ki.tombstone(7)
|
|
|
|
wki := &keyIndex{
|
|
key: []byte("foo"),
|
|
index: 7,
|
|
generations: []generation{{ver: 2, cont: []uint64{5, 7}}, {}},
|
|
}
|
|
if !reflect.DeepEqual(ki, wki) {
|
|
t.Errorf("ki = %+v, want %+v", ki, wki)
|
|
}
|
|
|
|
ki.put(8)
|
|
ki.put(9)
|
|
ki.tombstone(15)
|
|
|
|
wki = &keyIndex{
|
|
key: []byte("foo"),
|
|
index: 15,
|
|
generations: []generation{{ver: 2, cont: []uint64{5, 7}}, {ver: 3, cont: []uint64{8, 9, 15}}, {}},
|
|
}
|
|
if !reflect.DeepEqual(ki, wki) {
|
|
t.Errorf("ki = %+v, want %+v", ki, wki)
|
|
}
|
|
}
|
|
|
|
func TestKeyIndexCompact(t *testing.T) {
|
|
tests := []struct {
|
|
compact uint64
|
|
|
|
wki *keyIndex
|
|
wam map[uint64]struct{}
|
|
}{
|
|
{
|
|
1,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
index: 12,
|
|
generations: []generation{
|
|
{ver: 3, cont: []uint64{2, 4, 6}},
|
|
{ver: 3, cont: []uint64{8, 10, 12}},
|
|
{},
|
|
},
|
|
},
|
|
map[uint64]struct{}{
|
|
2: struct{}{}, 4: struct{}{}, 6: struct{}{},
|
|
8: struct{}{}, 10: struct{}{}, 12: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
2,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
index: 12,
|
|
generations: []generation{
|
|
{ver: 3, cont: []uint64{2, 4, 6}},
|
|
{ver: 3, cont: []uint64{8, 10, 12}},
|
|
{},
|
|
},
|
|
},
|
|
map[uint64]struct{}{
|
|
2: struct{}{}, 4: struct{}{}, 6: struct{}{},
|
|
8: struct{}{}, 10: struct{}{}, 12: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
3,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
index: 12,
|
|
generations: []generation{
|
|
{ver: 3, cont: []uint64{2, 4, 6}},
|
|
{ver: 3, cont: []uint64{8, 10, 12}},
|
|
{},
|
|
},
|
|
},
|
|
map[uint64]struct{}{
|
|
2: struct{}{}, 4: struct{}{}, 6: struct{}{},
|
|
8: struct{}{}, 10: struct{}{}, 12: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
4,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
index: 12,
|
|
generations: []generation{
|
|
{ver: 3, cont: []uint64{4, 6}},
|
|
{ver: 3, cont: []uint64{8, 10, 12}},
|
|
{},
|
|
},
|
|
},
|
|
map[uint64]struct{}{
|
|
4: struct{}{}, 6: struct{}{},
|
|
8: struct{}{}, 10: struct{}{}, 12: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
5,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
index: 12,
|
|
generations: []generation{
|
|
{ver: 3, cont: []uint64{4, 6}},
|
|
{ver: 3, cont: []uint64{8, 10, 12}},
|
|
{},
|
|
},
|
|
},
|
|
map[uint64]struct{}{
|
|
4: struct{}{}, 6: struct{}{},
|
|
8: struct{}{}, 10: struct{}{}, 12: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
6,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
index: 12,
|
|
generations: []generation{
|
|
{ver: 3, cont: []uint64{6}},
|
|
{ver: 3, cont: []uint64{8, 10, 12}},
|
|
{},
|
|
},
|
|
},
|
|
map[uint64]struct{}{
|
|
6: struct{}{},
|
|
8: struct{}{}, 10: struct{}{}, 12: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
7,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
index: 12,
|
|
generations: []generation{
|
|
{ver: 3, cont: []uint64{8, 10, 12}},
|
|
{},
|
|
},
|
|
},
|
|
map[uint64]struct{}{
|
|
8: struct{}{}, 10: struct{}{}, 12: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
8,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
index: 12,
|
|
generations: []generation{
|
|
{ver: 3, cont: []uint64{8, 10, 12}},
|
|
{},
|
|
},
|
|
},
|
|
map[uint64]struct{}{
|
|
8: struct{}{}, 10: struct{}{}, 12: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
9,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
index: 12,
|
|
generations: []generation{
|
|
{ver: 3, cont: []uint64{8, 10, 12}},
|
|
{},
|
|
},
|
|
},
|
|
map[uint64]struct{}{
|
|
8: struct{}{}, 10: struct{}{}, 12: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
10,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
index: 12,
|
|
generations: []generation{
|
|
{ver: 3, cont: []uint64{10, 12}},
|
|
{},
|
|
},
|
|
},
|
|
map[uint64]struct{}{
|
|
10: struct{}{}, 12: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
11,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
index: 12,
|
|
generations: []generation{
|
|
{ver: 3, cont: []uint64{10, 12}},
|
|
{},
|
|
},
|
|
},
|
|
map[uint64]struct{}{
|
|
10: struct{}{}, 12: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
12,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
index: 12,
|
|
generations: []generation{
|
|
{ver: 3, cont: []uint64{12}},
|
|
{},
|
|
},
|
|
},
|
|
map[uint64]struct{}{
|
|
12: struct{}{},
|
|
},
|
|
},
|
|
{
|
|
13,
|
|
&keyIndex{
|
|
key: []byte("foo"),
|
|
index: 12,
|
|
generations: []generation{
|
|
{},
|
|
},
|
|
},
|
|
map[uint64]struct{}{},
|
|
},
|
|
}
|
|
|
|
// Continous Compaction
|
|
ki := newTestKeyIndex()
|
|
for i, tt := range tests {
|
|
am := make(map[uint64]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)
|
|
}
|
|
}
|
|
|
|
// Jump Compaction
|
|
for i, tt := range tests {
|
|
if (i%2 == 0 && i < 6) && (i%2 == 1 && i > 6) {
|
|
am := make(map[uint64]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[uint64]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)
|
|
}
|
|
}
|
|
}
|
|
|
|
func newTestKeyIndex() *keyIndex {
|
|
// key: "foo"
|
|
// index: 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)
|
|
ki.put(4)
|
|
ki.tombstone(6)
|
|
ki.put(8)
|
|
ki.put(10)
|
|
ki.tombstone(12)
|
|
return ki
|
|
}
|