cluster_test.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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 := []int{1, 3, 5, 7, 9, 13, 51}
  9. for i, tt := range tests {
  10. _, nodes := buildCluster(tt)
  11. base := ltoa(nodes[0].sm.log)
  12. for j, n := range nodes {
  13. // ensure same log
  14. l := ltoa(n.sm.log)
  15. if g := diffu(base, l); g != "" {
  16. t.Errorf("#%d.%d: log diff:\n%s", i, j, g)
  17. }
  18. // ensure same leader
  19. if n.sm.lead != 0 {
  20. t.Errorf("#%d.%d: lead = %d, want 0", i, j, n.sm.lead)
  21. }
  22. // ensure same peer map
  23. p := map[int]struct{}{}
  24. for k := range n.sm.ins {
  25. p[k] = struct{}{}
  26. }
  27. wp := map[int]struct{}{}
  28. for k := 0; k < tt; k++ {
  29. wp[k] = struct{}{}
  30. }
  31. if !reflect.DeepEqual(p, wp) {
  32. t.Errorf("#%d.%d: peers = %+v, want %+v", i, j, p, wp)
  33. }
  34. }
  35. }
  36. }
  37. // TestBasicCluster ensures all nodes can send proposal to the cluster.
  38. // And all the proposals will get committed.
  39. func TestBasicCluster(t *testing.T) {
  40. tests := []struct {
  41. size int
  42. round int
  43. }{
  44. {1, 3},
  45. {3, 3},
  46. {5, 3},
  47. {7, 3},
  48. {13, 1},
  49. }
  50. for i, tt := range tests {
  51. nt, nodes := buildCluster(tt.size)
  52. for j := 0; j < tt.round; j++ {
  53. for _, n := range nodes {
  54. data := []byte{byte(n.addr)}
  55. nt.send(Message{Type: msgProp, To: n.addr, Entries: []Entry{{Data: data}}})
  56. base := nodes[0].Next()
  57. if len(base) != 1 {
  58. t.Fatalf("#%d: len(ents) = %d, want 1", i, len(base))
  59. }
  60. if !reflect.DeepEqual(base[0].Data, data) {
  61. t.Errorf("#%d: data = %s, want %s", i, base[0].Data, data)
  62. }
  63. for k := 1; k < tt.size; k++ {
  64. g := nodes[k].Next()
  65. if !reflect.DeepEqual(g, base) {
  66. t.Errorf("#%d.%d: ent = %v, want %v", i, k, g, base)
  67. }
  68. }
  69. }
  70. }
  71. }
  72. }
  73. // This function is full of heck now. It will go away when we finish our
  74. // network Interface, and ticker infrastructure.
  75. func buildCluster(size int) (nt *network, nodes []*Node) {
  76. nodes = make([]*Node, size)
  77. nis := make([]Interface, size)
  78. for i := range nodes {
  79. nodes[i] = New(i, defaultHeartbeat, defaultElection)
  80. nis[i] = nodes[i]
  81. }
  82. nt = newNetwork(nis...)
  83. Dictate(nodes[0]).Next()
  84. for i := 1; i < size; i++ {
  85. nt.send(nodes[0].newConfMessage(configAdd, &Config{NodeId: i}))
  86. for j := 0; j < i; j++ {
  87. nodes[j].Next()
  88. }
  89. }
  90. for i := 0; i < 10*defaultHeartbeat; i++ {
  91. nodes[0].Tick()
  92. }
  93. msgs := nodes[0].Msgs()
  94. nt.send(msgs...)
  95. for _, n := range nodes {
  96. n.Next()
  97. }
  98. return
  99. }