log_test.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. package raft
  2. import (
  3. "reflect"
  4. "testing"
  5. )
  6. // TestCompactionSideEffects ensures that all the log related funcationality works correctly after
  7. // a compaction.
  8. func TestCompactionSideEffects(t *testing.T) {
  9. var i int64
  10. lastIndex := int64(1000)
  11. log := newLog()
  12. for i = 0; i < lastIndex; i++ {
  13. log.append(int64(i), Entry{Term: int64(i + 1)})
  14. }
  15. log.compact(500)
  16. if log.lastIndex() != lastIndex {
  17. t.Errorf("lastIndex = %d, want %d", log.lastIndex(), lastIndex)
  18. }
  19. for i := log.offset; i <= log.lastIndex(); i++ {
  20. if log.term(i) != i {
  21. t.Errorf("term(%d) = %d, want %d", i, log.term(i), i)
  22. }
  23. }
  24. for i := log.offset; i <= log.lastIndex(); i++ {
  25. if !log.matchTerm(i, i) {
  26. t.Errorf("matchTerm(%d) = false, want true", i)
  27. }
  28. }
  29. prev := log.lastIndex()
  30. log.append(log.lastIndex(), Entry{Term: log.lastIndex() + 1})
  31. if log.lastIndex() != prev+1 {
  32. t.Errorf("lastIndex = %d, want = %d", log.lastIndex(), prev+1)
  33. }
  34. ents := log.entries(log.lastIndex())
  35. if len(ents) != 1 {
  36. t.Errorf("len(entries) = %d, want = %d", len(ents), 1)
  37. }
  38. }
  39. //TestCompaction ensures that the number of log entreis is correct after compactions.
  40. func TestCompaction(t *testing.T) {
  41. tests := []struct {
  42. app int
  43. compact []int64
  44. wleft []int
  45. wallow bool
  46. }{
  47. // out of upper bound
  48. {1000, []int64{1001}, []int{-1}, false},
  49. {1000, []int64{300, 500, 800, 900}, []int{701, 501, 201, 101}, true},
  50. // out of lower bound
  51. {1000, []int64{300, 299}, []int{701, -1}, false},
  52. }
  53. for i, tt := range tests {
  54. func() {
  55. defer func() {
  56. if r := recover(); r != nil {
  57. if tt.wallow == true {
  58. t.Errorf("%d: allow = %v, want %v", i, false, true)
  59. }
  60. }
  61. }()
  62. log := newLog()
  63. for i := 0; i < tt.app; i++ {
  64. log.append(int64(i), Entry{})
  65. }
  66. for j := 0; j < len(tt.compact); j++ {
  67. log.compact(tt.compact[j])
  68. if len(log.ents) != tt.wleft[j] {
  69. t.Errorf("#%d.%d len = %d, want %d", i, j, len(log.ents), tt.wleft[j])
  70. }
  71. }
  72. }()
  73. }
  74. }
  75. func TestLogRestore(t *testing.T) {
  76. var i int64
  77. log := newLog()
  78. for i = 0; i < 100; i++ {
  79. log.append(i, Entry{Term: i + 1})
  80. }
  81. index := int64(1000)
  82. term := int64(1000)
  83. log.restore(index, term)
  84. // only has the guard entry
  85. if len(log.ents) != 1 {
  86. t.Errorf("len = %d, want 0", len(log.ents))
  87. }
  88. if log.offset != index {
  89. t.Errorf("offset = %d, want %d", log.offset, index)
  90. }
  91. if log.applied != index {
  92. t.Errorf("applied = %d, want %d", log.applied, index)
  93. }
  94. if log.committed != index {
  95. t.Errorf("comitted = %d, want %d", log.committed, index)
  96. }
  97. if log.term(index) != term {
  98. t.Errorf("term = %d, want %d", log.term(index), term)
  99. }
  100. }
  101. func TestIsOutOfBounds(t *testing.T) {
  102. offset := int64(100)
  103. num := int64(100)
  104. l := &log{offset: offset, ents: make([]Entry, num)}
  105. tests := []struct {
  106. index int64
  107. w bool
  108. }{
  109. {offset - 1, true},
  110. {offset, false},
  111. {offset + num/2, false},
  112. {offset + num - 1, false},
  113. {offset + num, true},
  114. }
  115. for i, tt := range tests {
  116. g := l.isOutOfBounds(tt.index)
  117. if g != tt.w {
  118. t.Errorf("#%d: isOutOfBounds = %v, want %v", i, g, tt.w)
  119. }
  120. }
  121. }
  122. func TestAt(t *testing.T) {
  123. var i int64
  124. offset := int64(100)
  125. num := int64(100)
  126. l := &log{offset: offset}
  127. for i = 0; i < num; i++ {
  128. l.ents = append(l.ents, Entry{Term: i})
  129. }
  130. tests := []struct {
  131. index int64
  132. w *Entry
  133. }{
  134. {offset - 1, nil},
  135. {offset, &Entry{Term: 0}},
  136. {offset + num/2, &Entry{Term: num / 2}},
  137. {offset + num - 1, &Entry{Term: num - 1}},
  138. {offset + num, nil},
  139. }
  140. for i, tt := range tests {
  141. g := l.at(tt.index)
  142. if !reflect.DeepEqual(g, tt.w) {
  143. t.Errorf("#%d: at = %v, want %v", i, g, tt.w)
  144. }
  145. }
  146. }
  147. func TestSlice(t *testing.T) {
  148. var i int64
  149. offset := int64(100)
  150. num := int64(100)
  151. l := &log{offset: offset}
  152. for i = 0; i < num; i++ {
  153. l.ents = append(l.ents, Entry{Term: i})
  154. }
  155. tests := []struct {
  156. from int64
  157. to int64
  158. w []Entry
  159. }{
  160. {offset - 1, offset + 1, nil},
  161. {offset, offset + 1, []Entry{{Term: 0}}},
  162. {offset + num/2, offset + num/2 + 1, []Entry{{Term: num / 2}}},
  163. {offset + num - 1, offset + num, []Entry{{Term: num - 1}}},
  164. {offset + num, offset + num + 1, nil},
  165. {offset + num/2, offset + num/2, nil},
  166. {offset + num/2, offset + num/2 - 1, nil},
  167. }
  168. for i, tt := range tests {
  169. g := l.slice(tt.from, tt.to)
  170. if !reflect.DeepEqual(g, tt.w) {
  171. t.Errorf("#%d: from %d to %d = %v, want %v", i, tt.from, tt.to, g, tt.w)
  172. }
  173. }
  174. }