1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package mvcc
16
17 import (
18 "context"
19 "fmt"
20 "testing"
21
22 "github.com/stretchr/testify/assert"
23 "go.etcd.io/etcd/pkg/v3/traceutil"
24 "go.etcd.io/etcd/server/v3/lease"
25 betesting "go.etcd.io/etcd/server/v3/mvcc/backend/testing"
26 "go.etcd.io/etcd/server/v3/storage/mvcc/testutil"
27 "go.uber.org/zap/zaptest"
28 )
29
30
31
32
33 func TestHashByRevValue(t *testing.T) {
34 b, _ := betesting.NewDefaultTmpBackend(t)
35 s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{})
36
37 var totalRevisions int64 = 1210
38 assert.Less(t, int64(s.cfg.CompactionBatchLimit), totalRevisions)
39 assert.Less(t, int64(testutil.CompactionCycle*10), totalRevisions)
40 var rev int64
41 var got []KeyValueHash
42 for ; rev < totalRevisions; rev += testutil.CompactionCycle {
43 putKVs(s, rev, testutil.CompactionCycle)
44 hash := testHashByRev(t, s, rev+testutil.CompactionCycle/2)
45 got = append(got, hash)
46 }
47 putKVs(s, rev, totalRevisions)
48 hash := testHashByRev(t, s, rev+totalRevisions/2)
49 got = append(got, hash)
50 assert.Equal(t, []KeyValueHash{
51 {4082599214, -1, 35},
52 {2279933401, 35, 106},
53 {3284231217, 106, 177},
54 {126286495, 177, 248},
55 {900108730, 248, 319},
56 {2475485232, 319, 390},
57 {1226296507, 390, 461},
58 {2503661030, 461, 532},
59 {4155130747, 532, 603},
60 {106915399, 603, 674},
61 {406914006, 674, 745},
62 {1882211381, 745, 816},
63 {806177088, 816, 887},
64 {664311366, 887, 958},
65 {1496914449, 958, 1029},
66 {2434525091, 1029, 1100},
67 {3988652253, 1100, 1171},
68 {1122462288, 1171, 1242},
69 {724436716, 1242, 1883},
70 }, got)
71 }
72
73 func TestHashByRevValueLastRevision(t *testing.T) {
74 b, _ := betesting.NewDefaultTmpBackend(t)
75 s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{})
76
77 var totalRevisions int64 = 1210
78 assert.Less(t, int64(s.cfg.CompactionBatchLimit), totalRevisions)
79 assert.Less(t, int64(testutil.CompactionCycle*10), totalRevisions)
80 var rev int64
81 var got []KeyValueHash
82 for ; rev < totalRevisions; rev += testutil.CompactionCycle {
83 putKVs(s, rev, testutil.CompactionCycle)
84 hash := testHashByRev(t, s, 0)
85 got = append(got, hash)
86 }
87 putKVs(s, rev, totalRevisions)
88 hash := testHashByRev(t, s, 0)
89 got = append(got, hash)
90 assert.Equal(t, []KeyValueHash{
91 {1913897190, -1, 73},
92 {224860069, 73, 145},
93 {1565167519, 145, 217},
94 {1566261620, 217, 289},
95 {2037173024, 289, 361},
96 {691659396, 361, 433},
97 {2713730748, 433, 505},
98 {3919322507, 505, 577},
99 {769967540, 577, 649},
100 {2909194793, 649, 721},
101 {1576921157, 721, 793},
102 {4067701532, 793, 865},
103 {2226384237, 865, 937},
104 {2923408134, 937, 1009},
105 {2680329256, 1009, 1081},
106 {1546717673, 1081, 1153},
107 {2713657846, 1153, 1225},
108 {1046575299, 1225, 1297},
109 {2017735779, 1297, 2508},
110 }, got)
111 }
112
113 func putKVs(s *store, rev, count int64) {
114 for i := rev; i <= rev+count; i++ {
115 s.Put([]byte(testutil.PickKey(i)), []byte(fmt.Sprint(i)), 0)
116 }
117 }
118
119 func testHashByRev(t *testing.T, s *store, rev int64) KeyValueHash {
120 if rev == 0 {
121 rev = s.Rev()
122 }
123 hash, _, err := s.hashByRev(rev)
124 assert.NoError(t, err, "error on rev %v", rev)
125 _, err = s.Compact(traceutil.TODO(), rev)
126 assert.NoError(t, err, "error on compact %v", rev)
127 return hash
128 }
129
130
131
132 func TestCompactionHash(t *testing.T) {
133 b, _ := betesting.NewDefaultTmpBackend(t)
134 s := NewStore(zaptest.NewLogger(t), b, &lease.FakeLessor{}, StoreConfig{})
135
136 testutil.TestCompactionHash(context.Background(), t, hashTestCase{s}, s.cfg.CompactionBatchLimit)
137 }
138
139 type hashTestCase struct {
140 *store
141 }
142
143 func (tc hashTestCase) Put(ctx context.Context, key, value string) error {
144 tc.store.Put([]byte(key), []byte(value), 0)
145 return nil
146 }
147
148 func (tc hashTestCase) Delete(ctx context.Context, key string) error {
149 tc.store.DeleteRange([]byte(key), nil)
150 return nil
151 }
152
153 func (tc hashTestCase) HashByRev(ctx context.Context, rev int64) (testutil.KeyValueHash, error) {
154 hash, _, err := tc.store.HashStorage().HashByRev(rev)
155 return testutil.KeyValueHash{Hash: hash.Hash, CompactRevision: hash.CompactRevision, Revision: hash.Revision}, err
156 }
157
158 func (tc hashTestCase) Defrag(ctx context.Context) error {
159 return tc.store.b.Defrag()
160 }
161
162 func (tc hashTestCase) Compact(ctx context.Context, rev int64) error {
163 done, err := tc.store.Compact(traceutil.TODO(), rev)
164 if err != nil {
165 return err
166 }
167 select {
168 case <-done:
169 case <-ctx.Done():
170 return ctx.Err()
171 }
172 return nil
173 }
174
175 func TestHasherStore(t *testing.T) {
176 lg := zaptest.NewLogger(t)
177 s := newHashStorage(lg, newFakeStore())
178 var hashes []KeyValueHash
179 for i := 0; i < hashStorageMaxSize; i++ {
180 hash := KeyValueHash{Hash: uint32(i), Revision: int64(i) + 10, CompactRevision: int64(i) + 100}
181 hashes = append(hashes, hash)
182 s.Store(hash)
183 }
184
185 for _, want := range hashes {
186 got, _, err := s.HashByRev(want.Revision)
187 if err != nil {
188 t.Fatal(err)
189 }
190 if want.Hash != got.Hash {
191 t.Errorf("Expected stored hash to match, got: %d, expected: %d", want.Hash, got.Hash)
192 }
193 if want.Revision != got.Revision {
194 t.Errorf("Expected stored revision to match, got: %d, expected: %d", want.Revision, got.Revision)
195 }
196 if want.CompactRevision != got.CompactRevision {
197 t.Errorf("Expected stored compact revision to match, got: %d, expected: %d", want.CompactRevision, got.CompactRevision)
198 }
199 }
200 }
201
202 func TestHasherStoreFull(t *testing.T) {
203 lg := zaptest.NewLogger(t)
204 s := newHashStorage(lg, newFakeStore())
205 var minRevision int64 = 100
206 var maxRevision = minRevision + hashStorageMaxSize
207 for i := 0; i < hashStorageMaxSize; i++ {
208 s.Store(KeyValueHash{Revision: int64(i) + minRevision})
209 }
210
211
212 s.Store(KeyValueHash{Revision: minRevision - 1})
213 hash, _, err := s.HashByRev(minRevision - 1)
214 if err == nil {
215 t.Errorf("Expected an error as old revision should be discarded, got: %v", hash)
216 }
217
218 s.Store(KeyValueHash{Revision: maxRevision + 1})
219 _, _, err = s.HashByRev(maxRevision + 1)
220 if err != nil {
221 t.Errorf("Didn't expect error for new revision, err: %v", err)
222 }
223 }
224
View as plain text