etcd_functional_test.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /*
  2. Copyright 2014 CoreOS Inc.
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package etcdserver
  14. import (
  15. "fmt"
  16. "math/rand"
  17. "net/url"
  18. "reflect"
  19. "testing"
  20. "time"
  21. "github.com/coreos/etcd/conf"
  22. "github.com/coreos/etcd/third_party/github.com/coreos/go-etcd/etcd"
  23. )
  24. func TestKillLeader(t *testing.T) {
  25. defer afterTest(t)
  26. tests := []int{3, 5, 9}
  27. for i, tt := range tests {
  28. cl := testCluster{Size: tt}
  29. cl.Start()
  30. for j := 0; j < tt; j++ {
  31. lead, _ := cl.Leader()
  32. cl.Node(lead).Stop()
  33. // wait for leader election timeout
  34. time.Sleep(cl.Node(0).e.tickDuration * defaultElection * 2)
  35. if g, _ := cl.Leader(); g == lead {
  36. t.Errorf("#%d.%d: lead = %d, want not %d", i, j, g, lead)
  37. }
  38. cl.Node(lead).Start()
  39. cl.Node(lead).WaitMode(participantMode)
  40. }
  41. cl.Destroy()
  42. }
  43. }
  44. func TestKillRandom(t *testing.T) {
  45. defer afterTest(t)
  46. tests := []int{3, 5, 9}
  47. for _, tt := range tests {
  48. cl := testCluster{Size: tt}
  49. cl.Start()
  50. for j := 0; j < tt; j++ {
  51. // we cannot kill the majority
  52. // wait for the majority
  53. cl.Leader()
  54. toKill := make(map[int64]struct{})
  55. for len(toKill) != tt/2-1 {
  56. toKill[rand.Int63n(int64(tt))] = struct{}{}
  57. }
  58. for k := range toKill {
  59. cl.Node(int(k)).Stop()
  60. }
  61. // wait for leader election timeout
  62. time.Sleep(cl.Node(0).e.tickDuration * defaultElection * 2)
  63. cl.Leader()
  64. for k := range toKill {
  65. cl.Node(int(k)).Start()
  66. cl.Node(int(k)).WaitMode(participantMode)
  67. }
  68. }
  69. cl.Destroy()
  70. }
  71. }
  72. func TestJoinThroughFollower(t *testing.T) {
  73. defer afterTest(t)
  74. tests := []int{3, 5, 7}
  75. for _, tt := range tests {
  76. bt := &testServer{}
  77. bt.Start()
  78. cl := testCluster{nodes: []*testServer{bt}}
  79. seed := bt.URL
  80. for i := 1; i < tt; i++ {
  81. c := newTestConfig()
  82. c.Name = fmt.Sprint(i)
  83. c.Peers = []string{seed}
  84. ts := &testServer{Config: c}
  85. ts.Start()
  86. ts.WaitMode(participantMode)
  87. cl.nodes = append(cl.nodes, ts)
  88. cl.Leader()
  89. seed = ts.URL
  90. }
  91. cl.Destroy()
  92. }
  93. }
  94. func TestJoinWithoutHTTPScheme(t *testing.T) {
  95. bt := &testServer{}
  96. bt.Start()
  97. cl := testCluster{nodes: []*testServer{bt}}
  98. seed := bt.URL
  99. u, err := url.Parse(seed)
  100. if err != nil {
  101. t.Fatal(err)
  102. }
  103. // remove HTTP scheme
  104. seed = u.Host + u.Path
  105. for i := 1; i < 3; i++ {
  106. c := newTestConfig()
  107. c.Name = "server-" + fmt.Sprint(i)
  108. c.Peers = []string{seed}
  109. ts := &testServer{Config: c}
  110. ts.Start()
  111. ts.WaitMode(participantMode)
  112. cl.nodes = append(cl.nodes, ts)
  113. cl.Leader()
  114. }
  115. cl.Destroy()
  116. }
  117. func TestClusterConfigReload(t *testing.T) {
  118. defer afterTest(t)
  119. cl := &testCluster{Size: 5}
  120. cl.Start()
  121. defer cl.Destroy()
  122. lead, _ := cl.Leader()
  123. cc := conf.NewClusterConfig()
  124. cc.ActiveSize = 15
  125. cc.RemoveDelay = 60
  126. if err := cl.Participant(lead).setClusterConfig(cc); err != nil {
  127. t.Fatalf("setClusterConfig err = %v", err)
  128. }
  129. cl.Stop()
  130. cl.Restart()
  131. lead, _ = cl.Leader()
  132. // wait for msgAppResp to commit all entries
  133. time.Sleep(2 * defaultHeartbeat * cl.Participant(0).tickDuration)
  134. if g := cl.Participant(lead).clusterConfig(); !reflect.DeepEqual(g, cc) {
  135. t.Errorf("clusterConfig = %+v, want %+v", g, cc)
  136. }
  137. }
  138. func TestFiveNodeKillOneAndRecover(t *testing.T) {
  139. defer afterTest(t)
  140. cl := testCluster{Size: 5}
  141. cl.Start()
  142. for n := 0; n < 5; n++ {
  143. i := rand.Int() % 5
  144. cl.Node(i).Stop()
  145. cl.Leader()
  146. cl.Node(i).Start()
  147. cl.Node(i).WaitMode(participantMode)
  148. cl.Leader()
  149. }
  150. cl.Destroy()
  151. }
  152. func TestFiveNodeKillAllAndRecover(t *testing.T) {
  153. defer afterTest(t)
  154. cl := testCluster{Size: 5}
  155. cl.Start()
  156. defer cl.Destroy()
  157. cl.Leader()
  158. c := etcd.NewClient([]string{cl.URL(0)})
  159. for i := 0; i < 10; i++ {
  160. if _, err := c.Set("foo", "bar", 0); err != nil {
  161. panic(err)
  162. }
  163. }
  164. cl.Stop()
  165. cl.Restart()
  166. cl.Leader()
  167. res, err := c.Set("foo", "bar", 0)
  168. if err != nil {
  169. t.Fatalf("set err after recovery: %v", err)
  170. }
  171. if g := res.Node.ModifiedIndex; g != 16 {
  172. t.Errorf("modifiedIndex = %d, want %d", g, 16)
  173. }
  174. }
  175. // TestModeSwitch tests switch mode between standby and peer.
  176. func TestModeSwitch(t *testing.T) {
  177. t.Skip("not implemented")
  178. }