log_test.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  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. // TestAppend ensures:
  20. // 1. If an existing entry conflicts with a new one (same index
  21. // but different terms), delete the existing entry and all that
  22. // follow it
  23. // 2.Append any new entries not already in the log
  24. func TestAppend(t *testing.T) {
  25. previousEnts := []pb.Entry{{Term: 1}, {Term: 2}}
  26. previousUnstable := uint64(3)
  27. tests := []struct {
  28. after uint64
  29. ents []pb.Entry
  30. windex uint64
  31. wents []pb.Entry
  32. wunstable uint64
  33. }{
  34. {
  35. 2,
  36. []pb.Entry{},
  37. 2,
  38. []pb.Entry{{Term: 1}, {Term: 2}},
  39. 3,
  40. },
  41. {
  42. 2,
  43. []pb.Entry{{Term: 2}},
  44. 3,
  45. []pb.Entry{{Term: 1}, {Term: 2}, {Term: 2}},
  46. 3,
  47. },
  48. // conflicts with index 1
  49. {
  50. 0,
  51. []pb.Entry{{Term: 2}},
  52. 1,
  53. []pb.Entry{{Term: 2}},
  54. 1,
  55. },
  56. // conflicts with index 2
  57. {
  58. 1,
  59. []pb.Entry{{Term: 3}, {Term: 3}},
  60. 3,
  61. []pb.Entry{{Term: 1}, {Term: 3}, {Term: 3}},
  62. 2,
  63. },
  64. }
  65. for i, tt := range tests {
  66. raftLog := newLog()
  67. raftLog.ents = append(raftLog.ents, previousEnts...)
  68. raftLog.unstable = previousUnstable
  69. index := raftLog.append(tt.after, tt.ents...)
  70. if index != tt.windex {
  71. t.Errorf("#%d: lastIndex = %d, want %d", i, index, tt.windex)
  72. }
  73. if g := raftLog.entries(1); !reflect.DeepEqual(g, tt.wents) {
  74. t.Errorf("#%d: logEnts = %+v, want %+v", i, g, tt.wents)
  75. }
  76. if g := raftLog.unstable; g != tt.wunstable {
  77. t.Errorf("#%d: unstable = %d, want %d", i, g, tt.wunstable)
  78. }
  79. }
  80. }
  81. // TestCompactionSideEffects ensures that all the log related funcationality works correctly after
  82. // a compaction.
  83. func TestCompactionSideEffects(t *testing.T) {
  84. var i uint64
  85. lastIndex := uint64(1000)
  86. lastTerm := lastIndex
  87. raftLog := newLog()
  88. for i = 0; i < lastIndex; i++ {
  89. raftLog.append(uint64(i), pb.Entry{Term: uint64(i + 1), Index: uint64(i + 1)})
  90. }
  91. raftLog.maybeCommit(lastIndex, lastTerm)
  92. raftLog.resetNextEnts()
  93. raftLog.compact(500)
  94. if raftLog.lastIndex() != lastIndex {
  95. t.Errorf("lastIndex = %d, want %d", raftLog.lastIndex(), lastIndex)
  96. }
  97. for i := raftLog.offset; i <= raftLog.lastIndex(); i++ {
  98. if raftLog.term(i) != i {
  99. t.Errorf("term(%d) = %d, want %d", i, raftLog.term(i), i)
  100. }
  101. }
  102. for i := raftLog.offset; i <= raftLog.lastIndex(); i++ {
  103. if !raftLog.matchTerm(i, i) {
  104. t.Errorf("matchTerm(%d) = false, want true", i)
  105. }
  106. }
  107. unstableEnts := raftLog.unstableEnts()
  108. if g := len(unstableEnts); g != 500 {
  109. t.Errorf("len(unstableEntries) = %d, want = %d", g, 500)
  110. }
  111. if unstableEnts[0].Index != 501 {
  112. t.Errorf("Index = %d, want = %d", unstableEnts[0].Index, 501)
  113. }
  114. prev := raftLog.lastIndex()
  115. raftLog.append(raftLog.lastIndex(), pb.Entry{Term: raftLog.lastIndex() + 1})
  116. if raftLog.lastIndex() != prev+1 {
  117. t.Errorf("lastIndex = %d, want = %d", raftLog.lastIndex(), prev+1)
  118. }
  119. ents := raftLog.entries(raftLog.lastIndex())
  120. if len(ents) != 1 {
  121. t.Errorf("len(entries) = %d, want = %d", len(ents), 1)
  122. }
  123. }
  124. func TestUnstableEnts(t *testing.T) {
  125. previousEnts := []pb.Entry{{Term: 1, Index: 1}, {Term: 2, Index: 2}}
  126. tests := []struct {
  127. unstable uint64
  128. wents []pb.Entry
  129. wunstable uint64
  130. }{
  131. {3, nil, 3},
  132. {1, previousEnts, 3},
  133. }
  134. for i, tt := range tests {
  135. raftLog := newLog()
  136. raftLog.ents = append(raftLog.ents, previousEnts...)
  137. raftLog.unstable = tt.unstable
  138. ents := raftLog.unstableEnts()
  139. raftLog.resetUnstable()
  140. if !reflect.DeepEqual(ents, tt.wents) {
  141. t.Errorf("#%d: unstableEnts = %+v, want %+v", i, ents, tt.wents)
  142. }
  143. if g := raftLog.unstable; g != tt.wunstable {
  144. t.Errorf("#%d: unstable = %d, want %d", i, g, tt.wunstable)
  145. }
  146. }
  147. }
  148. //TestCompaction ensures that the number of log entreis is correct after compactions.
  149. func TestCompaction(t *testing.T) {
  150. tests := []struct {
  151. applied uint64
  152. lastIndex uint64
  153. compact []uint64
  154. wleft []int
  155. wallow bool
  156. }{
  157. // out of upper bound
  158. {1000, 1000, []uint64{1001}, []int{-1}, false},
  159. {1000, 1000, []uint64{300, 500, 800, 900}, []int{701, 501, 201, 101}, true},
  160. // out of lower bound
  161. {1000, 1000, []uint64{300, 299}, []int{701, -1}, false},
  162. {0, 1000, []uint64{1}, []int{-1}, false},
  163. }
  164. for i, tt := range tests {
  165. func() {
  166. defer func() {
  167. if r := recover(); r != nil {
  168. if tt.wallow == true {
  169. t.Errorf("%d: allow = %v, want %v", i, false, true)
  170. }
  171. }
  172. }()
  173. raftLog := newLog()
  174. for i := uint64(0); i < tt.lastIndex; i++ {
  175. raftLog.append(uint64(i), pb.Entry{})
  176. }
  177. raftLog.maybeCommit(tt.applied, 0)
  178. raftLog.resetNextEnts()
  179. for j := 0; j < len(tt.compact); j++ {
  180. raftLog.compact(tt.compact[j])
  181. if len(raftLog.ents) != tt.wleft[j] {
  182. t.Errorf("#%d.%d len = %d, want %d", i, j, len(raftLog.ents), tt.wleft[j])
  183. }
  184. }
  185. }()
  186. }
  187. }
  188. func TestLogRestore(t *testing.T) {
  189. var i uint64
  190. raftLog := newLog()
  191. for i = 0; i < 100; i++ {
  192. raftLog.append(i, pb.Entry{Term: i + 1})
  193. }
  194. index := uint64(1000)
  195. term := uint64(1000)
  196. raftLog.restore(pb.Snapshot{Index: index, Term: term})
  197. // only has the guard entry
  198. if len(raftLog.ents) != 1 {
  199. t.Errorf("len = %d, want 0", len(raftLog.ents))
  200. }
  201. if raftLog.offset != index {
  202. t.Errorf("offset = %d, want %d", raftLog.offset, index)
  203. }
  204. if raftLog.applied != index {
  205. t.Errorf("applied = %d, want %d", raftLog.applied, index)
  206. }
  207. if raftLog.committed != index {
  208. t.Errorf("comitted = %d, want %d", raftLog.committed, index)
  209. }
  210. if raftLog.unstable != index+1 {
  211. t.Errorf("unstable = %d, want %d", raftLog.unstable, index+1)
  212. }
  213. if raftLog.term(index) != term {
  214. t.Errorf("term = %d, want %d", raftLog.term(index), term)
  215. }
  216. }
  217. func TestIsOutOfBounds(t *testing.T) {
  218. offset := uint64(100)
  219. num := uint64(100)
  220. l := &raftLog{offset: offset, ents: make([]pb.Entry, num)}
  221. tests := []struct {
  222. index uint64
  223. w bool
  224. }{
  225. {offset - 1, true},
  226. {offset, false},
  227. {offset + num/2, false},
  228. {offset + num - 1, false},
  229. {offset + num, true},
  230. }
  231. for i, tt := range tests {
  232. g := l.isOutOfBounds(tt.index)
  233. if g != tt.w {
  234. t.Errorf("#%d: isOutOfBounds = %v, want %v", i, g, tt.w)
  235. }
  236. }
  237. }
  238. func TestAt(t *testing.T) {
  239. var i uint64
  240. offset := uint64(100)
  241. num := uint64(100)
  242. l := &raftLog{offset: offset}
  243. for i = 0; i < num; i++ {
  244. l.ents = append(l.ents, pb.Entry{Term: i})
  245. }
  246. tests := []struct {
  247. index uint64
  248. w *pb.Entry
  249. }{
  250. {offset - 1, nil},
  251. {offset, &pb.Entry{Term: 0}},
  252. {offset + num/2, &pb.Entry{Term: num / 2}},
  253. {offset + num - 1, &pb.Entry{Term: num - 1}},
  254. {offset + num, nil},
  255. }
  256. for i, tt := range tests {
  257. g := l.at(tt.index)
  258. if !reflect.DeepEqual(g, tt.w) {
  259. t.Errorf("#%d: at = %v, want %v", i, g, tt.w)
  260. }
  261. }
  262. }
  263. func TestSlice(t *testing.T) {
  264. var i uint64
  265. offset := uint64(100)
  266. num := uint64(100)
  267. l := &raftLog{offset: offset}
  268. for i = 0; i < num; i++ {
  269. l.ents = append(l.ents, pb.Entry{Term: i})
  270. }
  271. tests := []struct {
  272. from uint64
  273. to uint64
  274. w []pb.Entry
  275. }{
  276. {offset - 1, offset + 1, nil},
  277. {offset, offset + 1, []pb.Entry{{Term: 0}}},
  278. {offset + num/2, offset + num/2 + 1, []pb.Entry{{Term: num / 2}}},
  279. {offset + num - 1, offset + num, []pb.Entry{{Term: num - 1}}},
  280. {offset + num, offset + num + 1, nil},
  281. {offset + num/2, offset + num/2, nil},
  282. {offset + num/2, offset + num/2 - 1, nil},
  283. }
  284. for i, tt := range tests {
  285. g := l.slice(tt.from, tt.to)
  286. if !reflect.DeepEqual(g, tt.w) {
  287. t.Errorf("#%d: from %d to %d = %v, want %v", i, tt.from, tt.to, g, tt.w)
  288. }
  289. }
  290. }