1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package raft
16
17 import (
18 "math"
19 "reflect"
20 "testing"
21
22 pb "go.etcd.io/etcd/raft/v3/raftpb"
23 )
24
25 func TestStorageTerm(t *testing.T) {
26 ents := []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}}
27 tests := []struct {
28 i uint64
29
30 werr error
31 wterm uint64
32 wpanic bool
33 }{
34 {2, ErrCompacted, 0, false},
35 {3, nil, 3, false},
36 {4, nil, 4, false},
37 {5, nil, 5, false},
38 {6, ErrUnavailable, 0, false},
39 }
40
41 for i, tt := range tests {
42 s := &MemoryStorage{ents: ents}
43
44 func() {
45 defer func() {
46 if r := recover(); r != nil {
47 if !tt.wpanic {
48 t.Errorf("%d: panic = %v, want %v", i, true, tt.wpanic)
49 }
50 }
51 }()
52
53 term, err := s.Term(tt.i)
54 if err != tt.werr {
55 t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
56 }
57 if term != tt.wterm {
58 t.Errorf("#%d: term = %d, want %d", i, term, tt.wterm)
59 }
60 }()
61 }
62 }
63
64 func TestStorageEntries(t *testing.T) {
65 ents := []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}, {Index: 6, Term: 6}}
66 tests := []struct {
67 lo, hi, maxsize uint64
68
69 werr error
70 wentries []pb.Entry
71 }{
72 {2, 6, math.MaxUint64, ErrCompacted, nil},
73 {3, 4, math.MaxUint64, ErrCompacted, nil},
74 {4, 5, math.MaxUint64, nil, []pb.Entry{{Index: 4, Term: 4}}},
75 {4, 6, math.MaxUint64, nil, []pb.Entry{{Index: 4, Term: 4}, {Index: 5, Term: 5}}},
76 {4, 7, math.MaxUint64, nil, []pb.Entry{{Index: 4, Term: 4}, {Index: 5, Term: 5}, {Index: 6, Term: 6}}},
77
78 {4, 7, 0, nil, []pb.Entry{{Index: 4, Term: 4}}},
79
80 {4, 7, uint64(ents[1].Size() + ents[2].Size()), nil, []pb.Entry{{Index: 4, Term: 4}, {Index: 5, Term: 5}}},
81
82 {4, 7, uint64(ents[1].Size() + ents[2].Size() + ents[3].Size()/2), nil, []pb.Entry{{Index: 4, Term: 4}, {Index: 5, Term: 5}}},
83 {4, 7, uint64(ents[1].Size() + ents[2].Size() + ents[3].Size() - 1), nil, []pb.Entry{{Index: 4, Term: 4}, {Index: 5, Term: 5}}},
84
85 {4, 7, uint64(ents[1].Size() + ents[2].Size() + ents[3].Size()), nil, []pb.Entry{{Index: 4, Term: 4}, {Index: 5, Term: 5}, {Index: 6, Term: 6}}},
86 }
87
88 for i, tt := range tests {
89 s := &MemoryStorage{ents: ents}
90 entries, err := s.Entries(tt.lo, tt.hi, tt.maxsize)
91 if err != tt.werr {
92 t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
93 }
94 if !reflect.DeepEqual(entries, tt.wentries) {
95 t.Errorf("#%d: entries = %v, want %v", i, entries, tt.wentries)
96 }
97 }
98 }
99
100 func TestStorageLastIndex(t *testing.T) {
101 ents := []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}}
102 s := &MemoryStorage{ents: ents}
103
104 last, err := s.LastIndex()
105 if err != nil {
106 t.Errorf("err = %v, want nil", err)
107 }
108 if last != 5 {
109 t.Errorf("last = %d, want %d", last, 5)
110 }
111
112 s.Append([]pb.Entry{{Index: 6, Term: 5}})
113 last, err = s.LastIndex()
114 if err != nil {
115 t.Errorf("err = %v, want nil", err)
116 }
117 if last != 6 {
118 t.Errorf("last = %d, want %d", last, 6)
119 }
120 }
121
122 func TestStorageFirstIndex(t *testing.T) {
123 ents := []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}}
124 s := &MemoryStorage{ents: ents}
125
126 first, err := s.FirstIndex()
127 if err != nil {
128 t.Errorf("err = %v, want nil", err)
129 }
130 if first != 4 {
131 t.Errorf("first = %d, want %d", first, 4)
132 }
133
134 s.Compact(4)
135 first, err = s.FirstIndex()
136 if err != nil {
137 t.Errorf("err = %v, want nil", err)
138 }
139 if first != 5 {
140 t.Errorf("first = %d, want %d", first, 5)
141 }
142 }
143
144 func TestStorageCompact(t *testing.T) {
145 ents := []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}}
146 tests := []struct {
147 i uint64
148
149 werr error
150 windex uint64
151 wterm uint64
152 wlen int
153 }{
154 {2, ErrCompacted, 3, 3, 3},
155 {3, ErrCompacted, 3, 3, 3},
156 {4, nil, 4, 4, 2},
157 {5, nil, 5, 5, 1},
158 }
159
160 for i, tt := range tests {
161 s := &MemoryStorage{ents: ents}
162 err := s.Compact(tt.i)
163 if err != tt.werr {
164 t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
165 }
166 if s.ents[0].Index != tt.windex {
167 t.Errorf("#%d: index = %d, want %d", i, s.ents[0].Index, tt.windex)
168 }
169 if s.ents[0].Term != tt.wterm {
170 t.Errorf("#%d: term = %d, want %d", i, s.ents[0].Term, tt.wterm)
171 }
172 if len(s.ents) != tt.wlen {
173 t.Errorf("#%d: len = %d, want %d", i, len(s.ents), tt.wlen)
174 }
175 }
176 }
177
178 func TestStorageCreateSnapshot(t *testing.T) {
179 ents := []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}}
180 cs := &pb.ConfState{Voters: []uint64{1, 2, 3}}
181 data := []byte("data")
182
183 tests := []struct {
184 i uint64
185
186 werr error
187 wsnap pb.Snapshot
188 }{
189 {4, nil, pb.Snapshot{Data: data, Metadata: pb.SnapshotMetadata{Index: 4, Term: 4, ConfState: *cs}}},
190 {5, nil, pb.Snapshot{Data: data, Metadata: pb.SnapshotMetadata{Index: 5, Term: 5, ConfState: *cs}}},
191 }
192
193 for i, tt := range tests {
194 s := &MemoryStorage{ents: ents}
195 snap, err := s.CreateSnapshot(tt.i, cs, data)
196 if err != tt.werr {
197 t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
198 }
199 if !reflect.DeepEqual(snap, tt.wsnap) {
200 t.Errorf("#%d: snap = %+v, want %+v", i, snap, tt.wsnap)
201 }
202 }
203 }
204
205 func TestStorageAppend(t *testing.T) {
206 ents := []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}}
207 tests := []struct {
208 entries []pb.Entry
209
210 werr error
211 wentries []pb.Entry
212 }{
213 {
214 []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}},
215 nil,
216 []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}},
217 },
218 {
219 []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}},
220 nil,
221 []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}},
222 },
223 {
224 []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 6}, {Index: 5, Term: 6}},
225 nil,
226 []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 6}, {Index: 5, Term: 6}},
227 },
228 {
229 []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}, {Index: 6, Term: 5}},
230 nil,
231 []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}, {Index: 6, Term: 5}},
232 },
233
234 {
235 []pb.Entry{{Index: 2, Term: 3}, {Index: 3, Term: 3}, {Index: 4, Term: 5}},
236 nil,
237 []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 5}},
238 },
239
240 {
241 []pb.Entry{{Index: 4, Term: 5}},
242 nil,
243 []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 5}},
244 },
245
246 {
247 []pb.Entry{{Index: 6, Term: 5}},
248 nil,
249 []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}, {Index: 6, Term: 5}},
250 },
251 }
252
253 for i, tt := range tests {
254 s := &MemoryStorage{ents: ents}
255 err := s.Append(tt.entries)
256 if err != tt.werr {
257 t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
258 }
259 if !reflect.DeepEqual(s.ents, tt.wentries) {
260 t.Errorf("#%d: entries = %v, want %v", i, s.ents, tt.wentries)
261 }
262 }
263 }
264
265 func TestStorageApplySnapshot(t *testing.T) {
266 cs := &pb.ConfState{Voters: []uint64{1, 2, 3}}
267 data := []byte("data")
268
269 tests := []pb.Snapshot{{Data: data, Metadata: pb.SnapshotMetadata{Index: 4, Term: 4, ConfState: *cs}},
270 {Data: data, Metadata: pb.SnapshotMetadata{Index: 3, Term: 3, ConfState: *cs}},
271 }
272
273 s := NewMemoryStorage()
274
275
276 i := 0
277 tt := tests[i]
278 err := s.ApplySnapshot(tt)
279 if err != nil {
280 t.Errorf("#%d: err = %v, want %v", i, err, nil)
281 }
282
283
284 i = 1
285 tt = tests[i]
286 err = s.ApplySnapshot(tt)
287 if err != ErrSnapOutOfDate {
288 t.Errorf("#%d: err = %v, want %v", i, err, ErrSnapOutOfDate)
289 }
290 }
291
View as plain text