blob: b2ee570f9d54e6bf8598ebc7afd5c96bd4e08a22 [file] [log] [blame]
// Copyright 2015 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package mvcc
import (
"os"
"reflect"
"testing"
"time"
"github.com/coreos/etcd/lease"
"github.com/coreos/etcd/mvcc/backend"
)
func TestScheduleCompaction(t *testing.T) {
revs := []revision{{1, 0}, {2, 0}, {3, 0}}
tests := []struct {
rev int64
keep map[revision]struct{}
wrevs []revision
}{
// compact at 1 and discard all history
{
1,
nil,
revs[1:],
},
// compact at 3 and discard all history
{
3,
nil,
nil,
},
// compact at 1 and keeps history one step earlier
{
1,
map[revision]struct{}{
{main: 1}: {},
},
revs,
},
// compact at 1 and keeps history two steps earlier
{
3,
map[revision]struct{}{
{main: 2}: {},
{main: 3}: {},
},
revs[1:],
},
}
for i, tt := range tests {
b, tmpPath := backend.NewDefaultTmpBackend()
s := NewStore(b, &lease.FakeLessor{}, nil)
tx := s.b.BatchTx()
tx.Lock()
ibytes := newRevBytes()
for _, rev := range revs {
revToBytes(rev, ibytes)
tx.UnsafePut(keyBucketName, ibytes, []byte("bar"))
}
tx.Unlock()
s.scheduleCompaction(tt.rev, tt.keep)
tx.Lock()
for _, rev := range tt.wrevs {
revToBytes(rev, ibytes)
keys, _ := tx.UnsafeRange(keyBucketName, ibytes, nil, 0)
if len(keys) != 1 {
t.Errorf("#%d: range on %v = %d, want 1", i, rev, len(keys))
}
}
_, vals := tx.UnsafeRange(metaBucketName, finishedCompactKeyName, nil, 0)
revToBytes(revision{main: tt.rev}, ibytes)
if w := [][]byte{ibytes}; !reflect.DeepEqual(vals, w) {
t.Errorf("#%d: vals on %v = %+v, want %+v", i, finishedCompactKeyName, vals, w)
}
tx.Unlock()
cleanup(s, b, tmpPath)
}
}
func TestCompactAllAndRestore(t *testing.T) {
b, tmpPath := backend.NewDefaultTmpBackend()
s0 := NewStore(b, &lease.FakeLessor{}, nil)
defer os.Remove(tmpPath)
s0.Put([]byte("foo"), []byte("bar"), lease.NoLease)
s0.Put([]byte("foo"), []byte("bar1"), lease.NoLease)
s0.Put([]byte("foo"), []byte("bar2"), lease.NoLease)
s0.DeleteRange([]byte("foo"), nil)
rev := s0.Rev()
// compact all keys
done, err := s0.Compact(rev)
if err != nil {
t.Fatal(err)
}
select {
case <-done:
case <-time.After(10 * time.Second):
t.Fatal("timeout waiting for compaction to finish")
}
err = s0.Close()
if err != nil {
t.Fatal(err)
}
s1 := NewStore(b, &lease.FakeLessor{}, nil)
if s1.Rev() != rev {
t.Errorf("rev = %v, want %v", s1.Rev(), rev)
}
_, err = s1.Range([]byte("foo"), nil, RangeOptions{})
if err != nil {
t.Errorf("unexpect range error %v", err)
}
}