cluster_test.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. package raft
  2. import (
  3. "reflect"
  4. "testing"
  5. )
  6. // TestBuildCluster ensures cluster with various size could be built.
  7. func TestBuildCluster(t *testing.T) {
  8. tests := []struct {
  9. size int
  10. ids []int
  11. }{
  12. {1, nil},
  13. {3, nil},
  14. {5, nil},
  15. {7, nil},
  16. {9, nil},
  17. {13, nil},
  18. {51, nil},
  19. {1, []int{1}},
  20. {3, []int{1, 3, 5}},
  21. {5, []int{1, 4, 7, 10, 13}},
  22. }
  23. for i, tt := range tests {
  24. _, nodes := buildCluster(tt.size, tt.ids)
  25. base := ltoa(nodes[0].sm.log)
  26. for j, n := range nodes {
  27. // ensure same log
  28. l := ltoa(n.sm.log)
  29. if g := diffu(base, l); g != "" {
  30. t.Errorf("#%d.%d: log diff:\n%s", i, j, g)
  31. }
  32. // ensure same leader
  33. w := 0
  34. if tt.ids != nil {
  35. w = tt.ids[0]
  36. }
  37. if g := n.sm.lead; g != w {
  38. t.Errorf("#%d.%d: lead = %d, want %d", i, j, g, w)
  39. }
  40. // ensure same peer map
  41. p := map[int]struct{}{}
  42. for k := range n.sm.ins {
  43. p[k] = struct{}{}
  44. }
  45. wp := map[int]struct{}{}
  46. for k := 0; k < tt.size; k++ {
  47. if tt.ids != nil {
  48. wp[tt.ids[k]] = struct{}{}
  49. } else {
  50. wp[k] = struct{}{}
  51. }
  52. }
  53. if !reflect.DeepEqual(p, wp) {
  54. t.Errorf("#%d.%d: peers = %+v, want %+v", i, j, p, wp)
  55. }
  56. }
  57. }
  58. }
  59. // TestBasicCluster ensures all nodes can send proposal to the cluster.
  60. // And all the proposals will get committed.
  61. func TestBasicCluster(t *testing.T) {
  62. tests := []struct {
  63. size int
  64. round int
  65. }{
  66. {1, 3},
  67. {3, 3},
  68. {5, 3},
  69. {7, 3},
  70. {13, 1},
  71. }
  72. for i, tt := range tests {
  73. nt, nodes := buildCluster(tt.size, nil)
  74. for j := 0; j < tt.round; j++ {
  75. for _, n := range nodes {
  76. data := []byte{byte(n.Id())}
  77. nt.send(Message{Type: msgProp, To: n.Id(), Entries: []Entry{{Data: data}}})
  78. base := nodes[0].Next()
  79. if len(base) != 1 {
  80. t.Fatalf("#%d: len(ents) = %d, want 1", i, len(base))
  81. }
  82. if !reflect.DeepEqual(base[0].Data, data) {
  83. t.Errorf("#%d: data = %s, want %s", i, base[0].Data, data)
  84. }
  85. for k := 1; k < tt.size; k++ {
  86. g := nodes[k].Next()
  87. if !reflect.DeepEqual(g, base) {
  88. t.Errorf("#%d.%d: ent = %v, want %v", i, k, g, base)
  89. }
  90. }
  91. }
  92. }
  93. }
  94. }
  95. // This function is full of heck now. It will go away when we finish our
  96. // network Interface, and ticker infrastructure.
  97. func buildCluster(size int, ids []int) (nt *network, nodes []*Node) {
  98. if ids == nil {
  99. ids = make([]int, size)
  100. for i := 0; i < size; i++ {
  101. ids[i] = i
  102. }
  103. }
  104. nodes = make([]*Node, size)
  105. nis := make([]Interface, size)
  106. for i := range nodes {
  107. nodes[i] = New(ids[i], defaultHeartbeat, defaultElection)
  108. nis[i] = nodes[i]
  109. }
  110. nt = newNetwork(nis...)
  111. lead := dictate(nodes[0])
  112. lead.Next()
  113. for i := 1; i < size; i++ {
  114. lead.Add(ids[i], "")
  115. nt.send(lead.Msgs()...)
  116. for j := 0; j < i; j++ {
  117. nodes[j].Next()
  118. }
  119. }
  120. for i := 0; i < 10*defaultHeartbeat; i++ {
  121. nodes[0].Tick()
  122. }
  123. msgs := nodes[0].Msgs()
  124. nt.send(msgs...)
  125. for _, n := range nodes {
  126. n.Next()
  127. }
  128. return
  129. }