go.etcd.io/etcd@v3.3.27+incompatible/raft/storage_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 raft 16 17 import ( 18 "math" 19 "reflect" 20 "testing" 21 22 pb "github.com/coreos/etcd/raft/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 // even if maxsize is zero, the first entry should be returned 78 {4, 7, 0, nil, []pb.Entry{{Index: 4, Term: 4}}}, 79 // limit to 2 80 {4, 7, uint64(ents[1].Size() + ents[2].Size()), nil, []pb.Entry{{Index: 4, Term: 4}, {Index: 5, Term: 5}}}, 81 // limit to 2 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 // all 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("term = %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, 5) 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{Nodes: []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: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}}, 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: 6}, {Index: 5, Term: 6}}, 220 nil, 221 []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 6}, {Index: 5, Term: 6}}, 222 }, 223 { 224 []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}, {Index: 6, Term: 5}}, 225 nil, 226 []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}, {Index: 6, Term: 5}}, 227 }, 228 // truncate incoming entries, truncate the existing entries and append 229 { 230 []pb.Entry{{Index: 2, Term: 3}, {Index: 3, Term: 3}, {Index: 4, Term: 5}}, 231 nil, 232 []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 5}}, 233 }, 234 // truncate the existing entries and append 235 { 236 []pb.Entry{{Index: 4, Term: 5}}, 237 nil, 238 []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 5}}, 239 }, 240 // direct append 241 { 242 []pb.Entry{{Index: 6, Term: 5}}, 243 nil, 244 []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}, {Index: 6, Term: 5}}, 245 }, 246 } 247 248 for i, tt := range tests { 249 s := &MemoryStorage{ents: ents} 250 err := s.Append(tt.entries) 251 if err != tt.werr { 252 t.Errorf("#%d: err = %v, want %v", i, err, tt.werr) 253 } 254 if !reflect.DeepEqual(s.ents, tt.wentries) { 255 t.Errorf("#%d: entries = %v, want %v", i, s.ents, tt.wentries) 256 } 257 } 258 } 259 260 func TestStorageApplySnapshot(t *testing.T) { 261 cs := &pb.ConfState{Nodes: []uint64{1, 2, 3}} 262 data := []byte("data") 263 264 tests := []pb.Snapshot{{Data: data, Metadata: pb.SnapshotMetadata{Index: 4, Term: 4, ConfState: *cs}}, 265 {Data: data, Metadata: pb.SnapshotMetadata{Index: 3, Term: 3, ConfState: *cs}}, 266 } 267 268 s := NewMemoryStorage() 269 270 //Apply Snapshot successful 271 i := 0 272 tt := tests[i] 273 err := s.ApplySnapshot(tt) 274 if err != nil { 275 t.Errorf("#%d: err = %v, want %v", i, err, nil) 276 } 277 278 //Apply Snapshot fails due to ErrSnapOutOfDate 279 i = 1 280 tt = tests[i] 281 err = s.ApplySnapshot(tt) 282 if err != ErrSnapOutOfDate { 283 t.Errorf("#%d: err = %v, want %v", i, err, ErrSnapOutOfDate) 284 } 285 }