log_unstable_test.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /*
  2. Copyright 2014 CoreOS, Inc.
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package raft
  14. import (
  15. "reflect"
  16. "testing"
  17. pb "github.com/coreos/etcd/raft/raftpb"
  18. )
  19. func TestUnstableMaybeFirstIndex(t *testing.T) {
  20. tests := []struct {
  21. entries []pb.Entry
  22. offset uint64
  23. snap *pb.Snapshot
  24. wok bool
  25. windex uint64
  26. }{
  27. // no snapshot
  28. {
  29. []pb.Entry{{Index: 5, Term: 1}}, 5, nil,
  30. false, 0,
  31. },
  32. {
  33. []pb.Entry{}, 0, nil,
  34. false, 0,
  35. },
  36. // has snapshot
  37. {
  38. []pb.Entry{{Index: 5, Term: 1}}, 5, &pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: 4, Term: 1}},
  39. true, 5,
  40. },
  41. {
  42. []pb.Entry{}, 5, &pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: 4, Term: 1}},
  43. true, 5,
  44. },
  45. }
  46. for i, tt := range tests {
  47. u := unstable{
  48. entries: tt.entries,
  49. offset: tt.offset,
  50. snapshot: tt.snap,
  51. }
  52. index, ok := u.maybeFirstIndex()
  53. if ok != tt.wok {
  54. t.Errorf("#%d: ok = %t, want %t", i, ok, tt.wok)
  55. }
  56. if index != tt.windex {
  57. t.Errorf("#%d: index = %d, want %d", i, index, tt.windex)
  58. }
  59. }
  60. }
  61. func TestMaybeLastIndex(t *testing.T) {
  62. tests := []struct {
  63. entries []pb.Entry
  64. offset uint64
  65. snap *pb.Snapshot
  66. wok bool
  67. windex uint64
  68. }{
  69. // last in entries
  70. {
  71. []pb.Entry{{Index: 5, Term: 1}}, 5, nil,
  72. true, 5,
  73. },
  74. {
  75. []pb.Entry{{Index: 5, Term: 1}}, 5, &pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: 4, Term: 1}},
  76. true, 5,
  77. },
  78. // last in snapshot
  79. {
  80. []pb.Entry{}, 5, &pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: 4, Term: 1}},
  81. true, 4,
  82. },
  83. // empty unstable
  84. {
  85. []pb.Entry{}, 0, nil,
  86. false, 0,
  87. },
  88. }
  89. for i, tt := range tests {
  90. u := unstable{
  91. entries: tt.entries,
  92. offset: tt.offset,
  93. snapshot: tt.snap,
  94. }
  95. index, ok := u.maybeLastIndex()
  96. if ok != tt.wok {
  97. t.Errorf("#%d: ok = %t, want %t", i, ok, tt.wok)
  98. }
  99. if index != tt.windex {
  100. t.Errorf("#%d: index = %d, want %d", i, index, tt.windex)
  101. }
  102. }
  103. }
  104. func TestUnstableMaybeTerm(t *testing.T) {
  105. tests := []struct {
  106. entries []pb.Entry
  107. offset uint64
  108. snap *pb.Snapshot
  109. index uint64
  110. wok bool
  111. wterm uint64
  112. }{
  113. // term from entries
  114. {
  115. []pb.Entry{{Index: 5, Term: 1}}, 5, nil,
  116. 5,
  117. true, 1,
  118. },
  119. {
  120. []pb.Entry{{Index: 5, Term: 1}}, 5, nil,
  121. 6,
  122. false, 0,
  123. },
  124. {
  125. []pb.Entry{{Index: 5, Term: 1}}, 5, nil,
  126. 4,
  127. false, 0,
  128. },
  129. {
  130. []pb.Entry{{Index: 5, Term: 1}}, 5, &pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: 4, Term: 1}},
  131. 5,
  132. true, 1,
  133. },
  134. {
  135. []pb.Entry{{Index: 5, Term: 1}}, 5, &pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: 4, Term: 1}},
  136. 6,
  137. false, 0,
  138. },
  139. // term from snapshot
  140. {
  141. []pb.Entry{{Index: 5, Term: 1}}, 5, &pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: 4, Term: 1}},
  142. 4,
  143. true, 1,
  144. },
  145. {
  146. []pb.Entry{}, 5, &pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: 4, Term: 1}},
  147. 5,
  148. false, 0,
  149. },
  150. {
  151. []pb.Entry{}, 5, &pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: 4, Term: 1}},
  152. 4,
  153. true, 1,
  154. },
  155. {
  156. []pb.Entry{}, 0, nil,
  157. 5,
  158. false, 0,
  159. },
  160. }
  161. for i, tt := range tests {
  162. u := unstable{
  163. entries: tt.entries,
  164. offset: tt.offset,
  165. snapshot: tt.snap,
  166. }
  167. term, ok := u.maybeTerm(tt.index)
  168. if ok != tt.wok {
  169. t.Errorf("#%d: ok = %t, want %t", i, ok, tt.wok)
  170. }
  171. if term != tt.wterm {
  172. t.Errorf("#%d: term = %d, want %d", i, term, tt.wterm)
  173. }
  174. }
  175. }
  176. func TestUnstableRestore(t *testing.T) {
  177. u := unstable{
  178. entries: []pb.Entry{{Index: 5, Term: 1}},
  179. offset: 5,
  180. snapshot: &pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: 4, Term: 1}},
  181. }
  182. s := pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: 6, Term: 2}}
  183. u.restore(s)
  184. if u.offset != s.Metadata.Index+1 {
  185. t.Errorf("offset = %d, want %d", u.offset, s.Metadata.Index+1)
  186. }
  187. if len(u.entries) != 0 {
  188. t.Errorf("len = %d, want 0", len(u.entries))
  189. }
  190. if !reflect.DeepEqual(u.snapshot, &s) {
  191. t.Errorf("snap = %v, want %v", u.snapshot, &s)
  192. }
  193. }
  194. func TestUnstableStableTo(t *testing.T) {
  195. tests := []struct {
  196. entries []pb.Entry
  197. offset uint64
  198. snap *pb.Snapshot
  199. index, term uint64
  200. woffset uint64
  201. wlen int
  202. }{
  203. {
  204. []pb.Entry{}, 0, nil,
  205. 5, 1,
  206. 0, 0,
  207. },
  208. {
  209. []pb.Entry{{Index: 5, Term: 1}}, 5, nil,
  210. 5, 1, // stable to the first entry
  211. 6, 0,
  212. },
  213. {
  214. []pb.Entry{{Index: 5, Term: 1}, {Index: 6, Term: 1}}, 5, nil,
  215. 5, 1, // stable to the first entry
  216. 6, 1,
  217. },
  218. {
  219. []pb.Entry{{Index: 6, Term: 2}}, 5, nil,
  220. 6, 1, // stable to the first entry and term mismatch
  221. 5, 1,
  222. },
  223. {
  224. []pb.Entry{{Index: 5, Term: 1}}, 5, nil,
  225. 4, 1, // stable to old entry
  226. 5, 1,
  227. },
  228. {
  229. []pb.Entry{{Index: 5, Term: 1}}, 5, nil,
  230. 4, 2, // stable to old entry
  231. 5, 1,
  232. },
  233. // with snapshot
  234. {
  235. []pb.Entry{{Index: 5, Term: 1}}, 5, &pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: 4, Term: 1}},
  236. 5, 1, // stable to the first entry
  237. 6, 0,
  238. },
  239. {
  240. []pb.Entry{{Index: 5, Term: 1}, {Index: 6, Term: 1}}, 5, &pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: 4, Term: 1}},
  241. 5, 1, // stable to the first entry
  242. 6, 1,
  243. },
  244. {
  245. []pb.Entry{{Index: 6, Term: 2}}, 5, &pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: 5, Term: 1}},
  246. 6, 1, // stable to the first entry and term mismatch
  247. 5, 1,
  248. },
  249. {
  250. []pb.Entry{{Index: 5, Term: 1}}, 5, &pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: 4, Term: 1}},
  251. 4, 1, // stable to snapshot
  252. 5, 1,
  253. },
  254. {
  255. []pb.Entry{{Index: 5, Term: 2}}, 5, &pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: 4, Term: 2}},
  256. 4, 1, // stable to old entry
  257. 5, 1,
  258. },
  259. }
  260. for i, tt := range tests {
  261. u := unstable{
  262. entries: tt.entries,
  263. offset: tt.offset,
  264. snapshot: tt.snap,
  265. }
  266. u.stableTo(tt.index, tt.term)
  267. if u.offset != tt.woffset {
  268. t.Errorf("#%d: offset = %d, want %d", i, u.offset, tt.woffset)
  269. }
  270. if len(u.entries) != tt.wlen {
  271. t.Errorf("#%d: len = %d, want %d", i, len(u.entries), tt.wlen)
  272. }
  273. }
  274. }