log_test.go 4.2 KB

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