storage_test.go 7.9 KB

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