etcd_functional_test.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package etcd
  2. import (
  3. "math/rand"
  4. "testing"
  5. "time"
  6. )
  7. func TestKillLeader(t *testing.T) {
  8. tests := []int{3, 5, 9, 11}
  9. for i, tt := range tests {
  10. es, hs := buildCluster(tt, false)
  11. waitCluster(t, es)
  12. waitLeader(es)
  13. lead := es[0].node.Leader()
  14. es[lead].Stop()
  15. time.Sleep(es[0].tickDuration * defaultElection * 2)
  16. waitLeader(es)
  17. if es[1].node.Leader() == 0 {
  18. t.Errorf("#%d: lead = %d, want not 0", i, es[1].node.Leader())
  19. }
  20. for i := range es {
  21. es[len(es)-i-1].Stop()
  22. }
  23. for i := range hs {
  24. hs[len(hs)-i-1].Close()
  25. }
  26. }
  27. afterTest(t)
  28. }
  29. func TestRandomKill(t *testing.T) {
  30. tests := []int{3, 5, 9, 11}
  31. for _, tt := range tests {
  32. es, hs := buildCluster(tt, false)
  33. waitCluster(t, es)
  34. waitLeader(es)
  35. toKill := make(map[int64]struct{})
  36. for len(toKill) != tt/2-1 {
  37. toKill[rand.Int63n(int64(tt))] = struct{}{}
  38. }
  39. for k := range toKill {
  40. es[k].Stop()
  41. }
  42. time.Sleep(es[0].tickDuration * defaultElection * 2)
  43. waitLeader(es)
  44. for i := range es {
  45. es[len(es)-i-1].Stop()
  46. }
  47. for i := range hs {
  48. hs[len(hs)-i-1].Close()
  49. }
  50. }
  51. afterTest(t)
  52. }
  53. type leadterm struct {
  54. lead int64
  55. term int64
  56. }
  57. func waitLeader(es []*Server) {
  58. for {
  59. ls := make([]leadterm, 0, len(es))
  60. for i := range es {
  61. switch es[i].mode {
  62. case participant:
  63. ls = append(ls, reportLead(es[i]))
  64. case standby:
  65. //TODO(xiangli) add standby support
  66. case stop:
  67. }
  68. }
  69. if isSameLead(ls) {
  70. return
  71. }
  72. time.Sleep(es[0].tickDuration * defaultElection)
  73. }
  74. }
  75. func reportLead(s *Server) leadterm {
  76. return leadterm{s.node.Leader(), s.node.Term()}
  77. }
  78. func isSameLead(ls []leadterm) bool {
  79. m := make(map[leadterm]int)
  80. for i := range ls {
  81. m[ls[i]] = m[ls[i]] + 1
  82. }
  83. if len(m) == 1 {
  84. return true
  85. }
  86. // todo(xiangli): printout the current cluster status for debugging....
  87. return false
  88. }