cluster_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. // Copyright 2018 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 tester
  15. import (
  16. "reflect"
  17. "sort"
  18. "testing"
  19. "go.etcd.io/etcd/functional/rpcpb"
  20. "go.uber.org/zap"
  21. )
  22. func Test_read(t *testing.T) {
  23. exp := &Cluster{
  24. Members: []*rpcpb.Member{
  25. {
  26. EtcdExec: "./bin/etcd",
  27. AgentAddr: "127.0.0.1:19027",
  28. FailpointHTTPAddr: "http://127.0.0.1:7381",
  29. BaseDir: "/tmp/etcd-functional-1",
  30. EtcdClientProxy: false,
  31. EtcdPeerProxy: true,
  32. EtcdClientEndpoint: "127.0.0.1:1379",
  33. Etcd: &rpcpb.Etcd{
  34. Name: "s1",
  35. DataDir: "/tmp/etcd-functional-1/etcd.data",
  36. WALDir: "/tmp/etcd-functional-1/etcd.data/member/wal",
  37. HeartbeatIntervalMs: 100,
  38. ElectionTimeoutMs: 1000,
  39. ListenClientURLs: []string{"https://127.0.0.1:1379"},
  40. AdvertiseClientURLs: []string{"https://127.0.0.1:1379"},
  41. ClientAutoTLS: true,
  42. ClientCertAuth: false,
  43. ClientCertFile: "",
  44. ClientKeyFile: "",
  45. ClientTrustedCAFile: "",
  46. ListenPeerURLs: []string{"https://127.0.0.1:1380"},
  47. AdvertisePeerURLs: []string{"https://127.0.0.1:1381"},
  48. PeerAutoTLS: true,
  49. PeerClientCertAuth: false,
  50. PeerCertFile: "",
  51. PeerKeyFile: "",
  52. PeerTrustedCAFile: "",
  53. InitialCluster: "s1=https://127.0.0.1:1381,s2=https://127.0.0.1:2381,s3=https://127.0.0.1:3381",
  54. InitialClusterState: "new",
  55. InitialClusterToken: "tkn",
  56. SnapshotCount: 10000,
  57. QuotaBackendBytes: 10740000000,
  58. PreVote: true,
  59. InitialCorruptCheck: true,
  60. Logger: "zap",
  61. LogOutputs: []string{"/tmp/etcd-functional-1/etcd.log"},
  62. Debug: true,
  63. },
  64. ClientCertData: "",
  65. ClientCertPath: "",
  66. ClientKeyData: "",
  67. ClientKeyPath: "",
  68. ClientTrustedCAData: "",
  69. ClientTrustedCAPath: "",
  70. PeerCertData: "",
  71. PeerCertPath: "",
  72. PeerKeyData: "",
  73. PeerKeyPath: "",
  74. PeerTrustedCAData: "",
  75. PeerTrustedCAPath: "",
  76. SnapshotPath: "/tmp/etcd-functional-1.snapshot.db",
  77. },
  78. {
  79. EtcdExec: "./bin/etcd",
  80. AgentAddr: "127.0.0.1:29027",
  81. FailpointHTTPAddr: "http://127.0.0.1:7382",
  82. BaseDir: "/tmp/etcd-functional-2",
  83. EtcdClientProxy: false,
  84. EtcdPeerProxy: true,
  85. EtcdClientEndpoint: "127.0.0.1:2379",
  86. Etcd: &rpcpb.Etcd{
  87. Name: "s2",
  88. DataDir: "/tmp/etcd-functional-2/etcd.data",
  89. WALDir: "/tmp/etcd-functional-2/etcd.data/member/wal",
  90. HeartbeatIntervalMs: 100,
  91. ElectionTimeoutMs: 1000,
  92. ListenClientURLs: []string{"https://127.0.0.1:2379"},
  93. AdvertiseClientURLs: []string{"https://127.0.0.1:2379"},
  94. ClientAutoTLS: true,
  95. ClientCertAuth: false,
  96. ClientCertFile: "",
  97. ClientKeyFile: "",
  98. ClientTrustedCAFile: "",
  99. ListenPeerURLs: []string{"https://127.0.0.1:2380"},
  100. AdvertisePeerURLs: []string{"https://127.0.0.1:2381"},
  101. PeerAutoTLS: true,
  102. PeerClientCertAuth: false,
  103. PeerCertFile: "",
  104. PeerKeyFile: "",
  105. PeerTrustedCAFile: "",
  106. InitialCluster: "s1=https://127.0.0.1:1381,s2=https://127.0.0.1:2381,s3=https://127.0.0.1:3381",
  107. InitialClusterState: "new",
  108. InitialClusterToken: "tkn",
  109. SnapshotCount: 10000,
  110. QuotaBackendBytes: 10740000000,
  111. PreVote: true,
  112. InitialCorruptCheck: true,
  113. Logger: "zap",
  114. LogOutputs: []string{"/tmp/etcd-functional-2/etcd.log"},
  115. Debug: true,
  116. },
  117. ClientCertData: "",
  118. ClientCertPath: "",
  119. ClientKeyData: "",
  120. ClientKeyPath: "",
  121. ClientTrustedCAData: "",
  122. ClientTrustedCAPath: "",
  123. PeerCertData: "",
  124. PeerCertPath: "",
  125. PeerKeyData: "",
  126. PeerKeyPath: "",
  127. PeerTrustedCAData: "",
  128. PeerTrustedCAPath: "",
  129. SnapshotPath: "/tmp/etcd-functional-2.snapshot.db",
  130. },
  131. {
  132. EtcdExec: "./bin/etcd",
  133. AgentAddr: "127.0.0.1:39027",
  134. FailpointHTTPAddr: "http://127.0.0.1:7383",
  135. BaseDir: "/tmp/etcd-functional-3",
  136. EtcdClientProxy: false,
  137. EtcdPeerProxy: true,
  138. EtcdClientEndpoint: "127.0.0.1:3379",
  139. Etcd: &rpcpb.Etcd{
  140. Name: "s3",
  141. DataDir: "/tmp/etcd-functional-3/etcd.data",
  142. WALDir: "/tmp/etcd-functional-3/etcd.data/member/wal",
  143. HeartbeatIntervalMs: 100,
  144. ElectionTimeoutMs: 1000,
  145. ListenClientURLs: []string{"https://127.0.0.1:3379"},
  146. AdvertiseClientURLs: []string{"https://127.0.0.1:3379"},
  147. ClientAutoTLS: true,
  148. ClientCertAuth: false,
  149. ClientCertFile: "",
  150. ClientKeyFile: "",
  151. ClientTrustedCAFile: "",
  152. ListenPeerURLs: []string{"https://127.0.0.1:3380"},
  153. AdvertisePeerURLs: []string{"https://127.0.0.1:3381"},
  154. PeerAutoTLS: true,
  155. PeerClientCertAuth: false,
  156. PeerCertFile: "",
  157. PeerKeyFile: "",
  158. PeerTrustedCAFile: "",
  159. InitialCluster: "s1=https://127.0.0.1:1381,s2=https://127.0.0.1:2381,s3=https://127.0.0.1:3381",
  160. InitialClusterState: "new",
  161. InitialClusterToken: "tkn",
  162. SnapshotCount: 10000,
  163. QuotaBackendBytes: 10740000000,
  164. PreVote: true,
  165. InitialCorruptCheck: true,
  166. Logger: "zap",
  167. LogOutputs: []string{"/tmp/etcd-functional-3/etcd.log"},
  168. Debug: true,
  169. },
  170. ClientCertData: "",
  171. ClientCertPath: "",
  172. ClientKeyData: "",
  173. ClientKeyPath: "",
  174. ClientTrustedCAData: "",
  175. ClientTrustedCAPath: "",
  176. PeerCertData: "",
  177. PeerCertPath: "",
  178. PeerKeyData: "",
  179. PeerKeyPath: "",
  180. PeerTrustedCAData: "",
  181. PeerTrustedCAPath: "",
  182. SnapshotPath: "/tmp/etcd-functional-3.snapshot.db",
  183. },
  184. },
  185. Tester: &rpcpb.Tester{
  186. DataDir: "/tmp/etcd-tester-data",
  187. Network: "tcp",
  188. Addr: "127.0.0.1:9028",
  189. DelayLatencyMs: 5000,
  190. DelayLatencyMsRv: 500,
  191. UpdatedDelayLatencyMs: 5000,
  192. RoundLimit: 1,
  193. ExitOnCaseFail: true,
  194. EnablePprof: true,
  195. CaseDelayMs: 7000,
  196. CaseShuffle: true,
  197. Cases: []string{
  198. "SIGTERM_ONE_FOLLOWER",
  199. "SIGTERM_ONE_FOLLOWER_UNTIL_TRIGGER_SNAPSHOT",
  200. "SIGTERM_LEADER",
  201. "SIGTERM_LEADER_UNTIL_TRIGGER_SNAPSHOT",
  202. "SIGTERM_QUORUM",
  203. "SIGTERM_ALL",
  204. "SIGQUIT_AND_REMOVE_ONE_FOLLOWER",
  205. "SIGQUIT_AND_REMOVE_ONE_FOLLOWER_UNTIL_TRIGGER_SNAPSHOT",
  206. // "SIGQUIT_AND_REMOVE_LEADER",
  207. // "SIGQUIT_AND_REMOVE_LEADER_UNTIL_TRIGGER_SNAPSHOT",
  208. // "SIGQUIT_AND_REMOVE_QUORUM_AND_RESTORE_LEADER_SNAPSHOT_FROM_SCRATCH",
  209. // "BLACKHOLE_PEER_PORT_TX_RX_ONE_FOLLOWER",
  210. // "BLACKHOLE_PEER_PORT_TX_RX_ONE_FOLLOWER_UNTIL_TRIGGER_SNAPSHOT",
  211. "BLACKHOLE_PEER_PORT_TX_RX_LEADER",
  212. "BLACKHOLE_PEER_PORT_TX_RX_LEADER_UNTIL_TRIGGER_SNAPSHOT",
  213. "BLACKHOLE_PEER_PORT_TX_RX_QUORUM",
  214. "BLACKHOLE_PEER_PORT_TX_RX_ALL",
  215. // "DELAY_PEER_PORT_TX_RX_ONE_FOLLOWER",
  216. // "RANDOM_DELAY_PEER_PORT_TX_RX_ONE_FOLLOWER",
  217. // "DELAY_PEER_PORT_TX_RX_ONE_FOLLOWER_UNTIL_TRIGGER_SNAPSHOT",
  218. // "RANDOM_DELAY_PEER_PORT_TX_RX_ONE_FOLLOWER_UNTIL_TRIGGER_SNAPSHOT",
  219. "DELAY_PEER_PORT_TX_RX_LEADER",
  220. "RANDOM_DELAY_PEER_PORT_TX_RX_LEADER",
  221. "DELAY_PEER_PORT_TX_RX_LEADER_UNTIL_TRIGGER_SNAPSHOT",
  222. "RANDOM_DELAY_PEER_PORT_TX_RX_LEADER_UNTIL_TRIGGER_SNAPSHOT",
  223. "DELAY_PEER_PORT_TX_RX_QUORUM",
  224. "RANDOM_DELAY_PEER_PORT_TX_RX_QUORUM",
  225. "DELAY_PEER_PORT_TX_RX_ALL",
  226. "RANDOM_DELAY_PEER_PORT_TX_RX_ALL",
  227. "NO_FAIL_WITH_STRESS",
  228. "NO_FAIL_WITH_NO_STRESS_FOR_LIVENESS",
  229. },
  230. FailpointCommands: []string{`panic("etcd-tester")`},
  231. RunnerExecPath: "./bin/etcd-runner",
  232. ExternalExecPath: "",
  233. Stressers: []*rpcpb.Stresser{
  234. {Type: "KV_WRITE_SMALL", Weight: 0.35},
  235. {Type: "KV_WRITE_LARGE", Weight: 0.002},
  236. {Type: "KV_READ_ONE_KEY", Weight: 0.07},
  237. {Type: "KV_READ_RANGE", Weight: 0.07},
  238. {Type: "KV_DELETE_ONE_KEY", Weight: 0.07},
  239. {Type: "KV_DELETE_RANGE", Weight: 0.07},
  240. {Type: "KV_TXN_WRITE_DELETE", Weight: 0.35},
  241. {Type: "LEASE", Weight: 0.0},
  242. },
  243. Checkers: []string{"KV_HASH", "LEASE_EXPIRE"},
  244. StressKeySize: 100,
  245. StressKeySizeLarge: 32769,
  246. StressKeySuffixRange: 250000,
  247. StressKeySuffixRangeTxn: 100,
  248. StressKeyTxnOps: 10,
  249. StressClients: 100,
  250. StressQPS: 2000,
  251. },
  252. }
  253. logger, err := zap.NewProduction()
  254. if err != nil {
  255. t.Fatal(err)
  256. }
  257. defer logger.Sync()
  258. cfg, err := read(logger, "../../functional.yaml")
  259. if err != nil {
  260. t.Fatal(err)
  261. }
  262. cfg.lg = nil
  263. if !reflect.DeepEqual(exp, cfg) {
  264. t.Fatalf("expected %+v, got %+v", exp, cfg)
  265. }
  266. cfg.lg = logger
  267. cfg.updateCases()
  268. fs1 := cfg.listCases()
  269. cfg.shuffleCases()
  270. fs2 := cfg.listCases()
  271. if reflect.DeepEqual(fs1, fs2) {
  272. t.Fatalf("expected shuffled failure cases, got %q", fs2)
  273. }
  274. cfg.shuffleCases()
  275. fs3 := cfg.listCases()
  276. if reflect.DeepEqual(fs2, fs3) {
  277. t.Fatalf("expected reshuffled failure cases from %q, got %q", fs2, fs3)
  278. }
  279. // shuffle ensures visit all exactly once
  280. // so when sorted, failure cases must be equal
  281. sort.Strings(fs1)
  282. sort.Strings(fs2)
  283. sort.Strings(fs3)
  284. if !reflect.DeepEqual(fs1, fs2) {
  285. t.Fatalf("expected %q, got %q", fs1, fs2)
  286. }
  287. if !reflect.DeepEqual(fs2, fs3) {
  288. t.Fatalf("expected %q, got %q", fs2, fs3)
  289. }
  290. }