go.etcd.io/etcd@v3.3.27+incompatible/mvcc/kvstore_compaction_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  	"os"
    19  	"reflect"
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/coreos/etcd/lease"
    24  	"github.com/coreos/etcd/mvcc/backend"
    25  )
    26  
    27  func TestScheduleCompaction(t *testing.T) {
    28  	revs := []revision{{1, 0}, {2, 0}, {3, 0}}
    29  
    30  	tests := []struct {
    31  		rev   int64
    32  		keep  map[revision]struct{}
    33  		wrevs []revision
    34  	}{
    35  		// compact at 1 and discard all history
    36  		{
    37  			1,
    38  			nil,
    39  			revs[1:],
    40  		},
    41  		// compact at 3 and discard all history
    42  		{
    43  			3,
    44  			nil,
    45  			nil,
    46  		},
    47  		// compact at 1 and keeps history one step earlier
    48  		{
    49  			1,
    50  			map[revision]struct{}{
    51  				{main: 1}: {},
    52  			},
    53  			revs,
    54  		},
    55  		// compact at 1 and keeps history two steps earlier
    56  		{
    57  			3,
    58  			map[revision]struct{}{
    59  				{main: 2}: {},
    60  				{main: 3}: {},
    61  			},
    62  			revs[1:],
    63  		},
    64  	}
    65  	for i, tt := range tests {
    66  		b, tmpPath := backend.NewDefaultTmpBackend()
    67  		s := NewStore(b, &lease.FakeLessor{}, nil)
    68  		tx := s.b.BatchTx()
    69  
    70  		tx.Lock()
    71  		ibytes := newRevBytes()
    72  		for _, rev := range revs {
    73  			revToBytes(rev, ibytes)
    74  			tx.UnsafePut(keyBucketName, ibytes, []byte("bar"))
    75  		}
    76  		tx.Unlock()
    77  
    78  		s.scheduleCompaction(tt.rev, tt.keep)
    79  
    80  		tx.Lock()
    81  		for _, rev := range tt.wrevs {
    82  			revToBytes(rev, ibytes)
    83  			keys, _ := tx.UnsafeRange(keyBucketName, ibytes, nil, 0)
    84  			if len(keys) != 1 {
    85  				t.Errorf("#%d: range on %v = %d, want 1", i, rev, len(keys))
    86  			}
    87  		}
    88  		_, vals := tx.UnsafeRange(metaBucketName, finishedCompactKeyName, nil, 0)
    89  		revToBytes(revision{main: tt.rev}, ibytes)
    90  		if w := [][]byte{ibytes}; !reflect.DeepEqual(vals, w) {
    91  			t.Errorf("#%d: vals on %v = %+v, want %+v", i, finishedCompactKeyName, vals, w)
    92  		}
    93  		tx.Unlock()
    94  
    95  		cleanup(s, b, tmpPath)
    96  	}
    97  }
    98  
    99  func TestCompactAllAndRestore(t *testing.T) {
   100  	b, tmpPath := backend.NewDefaultTmpBackend()
   101  	s0 := NewStore(b, &lease.FakeLessor{}, nil)
   102  	defer os.Remove(tmpPath)
   103  
   104  	s0.Put([]byte("foo"), []byte("bar"), lease.NoLease)
   105  	s0.Put([]byte("foo"), []byte("bar1"), lease.NoLease)
   106  	s0.Put([]byte("foo"), []byte("bar2"), lease.NoLease)
   107  	s0.DeleteRange([]byte("foo"), nil)
   108  
   109  	rev := s0.Rev()
   110  	// compact all keys
   111  	done, err := s0.Compact(rev)
   112  	if err != nil {
   113  		t.Fatal(err)
   114  	}
   115  
   116  	select {
   117  	case <-done:
   118  	case <-time.After(10 * time.Second):
   119  		t.Fatal("timeout waiting for compaction to finish")
   120  	}
   121  
   122  	err = s0.Close()
   123  	if err != nil {
   124  		t.Fatal(err)
   125  	}
   126  
   127  	s1 := NewStore(b, &lease.FakeLessor{}, nil)
   128  	if s1.Rev() != rev {
   129  		t.Errorf("rev = %v, want %v", s1.Rev(), rev)
   130  	}
   131  	_, err = s1.Range([]byte("foo"), nil, RangeOptions{})
   132  	if err != nil {
   133  		t.Errorf("unexpect range error %v", err)
   134  	}
   135  }