go.etcd.io/etcd@v3.3.27+incompatible/mvcc/kv_test.go (about)

     1  // Copyright 2015 The etcd Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package mvcc
    16  
    17  import (
    18  	"fmt"
    19  	"os"
    20  	"reflect"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/coreos/etcd/lease"
    25  	"github.com/coreos/etcd/mvcc/backend"
    26  	"github.com/coreos/etcd/mvcc/mvccpb"
    27  	"github.com/coreos/etcd/pkg/testutil"
    28  
    29  	"github.com/prometheus/client_golang/prometheus"
    30  	dto "github.com/prometheus/client_model/go"
    31  )
    32  
    33  // Functional tests for features implemented in v3 store. It treats v3 store
    34  // as a black box, and tests it by feeding the input and validating the output.
    35  
    36  // TODO: add similar tests on operations in one txn/rev
    37  
    38  type (
    39  	rangeFunc       func(kv KV, key, end []byte, ro RangeOptions) (*RangeResult, error)
    40  	putFunc         func(kv KV, key, value []byte, lease lease.LeaseID) int64
    41  	deleteRangeFunc func(kv KV, key, end []byte) (n, rev int64)
    42  )
    43  
    44  var (
    45  	normalRangeFunc = func(kv KV, key, end []byte, ro RangeOptions) (*RangeResult, error) {
    46  		return kv.Range(key, end, ro)
    47  	}
    48  	txnRangeFunc = func(kv KV, key, end []byte, ro RangeOptions) (*RangeResult, error) {
    49  		txn := kv.Read()
    50  		defer txn.End()
    51  		return txn.Range(key, end, ro)
    52  	}
    53  
    54  	normalPutFunc = func(kv KV, key, value []byte, lease lease.LeaseID) int64 {
    55  		return kv.Put(key, value, lease)
    56  	}
    57  	txnPutFunc = func(kv KV, key, value []byte, lease lease.LeaseID) int64 {
    58  		txn := kv.Write()
    59  		defer txn.End()
    60  		return txn.Put(key, value, lease)
    61  	}
    62  
    63  	normalDeleteRangeFunc = func(kv KV, key, end []byte) (n, rev int64) {
    64  		return kv.DeleteRange(key, end)
    65  	}
    66  	txnDeleteRangeFunc = func(kv KV, key, end []byte) (n, rev int64) {
    67  		txn := kv.Write()
    68  		defer txn.End()
    69  		return txn.DeleteRange(key, end)
    70  	}
    71  )
    72  
    73  func TestKVRange(t *testing.T)    { testKVRange(t, normalRangeFunc) }
    74  func TestKVTxnRange(t *testing.T) { testKVRange(t, txnRangeFunc) }
    75  
    76  func testKVRange(t *testing.T, f rangeFunc) {
    77  	b, tmpPath := backend.NewDefaultTmpBackend()
    78  	s := NewStore(b, &lease.FakeLessor{}, nil)
    79  	defer cleanup(s, b, tmpPath)
    80  
    81  	kvs := put3TestKVs(s)
    82  
    83  	wrev := int64(4)
    84  	tests := []struct {
    85  		key, end []byte
    86  		wkvs     []mvccpb.KeyValue
    87  	}{
    88  		// get no keys
    89  		{
    90  			[]byte("doo"), []byte("foo"),
    91  			nil,
    92  		},
    93  		// get no keys when key == end
    94  		{
    95  			[]byte("foo"), []byte("foo"),
    96  			nil,
    97  		},
    98  		// get no keys when ranging single key
    99  		{
   100  			[]byte("doo"), nil,
   101  			nil,
   102  		},
   103  		// get all keys
   104  		{
   105  			[]byte("foo"), []byte("foo3"),
   106  			kvs,
   107  		},
   108  		// get partial keys
   109  		{
   110  			[]byte("foo"), []byte("foo1"),
   111  			kvs[:1],
   112  		},
   113  		// get single key
   114  		{
   115  			[]byte("foo"), nil,
   116  			kvs[:1],
   117  		},
   118  		// get entire keyspace
   119  		{
   120  			[]byte(""), []byte(""),
   121  			kvs,
   122  		},
   123  	}
   124  
   125  	for i, tt := range tests {
   126  		r, err := f(s, tt.key, tt.end, RangeOptions{})
   127  		if err != nil {
   128  			t.Fatal(err)
   129  		}
   130  		if r.Rev != wrev {
   131  			t.Errorf("#%d: rev = %d, want %d", i, r.Rev, wrev)
   132  		}
   133  		if !reflect.DeepEqual(r.KVs, tt.wkvs) {
   134  			t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, tt.wkvs)
   135  		}
   136  	}
   137  }
   138  
   139  func TestKVRangeRev(t *testing.T)    { testKVRangeRev(t, normalRangeFunc) }
   140  func TestKVTxnRangeRev(t *testing.T) { testKVRangeRev(t, txnRangeFunc) }
   141  
   142  func testKVRangeRev(t *testing.T, f rangeFunc) {
   143  	b, tmpPath := backend.NewDefaultTmpBackend()
   144  	s := NewStore(b, &lease.FakeLessor{}, nil)
   145  	defer cleanup(s, b, tmpPath)
   146  
   147  	kvs := put3TestKVs(s)
   148  
   149  	tests := []struct {
   150  		rev  int64
   151  		wrev int64
   152  		wkvs []mvccpb.KeyValue
   153  	}{
   154  		{-1, 4, kvs},
   155  		{0, 4, kvs},
   156  		{2, 4, kvs[:1]},
   157  		{3, 4, kvs[:2]},
   158  		{4, 4, kvs},
   159  	}
   160  
   161  	for i, tt := range tests {
   162  		r, err := f(s, []byte("foo"), []byte("foo3"), RangeOptions{Rev: tt.rev})
   163  		if err != nil {
   164  			t.Fatal(err)
   165  		}
   166  		if r.Rev != tt.wrev {
   167  			t.Errorf("#%d: rev = %d, want %d", i, r.Rev, tt.wrev)
   168  		}
   169  		if !reflect.DeepEqual(r.KVs, tt.wkvs) {
   170  			t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, tt.wkvs)
   171  		}
   172  	}
   173  }
   174  
   175  func TestKVRangeBadRev(t *testing.T)    { testKVRangeBadRev(t, normalRangeFunc) }
   176  func TestKVTxnRangeBadRev(t *testing.T) { testKVRangeBadRev(t, txnRangeFunc) }
   177  
   178  func testKVRangeBadRev(t *testing.T, f rangeFunc) {
   179  	b, tmpPath := backend.NewDefaultTmpBackend()
   180  	s := NewStore(b, &lease.FakeLessor{}, nil)
   181  	defer cleanup(s, b, tmpPath)
   182  
   183  	put3TestKVs(s)
   184  	if _, err := s.Compact(4); err != nil {
   185  		t.Fatalf("compact error (%v)", err)
   186  	}
   187  
   188  	tests := []struct {
   189  		rev  int64
   190  		werr error
   191  	}{
   192  		{-1, nil}, // <= 0 is most recent store
   193  		{0, nil},
   194  		{1, ErrCompacted},
   195  		{2, ErrCompacted},
   196  		{4, nil},
   197  		{5, ErrFutureRev},
   198  		{100, ErrFutureRev},
   199  	}
   200  	for i, tt := range tests {
   201  		_, err := f(s, []byte("foo"), []byte("foo3"), RangeOptions{Rev: tt.rev})
   202  		if err != tt.werr {
   203  			t.Errorf("#%d: error = %v, want %v", i, err, tt.werr)
   204  		}
   205  	}
   206  }
   207  
   208  func TestKVRangeLimit(t *testing.T)    { testKVRangeLimit(t, normalRangeFunc) }
   209  func TestKVTxnRangeLimit(t *testing.T) { testKVRangeLimit(t, txnRangeFunc) }
   210  
   211  func testKVRangeLimit(t *testing.T, f rangeFunc) {
   212  	b, tmpPath := backend.NewDefaultTmpBackend()
   213  	s := NewStore(b, &lease.FakeLessor{}, nil)
   214  	defer cleanup(s, b, tmpPath)
   215  
   216  	kvs := put3TestKVs(s)
   217  
   218  	wrev := int64(4)
   219  	tests := []struct {
   220  		limit int64
   221  		wkvs  []mvccpb.KeyValue
   222  	}{
   223  		// no limit
   224  		{-1, kvs},
   225  		// no limit
   226  		{0, kvs},
   227  		{1, kvs[:1]},
   228  		{2, kvs[:2]},
   229  		{3, kvs},
   230  		{100, kvs},
   231  	}
   232  	for i, tt := range tests {
   233  		r, err := f(s, []byte("foo"), []byte("foo3"), RangeOptions{Limit: tt.limit})
   234  		if err != nil {
   235  			t.Fatalf("#%d: range error (%v)", i, err)
   236  		}
   237  		if !reflect.DeepEqual(r.KVs, tt.wkvs) {
   238  			t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, tt.wkvs)
   239  		}
   240  		if r.Rev != wrev {
   241  			t.Errorf("#%d: rev = %d, want %d", i, r.Rev, wrev)
   242  		}
   243  		if r.Count != len(kvs) {
   244  			t.Errorf("#%d: count = %d, want %d", i, r.Count, len(kvs))
   245  		}
   246  	}
   247  }
   248  
   249  func TestKVPutMultipleTimes(t *testing.T)    { testKVPutMultipleTimes(t, normalPutFunc) }
   250  func TestKVTxnPutMultipleTimes(t *testing.T) { testKVPutMultipleTimes(t, txnPutFunc) }
   251  
   252  func testKVPutMultipleTimes(t *testing.T, f putFunc) {
   253  	b, tmpPath := backend.NewDefaultTmpBackend()
   254  	s := NewStore(b, &lease.FakeLessor{}, nil)
   255  	defer cleanup(s, b, tmpPath)
   256  
   257  	for i := 0; i < 10; i++ {
   258  		base := int64(i + 1)
   259  
   260  		rev := f(s, []byte("foo"), []byte("bar"), lease.LeaseID(base))
   261  		if rev != base+1 {
   262  			t.Errorf("#%d: rev = %d, want %d", i, rev, base+1)
   263  		}
   264  
   265  		r, err := s.Range([]byte("foo"), nil, RangeOptions{})
   266  		if err != nil {
   267  			t.Fatal(err)
   268  		}
   269  		wkvs := []mvccpb.KeyValue{
   270  			{Key: []byte("foo"), Value: []byte("bar"), CreateRevision: 2, ModRevision: base + 1, Version: base, Lease: base},
   271  		}
   272  		if !reflect.DeepEqual(r.KVs, wkvs) {
   273  			t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, wkvs)
   274  		}
   275  	}
   276  }
   277  
   278  func TestKVDeleteRange(t *testing.T)    { testKVDeleteRange(t, normalDeleteRangeFunc) }
   279  func TestKVTxnDeleteRange(t *testing.T) { testKVDeleteRange(t, txnDeleteRangeFunc) }
   280  
   281  func testKVDeleteRange(t *testing.T, f deleteRangeFunc) {
   282  	tests := []struct {
   283  		key, end []byte
   284  
   285  		wrev int64
   286  		wN   int64
   287  	}{
   288  		{
   289  			[]byte("foo"), nil,
   290  			5, 1,
   291  		},
   292  		{
   293  			[]byte("foo"), []byte("foo1"),
   294  			5, 1,
   295  		},
   296  		{
   297  			[]byte("foo"), []byte("foo2"),
   298  			5, 2,
   299  		},
   300  		{
   301  			[]byte("foo"), []byte("foo3"),
   302  			5, 3,
   303  		},
   304  		{
   305  			[]byte("foo3"), []byte("foo8"),
   306  			4, 0,
   307  		},
   308  		{
   309  			[]byte("foo3"), nil,
   310  			4, 0,
   311  		},
   312  	}
   313  
   314  	for i, tt := range tests {
   315  		b, tmpPath := backend.NewDefaultTmpBackend()
   316  		s := NewStore(b, &lease.FakeLessor{}, nil)
   317  
   318  		s.Put([]byte("foo"), []byte("bar"), lease.NoLease)
   319  		s.Put([]byte("foo1"), []byte("bar1"), lease.NoLease)
   320  		s.Put([]byte("foo2"), []byte("bar2"), lease.NoLease)
   321  
   322  		n, rev := f(s, tt.key, tt.end)
   323  		if n != tt.wN || rev != tt.wrev {
   324  			t.Errorf("#%d: n = %d, rev = %d, want (%d, %d)", i, n, rev, tt.wN, tt.wrev)
   325  		}
   326  
   327  		cleanup(s, b, tmpPath)
   328  	}
   329  }
   330  
   331  func TestKVDeleteMultipleTimes(t *testing.T)    { testKVDeleteMultipleTimes(t, normalDeleteRangeFunc) }
   332  func TestKVTxnDeleteMultipleTimes(t *testing.T) { testKVDeleteMultipleTimes(t, txnDeleteRangeFunc) }
   333  
   334  func testKVDeleteMultipleTimes(t *testing.T, f deleteRangeFunc) {
   335  	b, tmpPath := backend.NewDefaultTmpBackend()
   336  	s := NewStore(b, &lease.FakeLessor{}, nil)
   337  	defer cleanup(s, b, tmpPath)
   338  
   339  	s.Put([]byte("foo"), []byte("bar"), lease.NoLease)
   340  
   341  	n, rev := f(s, []byte("foo"), nil)
   342  	if n != 1 || rev != 3 {
   343  		t.Fatalf("n = %d, rev = %d, want (%d, %d)", n, rev, 1, 3)
   344  	}
   345  
   346  	for i := 0; i < 10; i++ {
   347  		n, rev := f(s, []byte("foo"), nil)
   348  		if n != 0 || rev != 3 {
   349  			t.Fatalf("#%d: n = %d, rev = %d, want (%d, %d)", i, n, rev, 0, 3)
   350  		}
   351  	}
   352  }
   353  
   354  // test that range, put, delete on single key in sequence repeatedly works correctly.
   355  func TestKVOperationInSequence(t *testing.T) {
   356  	b, tmpPath := backend.NewDefaultTmpBackend()
   357  	s := NewStore(b, &lease.FakeLessor{}, nil)
   358  	defer cleanup(s, b, tmpPath)
   359  
   360  	for i := 0; i < 10; i++ {
   361  		base := int64(i*2 + 1)
   362  
   363  		// put foo
   364  		rev := s.Put([]byte("foo"), []byte("bar"), lease.NoLease)
   365  		if rev != base+1 {
   366  			t.Errorf("#%d: put rev = %d, want %d", i, rev, base+1)
   367  		}
   368  
   369  		r, err := s.Range([]byte("foo"), nil, RangeOptions{Rev: base + 1})
   370  		if err != nil {
   371  			t.Fatal(err)
   372  		}
   373  		wkvs := []mvccpb.KeyValue{
   374  			{Key: []byte("foo"), Value: []byte("bar"), CreateRevision: base + 1, ModRevision: base + 1, Version: 1, Lease: int64(lease.NoLease)},
   375  		}
   376  		if !reflect.DeepEqual(r.KVs, wkvs) {
   377  			t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, wkvs)
   378  		}
   379  		if r.Rev != base+1 {
   380  			t.Errorf("#%d: range rev = %d, want %d", i, rev, base+1)
   381  		}
   382  
   383  		// delete foo
   384  		n, rev := s.DeleteRange([]byte("foo"), nil)
   385  		if n != 1 || rev != base+2 {
   386  			t.Errorf("#%d: n = %d, rev = %d, want (%d, %d)", i, n, rev, 1, base+2)
   387  		}
   388  
   389  		r, err = s.Range([]byte("foo"), nil, RangeOptions{Rev: base + 2})
   390  		if err != nil {
   391  			t.Fatal(err)
   392  		}
   393  		if r.KVs != nil {
   394  			t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, nil)
   395  		}
   396  		if r.Rev != base+2 {
   397  			t.Errorf("#%d: range rev = %d, want %d", i, r.Rev, base+2)
   398  		}
   399  	}
   400  }
   401  
   402  func TestKVTxnBlockWriteOperations(t *testing.T) {
   403  	b, tmpPath := backend.NewDefaultTmpBackend()
   404  	s := NewStore(b, &lease.FakeLessor{}, nil)
   405  
   406  	tests := []func(){
   407  		func() { s.Put([]byte("foo"), nil, lease.NoLease) },
   408  		func() { s.DeleteRange([]byte("foo"), nil) },
   409  	}
   410  	for i, tt := range tests {
   411  		txn := s.Write()
   412  		done := make(chan struct{}, 1)
   413  		go func() {
   414  			tt()
   415  			done <- struct{}{}
   416  		}()
   417  		select {
   418  		case <-done:
   419  			t.Fatalf("#%d: operation failed to be blocked", i)
   420  		case <-time.After(10 * time.Millisecond):
   421  		}
   422  
   423  		txn.End()
   424  		select {
   425  		case <-done:
   426  		case <-time.After(10 * time.Second):
   427  			testutil.FatalStack(t, fmt.Sprintf("#%d: operation failed to be unblocked", i))
   428  		}
   429  	}
   430  
   431  	// only close backend when we know all the tx are finished
   432  	cleanup(s, b, tmpPath)
   433  }
   434  
   435  func TestKVTxnNonBlockRange(t *testing.T) {
   436  	b, tmpPath := backend.NewDefaultTmpBackend()
   437  	s := NewStore(b, &lease.FakeLessor{}, nil)
   438  	defer cleanup(s, b, tmpPath)
   439  
   440  	txn := s.Write()
   441  	defer txn.End()
   442  
   443  	donec := make(chan struct{})
   444  	go func() {
   445  		defer close(donec)
   446  		s.Range([]byte("foo"), nil, RangeOptions{})
   447  	}()
   448  	select {
   449  	case <-donec:
   450  	case <-time.After(100 * time.Millisecond):
   451  		t.Fatalf("range operation blocked on write txn")
   452  	}
   453  }
   454  
   455  // test that txn range, put, delete on single key in sequence repeatedly works correctly.
   456  func TestKVTxnOperationInSequence(t *testing.T) {
   457  	b, tmpPath := backend.NewDefaultTmpBackend()
   458  	s := NewStore(b, &lease.FakeLessor{}, nil)
   459  	defer cleanup(s, b, tmpPath)
   460  
   461  	for i := 0; i < 10; i++ {
   462  		txn := s.Write()
   463  		base := int64(i + 1)
   464  
   465  		// put foo
   466  		rev := txn.Put([]byte("foo"), []byte("bar"), lease.NoLease)
   467  		if rev != base+1 {
   468  			t.Errorf("#%d: put rev = %d, want %d", i, rev, base+1)
   469  		}
   470  
   471  		r, err := txn.Range([]byte("foo"), nil, RangeOptions{Rev: base + 1})
   472  		if err != nil {
   473  			t.Fatal(err)
   474  		}
   475  		wkvs := []mvccpb.KeyValue{
   476  			{Key: []byte("foo"), Value: []byte("bar"), CreateRevision: base + 1, ModRevision: base + 1, Version: 1, Lease: int64(lease.NoLease)},
   477  		}
   478  		if !reflect.DeepEqual(r.KVs, wkvs) {
   479  			t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, wkvs)
   480  		}
   481  		if r.Rev != base+1 {
   482  			t.Errorf("#%d: range rev = %d, want %d", i, r.Rev, base+1)
   483  		}
   484  
   485  		// delete foo
   486  		n, rev := txn.DeleteRange([]byte("foo"), nil)
   487  		if n != 1 || rev != base+1 {
   488  			t.Errorf("#%d: n = %d, rev = %d, want (%d, %d)", i, n, rev, 1, base+1)
   489  		}
   490  
   491  		r, err = txn.Range([]byte("foo"), nil, RangeOptions{Rev: base + 1})
   492  		if err != nil {
   493  			t.Errorf("#%d: range error (%v)", i, err)
   494  		}
   495  		if r.KVs != nil {
   496  			t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, nil)
   497  		}
   498  		if r.Rev != base+1 {
   499  			t.Errorf("#%d: range rev = %d, want %d", i, r.Rev, base+1)
   500  		}
   501  
   502  		txn.End()
   503  	}
   504  }
   505  
   506  func TestKVCompactReserveLastValue(t *testing.T) {
   507  	b, tmpPath := backend.NewDefaultTmpBackend()
   508  	s := NewStore(b, &lease.FakeLessor{}, nil)
   509  	defer cleanup(s, b, tmpPath)
   510  
   511  	s.Put([]byte("foo"), []byte("bar0"), 1)
   512  	s.Put([]byte("foo"), []byte("bar1"), 2)
   513  	s.DeleteRange([]byte("foo"), nil)
   514  	s.Put([]byte("foo"), []byte("bar2"), 3)
   515  
   516  	// rev in tests will be called in Compact() one by one on the same store
   517  	tests := []struct {
   518  		rev int64
   519  		// wanted kvs right after the compacted rev
   520  		wkvs []mvccpb.KeyValue
   521  	}{
   522  		{
   523  			1,
   524  			[]mvccpb.KeyValue{
   525  				{Key: []byte("foo"), Value: []byte("bar0"), CreateRevision: 2, ModRevision: 2, Version: 1, Lease: 1},
   526  			},
   527  		},
   528  		{
   529  			2,
   530  			[]mvccpb.KeyValue{
   531  				{Key: []byte("foo"), Value: []byte("bar1"), CreateRevision: 2, ModRevision: 3, Version: 2, Lease: 2},
   532  			},
   533  		},
   534  		{
   535  			3,
   536  			nil,
   537  		},
   538  		{
   539  			4,
   540  			[]mvccpb.KeyValue{
   541  				{Key: []byte("foo"), Value: []byte("bar2"), CreateRevision: 5, ModRevision: 5, Version: 1, Lease: 3},
   542  			},
   543  		},
   544  	}
   545  	for i, tt := range tests {
   546  		_, err := s.Compact(tt.rev)
   547  		if err != nil {
   548  			t.Errorf("#%d: unexpect compact error %v", i, err)
   549  		}
   550  		r, err := s.Range([]byte("foo"), nil, RangeOptions{Rev: tt.rev + 1})
   551  		if err != nil {
   552  			t.Errorf("#%d: unexpect range error %v", i, err)
   553  		}
   554  		if !reflect.DeepEqual(r.KVs, tt.wkvs) {
   555  			t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, tt.wkvs)
   556  		}
   557  	}
   558  }
   559  
   560  func TestKVCompactBad(t *testing.T) {
   561  	b, tmpPath := backend.NewDefaultTmpBackend()
   562  	s := NewStore(b, &lease.FakeLessor{}, nil)
   563  	defer cleanup(s, b, tmpPath)
   564  
   565  	s.Put([]byte("foo"), []byte("bar0"), lease.NoLease)
   566  	s.Put([]byte("foo"), []byte("bar1"), lease.NoLease)
   567  	s.Put([]byte("foo"), []byte("bar2"), lease.NoLease)
   568  
   569  	// rev in tests will be called in Compact() one by one on the same store
   570  	tests := []struct {
   571  		rev  int64
   572  		werr error
   573  	}{
   574  		{0, nil},
   575  		{1, nil},
   576  		{1, ErrCompacted},
   577  		{4, nil},
   578  		{5, ErrFutureRev},
   579  		{100, ErrFutureRev},
   580  	}
   581  	for i, tt := range tests {
   582  		_, err := s.Compact(tt.rev)
   583  		if err != tt.werr {
   584  			t.Errorf("#%d: compact error = %v, want %v", i, err, tt.werr)
   585  		}
   586  	}
   587  }
   588  
   589  func TestKVHash(t *testing.T) {
   590  	hashes := make([]uint32, 3)
   591  
   592  	for i := 0; i < len(hashes); i++ {
   593  		var err error
   594  		b, tmpPath := backend.NewDefaultTmpBackend()
   595  		kv := NewStore(b, &lease.FakeLessor{}, nil)
   596  		kv.Put([]byte("foo0"), []byte("bar0"), lease.NoLease)
   597  		kv.Put([]byte("foo1"), []byte("bar0"), lease.NoLease)
   598  		hashes[i], _, err = kv.Hash()
   599  		if err != nil {
   600  			t.Fatalf("failed to get hash: %v", err)
   601  		}
   602  		cleanup(kv, b, tmpPath)
   603  	}
   604  
   605  	for i := 1; i < len(hashes); i++ {
   606  		if hashes[i-1] != hashes[i] {
   607  			t.Errorf("hash[%d](%d) != hash[%d](%d)", i-1, hashes[i-1], i, hashes[i])
   608  		}
   609  	}
   610  }
   611  
   612  func TestKVRestore(t *testing.T) {
   613  	tests := []func(kv KV){
   614  		func(kv KV) {
   615  			kv.Put([]byte("foo"), []byte("bar0"), 1)
   616  			kv.Put([]byte("foo"), []byte("bar1"), 2)
   617  			kv.Put([]byte("foo"), []byte("bar2"), 3)
   618  			kv.Put([]byte("foo2"), []byte("bar0"), 1)
   619  		},
   620  		func(kv KV) {
   621  			kv.Put([]byte("foo"), []byte("bar0"), 1)
   622  			kv.DeleteRange([]byte("foo"), nil)
   623  			kv.Put([]byte("foo"), []byte("bar1"), 2)
   624  		},
   625  		func(kv KV) {
   626  			kv.Put([]byte("foo"), []byte("bar0"), 1)
   627  			kv.Put([]byte("foo"), []byte("bar1"), 2)
   628  			kv.Compact(1)
   629  		},
   630  	}
   631  	for i, tt := range tests {
   632  		b, tmpPath := backend.NewDefaultTmpBackend()
   633  		s := NewStore(b, &lease.FakeLessor{}, nil)
   634  		tt(s)
   635  		var kvss [][]mvccpb.KeyValue
   636  		for k := int64(0); k < 10; k++ {
   637  			r, _ := s.Range([]byte("a"), []byte("z"), RangeOptions{Rev: k})
   638  			kvss = append(kvss, r.KVs)
   639  		}
   640  
   641  		keysBefore := readGaugeInt(&keysGauge)
   642  		s.Close()
   643  
   644  		// ns should recover the the previous state from backend.
   645  		ns := NewStore(b, &lease.FakeLessor{}, nil)
   646  
   647  		if keysRestore := readGaugeInt(&keysGauge); keysBefore != keysRestore {
   648  			t.Errorf("#%d: got %d key count, expected %d", i, keysRestore, keysBefore)
   649  		}
   650  
   651  		// wait for possible compaction to finish
   652  		testutil.WaitSchedule()
   653  		var nkvss [][]mvccpb.KeyValue
   654  		for k := int64(0); k < 10; k++ {
   655  			r, _ := ns.Range([]byte("a"), []byte("z"), RangeOptions{Rev: k})
   656  			nkvss = append(nkvss, r.KVs)
   657  		}
   658  		cleanup(ns, b, tmpPath)
   659  
   660  		if !reflect.DeepEqual(nkvss, kvss) {
   661  			t.Errorf("#%d: kvs history = %+v, want %+v", i, nkvss, kvss)
   662  		}
   663  	}
   664  }
   665  
   666  func readGaugeInt(g *prometheus.Gauge) int {
   667  	ch := make(chan prometheus.Metric, 1)
   668  	keysGauge.Collect(ch)
   669  	m := <-ch
   670  	mm := &dto.Metric{}
   671  	m.Write(mm)
   672  	return int(mm.GetGauge().GetValue())
   673  }
   674  
   675  func TestKVSnapshot(t *testing.T) {
   676  	b, tmpPath := backend.NewDefaultTmpBackend()
   677  	s := NewStore(b, &lease.FakeLessor{}, nil)
   678  	defer cleanup(s, b, tmpPath)
   679  
   680  	wkvs := put3TestKVs(s)
   681  
   682  	newPath := "new_test"
   683  	f, err := os.Create(newPath)
   684  	if err != nil {
   685  		t.Fatal(err)
   686  	}
   687  	defer os.Remove(newPath)
   688  
   689  	snap := s.b.Snapshot()
   690  	defer snap.Close()
   691  	_, err = snap.WriteTo(f)
   692  	if err != nil {
   693  		t.Fatal(err)
   694  	}
   695  	f.Close()
   696  
   697  	ns := NewStore(b, &lease.FakeLessor{}, nil)
   698  	defer ns.Close()
   699  	r, err := ns.Range([]byte("a"), []byte("z"), RangeOptions{})
   700  	if err != nil {
   701  		t.Errorf("unexpect range error (%v)", err)
   702  	}
   703  	if !reflect.DeepEqual(r.KVs, wkvs) {
   704  		t.Errorf("kvs = %+v, want %+v", r.KVs, wkvs)
   705  	}
   706  	if r.Rev != 4 {
   707  		t.Errorf("rev = %d, want %d", r.Rev, 4)
   708  	}
   709  }
   710  
   711  func TestWatchableKVWatch(t *testing.T) {
   712  	b, tmpPath := backend.NewDefaultTmpBackend()
   713  	s := WatchableKV(newWatchableStore(b, &lease.FakeLessor{}, nil, nil))
   714  	defer cleanup(s, b, tmpPath)
   715  
   716  	w := s.NewWatchStream()
   717  	defer w.Close()
   718  
   719  	wid := w.Watch([]byte("foo"), []byte("fop"), 0)
   720  
   721  	wev := []mvccpb.Event{
   722  		{Type: mvccpb.PUT,
   723  			Kv: &mvccpb.KeyValue{
   724  				Key:            []byte("foo"),
   725  				Value:          []byte("bar"),
   726  				CreateRevision: 2,
   727  				ModRevision:    2,
   728  				Version:        1,
   729  				Lease:          1,
   730  			},
   731  		},
   732  		{
   733  			Type: mvccpb.PUT,
   734  			Kv: &mvccpb.KeyValue{
   735  				Key:            []byte("foo1"),
   736  				Value:          []byte("bar1"),
   737  				CreateRevision: 3,
   738  				ModRevision:    3,
   739  				Version:        1,
   740  				Lease:          2,
   741  			},
   742  		},
   743  		{
   744  			Type: mvccpb.PUT,
   745  			Kv: &mvccpb.KeyValue{
   746  				Key:            []byte("foo1"),
   747  				Value:          []byte("bar11"),
   748  				CreateRevision: 3,
   749  				ModRevision:    4,
   750  				Version:        2,
   751  				Lease:          3,
   752  			},
   753  		},
   754  	}
   755  
   756  	s.Put([]byte("foo"), []byte("bar"), 1)
   757  	select {
   758  	case resp := <-w.Chan():
   759  		if resp.WatchID != wid {
   760  			t.Errorf("resp.WatchID got = %d, want = %d", resp.WatchID, wid)
   761  		}
   762  		ev := resp.Events[0]
   763  		if !reflect.DeepEqual(ev, wev[0]) {
   764  			t.Errorf("watched event = %+v, want %+v", ev, wev[0])
   765  		}
   766  	case <-time.After(5 * time.Second):
   767  		// CPU might be too slow, and the routine is not able to switch around
   768  		testutil.FatalStack(t, "failed to watch the event")
   769  	}
   770  
   771  	s.Put([]byte("foo1"), []byte("bar1"), 2)
   772  	select {
   773  	case resp := <-w.Chan():
   774  		if resp.WatchID != wid {
   775  			t.Errorf("resp.WatchID got = %d, want = %d", resp.WatchID, wid)
   776  		}
   777  		ev := resp.Events[0]
   778  		if !reflect.DeepEqual(ev, wev[1]) {
   779  			t.Errorf("watched event = %+v, want %+v", ev, wev[1])
   780  		}
   781  	case <-time.After(5 * time.Second):
   782  		testutil.FatalStack(t, "failed to watch the event")
   783  	}
   784  
   785  	w = s.NewWatchStream()
   786  	wid = w.Watch([]byte("foo1"), []byte("foo2"), 3)
   787  
   788  	select {
   789  	case resp := <-w.Chan():
   790  		if resp.WatchID != wid {
   791  			t.Errorf("resp.WatchID got = %d, want = %d", resp.WatchID, wid)
   792  		}
   793  		ev := resp.Events[0]
   794  		if !reflect.DeepEqual(ev, wev[1]) {
   795  			t.Errorf("watched event = %+v, want %+v", ev, wev[1])
   796  		}
   797  	case <-time.After(5 * time.Second):
   798  		testutil.FatalStack(t, "failed to watch the event")
   799  	}
   800  
   801  	s.Put([]byte("foo1"), []byte("bar11"), 3)
   802  	select {
   803  	case resp := <-w.Chan():
   804  		if resp.WatchID != wid {
   805  			t.Errorf("resp.WatchID got = %d, want = %d", resp.WatchID, wid)
   806  		}
   807  		ev := resp.Events[0]
   808  		if !reflect.DeepEqual(ev, wev[2]) {
   809  			t.Errorf("watched event = %+v, want %+v", ev, wev[2])
   810  		}
   811  	case <-time.After(5 * time.Second):
   812  		testutil.FatalStack(t, "failed to watch the event")
   813  	}
   814  }
   815  
   816  func cleanup(s KV, b backend.Backend, path string) {
   817  	s.Close()
   818  	b.Close()
   819  	os.Remove(path)
   820  }
   821  
   822  func put3TestKVs(s KV) []mvccpb.KeyValue {
   823  	s.Put([]byte("foo"), []byte("bar"), 1)
   824  	s.Put([]byte("foo1"), []byte("bar1"), 2)
   825  	s.Put([]byte("foo2"), []byte("bar2"), 3)
   826  	return []mvccpb.KeyValue{
   827  		{Key: []byte("foo"), Value: []byte("bar"), CreateRevision: 2, ModRevision: 2, Version: 1, Lease: 1},
   828  		{Key: []byte("foo1"), Value: []byte("bar1"), CreateRevision: 3, ModRevision: 3, Version: 1, Lease: 2},
   829  		{Key: []byte("foo2"), Value: []byte("bar2"), CreateRevision: 4, ModRevision: 4, Version: 1, Lease: 3},
   830  	}
   831  }