progress_test.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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 tracker
  15. import (
  16. "testing"
  17. )
  18. func TestProgressString(t *testing.T) {
  19. ins := NewInflights(1)
  20. ins.Add(123)
  21. pr := &Progress{
  22. Match: 1,
  23. Next: 2,
  24. State: StateSnapshot,
  25. PendingSnapshot: 123,
  26. RecentActive: false,
  27. ProbeSent: true,
  28. IsLearner: true,
  29. Inflights: ins,
  30. }
  31. const exp = `StateSnapshot match=1 next=2 learner paused pendingSnap=123 inactive inflight=1[full]`
  32. if act := pr.String(); act != exp {
  33. t.Errorf("exp: %s\nact: %s", exp, act)
  34. }
  35. }
  36. func TestProgressIsPaused(t *testing.T) {
  37. tests := []struct {
  38. state StateType
  39. paused bool
  40. w bool
  41. }{
  42. {StateProbe, false, false},
  43. {StateProbe, true, true},
  44. {StateReplicate, false, false},
  45. {StateReplicate, true, false},
  46. {StateSnapshot, false, true},
  47. {StateSnapshot, true, true},
  48. }
  49. for i, tt := range tests {
  50. p := &Progress{
  51. State: tt.state,
  52. ProbeSent: tt.paused,
  53. Inflights: NewInflights(256),
  54. }
  55. if g := p.IsPaused(); g != tt.w {
  56. t.Errorf("#%d: paused= %t, want %t", i, g, tt.w)
  57. }
  58. }
  59. }
  60. // TestProgressResume ensures that MaybeUpdate and MaybeDecrTo will reset
  61. // ProbeSent.
  62. func TestProgressResume(t *testing.T) {
  63. p := &Progress{
  64. Next: 2,
  65. ProbeSent: true,
  66. }
  67. p.MaybeDecrTo(1, 1)
  68. if p.ProbeSent {
  69. t.Errorf("paused= %v, want false", p.ProbeSent)
  70. }
  71. p.ProbeSent = true
  72. p.MaybeUpdate(2)
  73. if p.ProbeSent {
  74. t.Errorf("paused= %v, want false", p.ProbeSent)
  75. }
  76. }
  77. func TestProgressBecomeProbe(t *testing.T) {
  78. match := uint64(1)
  79. tests := []struct {
  80. p *Progress
  81. wnext uint64
  82. }{
  83. {
  84. &Progress{State: StateReplicate, Match: match, Next: 5, Inflights: NewInflights(256)},
  85. 2,
  86. },
  87. {
  88. // snapshot finish
  89. &Progress{State: StateSnapshot, Match: match, Next: 5, PendingSnapshot: 10, Inflights: NewInflights(256)},
  90. 11,
  91. },
  92. {
  93. // snapshot failure
  94. &Progress{State: StateSnapshot, Match: match, Next: 5, PendingSnapshot: 0, Inflights: NewInflights(256)},
  95. 2,
  96. },
  97. }
  98. for i, tt := range tests {
  99. tt.p.BecomeProbe()
  100. if tt.p.State != StateProbe {
  101. t.Errorf("#%d: state = %s, want %s", i, tt.p.State, StateProbe)
  102. }
  103. if tt.p.Match != match {
  104. t.Errorf("#%d: match = %d, want %d", i, tt.p.Match, match)
  105. }
  106. if tt.p.Next != tt.wnext {
  107. t.Errorf("#%d: next = %d, want %d", i, tt.p.Next, tt.wnext)
  108. }
  109. }
  110. }
  111. func TestProgressBecomeReplicate(t *testing.T) {
  112. p := &Progress{State: StateProbe, Match: 1, Next: 5, Inflights: NewInflights(256)}
  113. p.BecomeReplicate()
  114. if p.State != StateReplicate {
  115. t.Errorf("state = %s, want %s", p.State, StateReplicate)
  116. }
  117. if p.Match != 1 {
  118. t.Errorf("match = %d, want 1", p.Match)
  119. }
  120. if w := p.Match + 1; p.Next != w {
  121. t.Errorf("next = %d, want %d", p.Next, w)
  122. }
  123. }
  124. func TestProgressBecomeSnapshot(t *testing.T) {
  125. p := &Progress{State: StateProbe, Match: 1, Next: 5, Inflights: NewInflights(256)}
  126. p.BecomeSnapshot(10)
  127. if p.State != StateSnapshot {
  128. t.Errorf("state = %s, want %s", p.State, StateSnapshot)
  129. }
  130. if p.Match != 1 {
  131. t.Errorf("match = %d, want 1", p.Match)
  132. }
  133. if p.PendingSnapshot != 10 {
  134. t.Errorf("pendingSnapshot = %d, want 10", p.PendingSnapshot)
  135. }
  136. }
  137. func TestProgressUpdate(t *testing.T) {
  138. prevM, prevN := uint64(3), uint64(5)
  139. tests := []struct {
  140. update uint64
  141. wm uint64
  142. wn uint64
  143. wok bool
  144. }{
  145. {prevM - 1, prevM, prevN, false}, // do not decrease match, next
  146. {prevM, prevM, prevN, false}, // do not decrease next
  147. {prevM + 1, prevM + 1, prevN, true}, // increase match, do not decrease next
  148. {prevM + 2, prevM + 2, prevN + 1, true}, // increase match, next
  149. }
  150. for i, tt := range tests {
  151. p := &Progress{
  152. Match: prevM,
  153. Next: prevN,
  154. }
  155. ok := p.MaybeUpdate(tt.update)
  156. if ok != tt.wok {
  157. t.Errorf("#%d: ok= %v, want %v", i, ok, tt.wok)
  158. }
  159. if p.Match != tt.wm {
  160. t.Errorf("#%d: match= %d, want %d", i, p.Match, tt.wm)
  161. }
  162. if p.Next != tt.wn {
  163. t.Errorf("#%d: next= %d, want %d", i, p.Next, tt.wn)
  164. }
  165. }
  166. }
  167. func TestProgressMaybeDecr(t *testing.T) {
  168. tests := []struct {
  169. state StateType
  170. m uint64
  171. n uint64
  172. rejected uint64
  173. last uint64
  174. w bool
  175. wn uint64
  176. }{
  177. {
  178. // state replicate and rejected is not greater than match
  179. StateReplicate, 5, 10, 5, 5, false, 10,
  180. },
  181. {
  182. // state replicate and rejected is not greater than match
  183. StateReplicate, 5, 10, 4, 4, false, 10,
  184. },
  185. {
  186. // state replicate and rejected is greater than match
  187. // directly decrease to match+1
  188. StateReplicate, 5, 10, 9, 9, true, 6,
  189. },
  190. {
  191. // next-1 != rejected is always false
  192. StateProbe, 0, 0, 0, 0, false, 0,
  193. },
  194. {
  195. // next-1 != rejected is always false
  196. StateProbe, 0, 10, 5, 5, false, 10,
  197. },
  198. {
  199. // next>1 = decremented by 1
  200. StateProbe, 0, 10, 9, 9, true, 9,
  201. },
  202. {
  203. // next>1 = decremented by 1
  204. StateProbe, 0, 2, 1, 1, true, 1,
  205. },
  206. {
  207. // next<=1 = reset to 1
  208. StateProbe, 0, 1, 0, 0, true, 1,
  209. },
  210. {
  211. // decrease to min(rejected, last+1)
  212. StateProbe, 0, 10, 9, 2, true, 3,
  213. },
  214. {
  215. // rejected < 1, reset to 1
  216. StateProbe, 0, 10, 9, 0, true, 1,
  217. },
  218. }
  219. for i, tt := range tests {
  220. p := &Progress{
  221. State: tt.state,
  222. Match: tt.m,
  223. Next: tt.n,
  224. }
  225. if g := p.MaybeDecrTo(tt.rejected, tt.last); g != tt.w {
  226. t.Errorf("#%d: maybeDecrTo= %t, want %t", i, g, tt.w)
  227. }
  228. if gm := p.Match; gm != tt.m {
  229. t.Errorf("#%d: match= %d, want %d", i, gm, tt.m)
  230. }
  231. if gn := p.Next; gn != tt.wn {
  232. t.Errorf("#%d: next= %d, want %d", i, gn, tt.wn)
  233. }
  234. }
  235. }