Browse Source

Merge pull request #2998 from yichengq/storage-kvstore-test

storage: add kv range test
Yicheng Qin 10 years ago
parent
commit
06ca914429
2 changed files with 84 additions and 12 deletions
  1. 7 3
      storage/kvstore.go
  2. 77 9
      storage/kvstore_test.go

+ 7 - 3
storage/kvstore.go

@@ -24,6 +24,7 @@ var (
 
 
 	ErrTnxIDMismatch = errors.New("storage: tnx id mismatch")
 	ErrTnxIDMismatch = errors.New("storage: tnx id mismatch")
 	ErrCompacted     = errors.New("storage: required reversion has been compacted")
 	ErrCompacted     = errors.New("storage: required reversion has been compacted")
+	ErrFutureRev     = errors.New("storage: required reversion is a future reversion")
 )
 )
 
 
 type store struct {
 type store struct {
@@ -240,6 +241,9 @@ func (a *store) Equal(b *store) bool {
 
 
 // range is a keyword in Go, add Keys suffix.
 // range is a keyword in Go, add Keys suffix.
 func (s *store) rangeKeys(key, end []byte, limit, rangeRev int64) (kvs []storagepb.KeyValue, rev int64, err error) {
 func (s *store) rangeKeys(key, end []byte, limit, rangeRev int64) (kvs []storagepb.KeyValue, rev int64, err error) {
+	if rangeRev > s.currentRev.main {
+		return nil, s.currentRev.main, ErrFutureRev
+	}
 	if rangeRev <= 0 {
 	if rangeRev <= 0 {
 		rev = int64(s.currentRev.main)
 		rev = int64(s.currentRev.main)
 		if s.currentRev.sub > 0 {
 		if s.currentRev.sub > 0 {
@@ -256,9 +260,6 @@ func (s *store) rangeKeys(key, end []byte, limit, rangeRev int64) (kvs []storage
 	if len(revpairs) == 0 {
 	if len(revpairs) == 0 {
 		return nil, rev, nil
 		return nil, rev, nil
 	}
 	}
-	if limit > 0 && len(revpairs) > int(limit) {
-		revpairs = revpairs[:limit]
-	}
 
 
 	tx := s.b.BatchTx()
 	tx := s.b.BatchTx()
 	tx.Lock()
 	tx.Lock()
@@ -279,6 +280,9 @@ func (s *store) rangeKeys(key, end []byte, limit, rangeRev int64) (kvs []storage
 		if e.Type == storagepb.PUT {
 		if e.Type == storagepb.PUT {
 			kvs = append(kvs, e.Kv)
 			kvs = append(kvs, e.Kv)
 		}
 		}
+		if limit > 0 && len(kvs) >= int(limit) {
+			break
+		}
 	}
 	}
 	return kvs, rev, nil
 	return kvs, rev, nil
 }
 }

+ 77 - 9
storage/kvstore_test.go

@@ -4,7 +4,10 @@ import (
 	"bytes"
 	"bytes"
 	"crypto/rand"
 	"crypto/rand"
 	"os"
 	"os"
+	"reflect"
 	"testing"
 	"testing"
+
+	"github.com/coreos/etcd/storage/storagepb"
 )
 )
 
 
 func TestRange(t *testing.T) {
 func TestRange(t *testing.T) {
@@ -14,30 +17,34 @@ func TestRange(t *testing.T) {
 	s.Put([]byte("foo"), []byte("bar"))
 	s.Put([]byte("foo"), []byte("bar"))
 	s.Put([]byte("foo1"), []byte("bar1"))
 	s.Put([]byte("foo1"), []byte("bar1"))
 	s.Put([]byte("foo2"), []byte("bar2"))
 	s.Put([]byte("foo2"), []byte("bar2"))
+	kvs := []storagepb.KeyValue{
+		{Key: []byte("foo"), Value: []byte("bar")},
+		{Key: []byte("foo1"), Value: []byte("bar1")},
+		{Key: []byte("foo2"), Value: []byte("bar2")},
+	}
 
 
 	tests := []struct {
 	tests := []struct {
 		key, end []byte
 		key, end []byte
 		rev      int64
 		rev      int64
 
 
 		wrev int64
 		wrev int64
-		// TODO: change this to the actual kv
-		wN int64
+		wkvs []storagepb.KeyValue
 	}{
 	}{
 		{
 		{
 			[]byte("foo"), []byte("foo3"), 0,
 			[]byte("foo"), []byte("foo3"), 0,
-			3, 3,
+			3, kvs,
 		},
 		},
 		{
 		{
 			[]byte("foo"), []byte("foo1"), 0,
 			[]byte("foo"), []byte("foo1"), 0,
-			3, 1,
+			3, kvs[:1],
 		},
 		},
 		{
 		{
 			[]byte("foo"), []byte("foo3"), 1,
 			[]byte("foo"), []byte("foo3"), 1,
-			1, 1,
+			1, kvs[:1],
 		},
 		},
 		{
 		{
 			[]byte("foo"), []byte("foo3"), 2,
 			[]byte("foo"), []byte("foo3"), 2,
-			2, 2,
+			2, kvs[:2],
 		},
 		},
 	}
 	}
 
 
@@ -46,12 +53,73 @@ func TestRange(t *testing.T) {
 		if err != nil {
 		if err != nil {
 			t.Fatal(err)
 			t.Fatal(err)
 		}
 		}
-		if len(kvs) != int(tt.wN) {
-			t.Errorf("#%d: len(kvs) = %d, want %d", i, len(kvs), tt.wN)
-		}
 		if rev != tt.wrev {
 		if rev != tt.wrev {
 			t.Errorf("#%d: rev = %d, want %d", i, tt.rev, tt.wrev)
 			t.Errorf("#%d: rev = %d, want %d", i, tt.rev, tt.wrev)
 		}
 		}
+		if !reflect.DeepEqual(kvs, tt.wkvs) {
+			t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, tt.wkvs)
+		}
+	}
+}
+
+func TestRangeBadRev(t *testing.T) {
+	s := newStore("test")
+	defer os.Remove("test")
+
+	s.Put([]byte("foo"), []byte("bar"))
+	s.Put([]byte("foo1"), []byte("bar1"))
+	s.Put([]byte("foo2"), []byte("bar2"))
+	if err := s.Compact(3); err != nil {
+		t.Fatalf("compact error (%v)", err)
+	}
+
+	tests := []struct {
+		rev  int64
+		werr error
+	}{
+		{2, ErrCompacted},
+		{3, ErrCompacted},
+		{4, ErrFutureRev},
+	}
+	for i, tt := range tests {
+		_, _, err := s.Range([]byte("foo"), []byte("foo3"), 0, tt.rev)
+		if err != tt.werr {
+			t.Errorf("#%d: error = %v, want %v", i, err, tt.werr)
+		}
+	}
+}
+
+func TestRangeLimit(t *testing.T) {
+	s := newStore("test")
+	defer os.Remove("test")
+
+	s.Put([]byte("foo"), []byte("bar"))
+	s.Put([]byte("foo1"), []byte("bar1"))
+	s.Put([]byte("foo2"), []byte("bar2"))
+	s.DeleteRange([]byte("foo1"), nil)
+	kvs := []storagepb.KeyValue{
+		{Key: []byte("foo"), Value: []byte("bar")},
+		{Key: []byte("foo2"), Value: []byte("bar2")},
+	}
+
+	tests := []struct {
+		limit int64
+		wkvs  []storagepb.KeyValue
+	}{
+		// no limit
+		{0, kvs},
+		{1, kvs[:1]},
+		{2, kvs},
+		{3, kvs},
+	}
+	for i, tt := range tests {
+		kvs, _, err := s.Range([]byte("foo"), []byte("foo3"), tt.limit, 0)
+		if err != nil {
+			t.Fatalf("#%d: range error (%v)", i, err)
+		}
+		if !reflect.DeepEqual(kvs, tt.wkvs) {
+			t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, tt.wkvs)
+		}
 	}
 	}
 }
 }