cluster_test.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  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. "reflect"
  16. "testing"
  17. )
  18. func TestClusterAddSlice(t *testing.T) {
  19. tests := []struct {
  20. mems []Member
  21. want *Cluster
  22. }{
  23. {
  24. []Member{},
  25. NewCluster(""),
  26. },
  27. {
  28. []Member{
  29. newTestMember(1, []string{"foo", "bar"}, "", nil),
  30. newTestMember(2, []string{"baz"}, "", nil),
  31. },
  32. &Cluster{
  33. members: map[uint64]*Member{
  34. 1: newTestMemberp(1, []string{"foo", "bar"}, "", nil),
  35. 2: newTestMemberp(2, []string{"baz"}, "", nil),
  36. },
  37. },
  38. },
  39. }
  40. for i, tt := range tests {
  41. c := NewCluster("")
  42. if err := c.AddSlice(tt.mems); err != nil {
  43. t.Errorf("#%d: err=%#v, want nil", i, err)
  44. continue
  45. }
  46. if !reflect.DeepEqual(c, tt.want) {
  47. t.Errorf("#%d: c=%#v, want %#v", i, c, tt.want)
  48. }
  49. }
  50. }
  51. func TestClusterAddSliceBad(t *testing.T) {
  52. c := Cluster{
  53. members: map[uint64]*Member{
  54. 1: newTestMemberp(1, nil, "", nil),
  55. },
  56. }
  57. if err := c.AddSlice([]Member{newTestMember(1, nil, "", nil)}); err == nil {
  58. t.Error("want err, but got nil")
  59. }
  60. }
  61. func TestClusterPick(t *testing.T) {
  62. cs := Cluster{
  63. members: map[uint64]*Member{
  64. 1: newTestMemberp(1, []string{"abc", "def", "ghi", "jkl", "mno", "pqr", "stu"}, "", nil),
  65. 2: newTestMemberp(2, []string{"xyz"}, "", nil),
  66. 3: newTestMemberp(3, []string{}, "", nil),
  67. },
  68. }
  69. ids := map[string]bool{
  70. "abc": true,
  71. "def": true,
  72. "ghi": true,
  73. "jkl": true,
  74. "mno": true,
  75. "pqr": true,
  76. "stu": true,
  77. }
  78. for i := 0; i < 1000; i++ {
  79. a := cs.Pick(1)
  80. if !ids[a] {
  81. t.Errorf("returned ID %q not in expected range!", a)
  82. break
  83. }
  84. }
  85. if b := cs.Pick(2); b != "xyz" {
  86. t.Errorf("id=%q, want %q", b, "xyz")
  87. }
  88. if c := cs.Pick(3); c != "" {
  89. t.Errorf("id=%q, want %q", c, "")
  90. }
  91. if d := cs.Pick(4); d != "" {
  92. t.Errorf("id=%q, want %q", d, "")
  93. }
  94. }
  95. func TestClusterFind(t *testing.T) {
  96. tests := []struct {
  97. id uint64
  98. name string
  99. mems []Member
  100. match bool
  101. }{
  102. {
  103. 1,
  104. "node1",
  105. []Member{newTestMember(1, nil, "node1", nil)},
  106. true,
  107. },
  108. {
  109. 2,
  110. "foobar",
  111. []Member{},
  112. false,
  113. },
  114. {
  115. 2,
  116. "node2",
  117. []Member{newTestMember(1, nil, "node1", nil), newTestMember(2, nil, "node2", nil)},
  118. true,
  119. },
  120. {
  121. 3,
  122. "node3",
  123. []Member{newTestMember(1, nil, "node1", nil), newTestMember(2, nil, "node2", nil)},
  124. false,
  125. },
  126. }
  127. for i, tt := range tests {
  128. c := NewCluster("")
  129. c.AddSlice(tt.mems)
  130. m := c.FindID(tt.id)
  131. if m == nil && !tt.match {
  132. continue
  133. }
  134. if m == nil && tt.match {
  135. t.Errorf("#%d: expected match got empty", i)
  136. }
  137. if m.Name != tt.name && tt.match {
  138. t.Errorf("#%d: got = %v, want %v", i, m.Name, tt.name)
  139. }
  140. }
  141. for i, tt := range tests {
  142. c := NewCluster("")
  143. c.AddSlice(tt.mems)
  144. m := c.FindID(tt.id)
  145. if m == nil && !tt.match {
  146. continue
  147. }
  148. if m == nil && tt.match {
  149. t.Errorf("#%d: expected match got empty", i)
  150. }
  151. if m.ID != tt.id && tt.match {
  152. t.Errorf("#%d: got = %v, want %v", i, m.Name, tt.id)
  153. }
  154. }
  155. }
  156. func TestClusterSet(t *testing.T) {
  157. tests := []struct {
  158. f string
  159. mems []Member
  160. }{
  161. {
  162. "mem1=http://10.0.0.1:2379,mem1=http://128.193.4.20:2379,mem2=http://10.0.0.2:2379,default=http://127.0.0.1:2379",
  163. []Member{
  164. newTestMember(3736794188555456841, []string{"http://10.0.0.1:2379", "http://128.193.4.20:2379"}, "mem1", nil),
  165. newTestMember(5674507346857578431, []string{"http://10.0.0.2:2379"}, "mem2", nil),
  166. newTestMember(2676999861503984872, []string{"http://127.0.0.1:2379"}, "default", nil),
  167. },
  168. },
  169. }
  170. for i, tt := range tests {
  171. c := NewCluster("")
  172. if err := c.AddSlice(tt.mems); err != nil {
  173. t.Error(err)
  174. }
  175. g := Cluster{}
  176. g.SetMembersFromString(tt.f)
  177. if g.String() != c.String() {
  178. t.Errorf("#%d: set = %v, want %v", i, g, c)
  179. }
  180. }
  181. }
  182. func TestClusterGenID(t *testing.T) {
  183. cs := NewCluster("")
  184. cs.AddSlice([]Member{
  185. newTestMember(1, nil, "", nil),
  186. newTestMember(2, nil, "", nil),
  187. })
  188. cs.GenID(nil)
  189. if cs.ID() == 0 {
  190. t.Fatalf("cluster.ID = %v, want not 0", cs.ID())
  191. }
  192. previd := cs.ID()
  193. cs.Add(newTestMember(3, nil, "", nil))
  194. cs.GenID(nil)
  195. if cs.ID() == previd {
  196. t.Fatalf("cluster.ID = %v, want not %v", cs.ID(), previd)
  197. }
  198. previd = cs.ID()
  199. cs.GenID([]byte("http://discovery.etcd.io/12345678"))
  200. if cs.ID() == previd {
  201. t.Fatalf("cluster.ID = %v, want not %v", cs.ID(), previd)
  202. }
  203. }
  204. func TestClusterSetBad(t *testing.T) {
  205. tests := []string{
  206. // invalid URL
  207. "%^",
  208. // no URL defined for member
  209. "mem1=,mem2=http://128.193.4.20:2379,mem3=http://10.0.0.2:2379",
  210. "mem1,mem2=http://128.193.4.20:2379,mem3=http://10.0.0.2:2379",
  211. // TODO(philips): anyone know of a 64 bit sha1 hash collision
  212. // "06b2f82fd81b2c20=http://128.193.4.20:2379,02c60cb75083ceef=http://128.193.4.20:2379",
  213. }
  214. for i, tt := range tests {
  215. g := NewCluster("")
  216. if err := g.SetMembersFromString(tt); err == nil {
  217. t.Errorf("#%d: set = %v, want err", i, tt)
  218. }
  219. }
  220. }
  221. func TestClusterMemberIDs(t *testing.T) {
  222. cs := NewCluster("")
  223. cs.AddSlice([]Member{
  224. newTestMember(1, nil, "", nil),
  225. newTestMember(4, nil, "", nil),
  226. newTestMember(100, nil, "", nil),
  227. })
  228. w := []uint64{1, 4, 100}
  229. g := cs.MemberIDs()
  230. if !reflect.DeepEqual(w, g) {
  231. t.Errorf("IDs=%+v, want %+v", g, w)
  232. }
  233. }
  234. func TestClusterAddBad(t *testing.T) {
  235. // Should not be possible to add the same ID multiple times
  236. mems := []Member{
  237. newTestMember(1, nil, "mem1", nil),
  238. newTestMember(1, nil, "mem2", nil),
  239. }
  240. c := NewCluster("")
  241. c.Add(newTestMember(1, nil, "mem1", nil))
  242. for i, m := range mems {
  243. if err := c.Add(m); err == nil {
  244. t.Errorf("#%d: set = %v, want err", i, err)
  245. }
  246. }
  247. }
  248. func TestClusterPeerURLs(t *testing.T) {
  249. tests := []struct {
  250. mems []Member
  251. wurls []string
  252. }{
  253. // single peer with a single address
  254. {
  255. mems: []Member{
  256. newTestMember(1, []string{"http://192.0.2.1"}, "", nil),
  257. },
  258. wurls: []string{"http://192.0.2.1"},
  259. },
  260. // single peer with a single address with a port
  261. {
  262. mems: []Member{
  263. newTestMember(1, []string{"http://192.0.2.1:8001"}, "", nil),
  264. },
  265. wurls: []string{"http://192.0.2.1:8001"},
  266. },
  267. // several members explicitly unsorted
  268. {
  269. mems: []Member{
  270. newTestMember(2, []string{"http://192.0.2.3", "http://192.0.2.4"}, "", nil),
  271. newTestMember(3, []string{"http://192.0.2.5", "http://192.0.2.6"}, "", nil),
  272. newTestMember(1, []string{"http://192.0.2.1", "http://192.0.2.2"}, "", nil),
  273. },
  274. wurls: []string{"http://192.0.2.1", "http://192.0.2.2", "http://192.0.2.3", "http://192.0.2.4", "http://192.0.2.5", "http://192.0.2.6"},
  275. },
  276. // no members
  277. {
  278. mems: []Member{},
  279. wurls: []string{},
  280. },
  281. // peer with no peer urls
  282. {
  283. mems: []Member{
  284. newTestMember(3, []string{}, "", nil),
  285. },
  286. wurls: []string{},
  287. },
  288. }
  289. for i, tt := range tests {
  290. c := NewCluster("")
  291. if err := c.AddSlice(tt.mems); err != nil {
  292. t.Errorf("AddSlice error: %v", err)
  293. continue
  294. }
  295. urls := c.PeerURLs()
  296. if !reflect.DeepEqual(urls, tt.wurls) {
  297. t.Errorf("#%d: PeerURLs = %v, want %v", i, urls, tt.wurls)
  298. }
  299. }
  300. }
  301. func TestClusterClientURLs(t *testing.T) {
  302. tests := []struct {
  303. mems []Member
  304. wurls []string
  305. }{
  306. // single peer with a single address
  307. {
  308. mems: []Member{
  309. newTestMember(1, nil, "", []string{"http://192.0.2.1"}),
  310. },
  311. wurls: []string{"http://192.0.2.1"},
  312. },
  313. // single peer with a single address with a port
  314. {
  315. mems: []Member{
  316. newTestMember(1, nil, "", []string{"http://192.0.2.1:8001"}),
  317. },
  318. wurls: []string{"http://192.0.2.1:8001"},
  319. },
  320. // several members explicitly unsorted
  321. {
  322. mems: []Member{
  323. newTestMember(2, nil, "", []string{"http://192.0.2.3", "http://192.0.2.4"}),
  324. newTestMember(3, nil, "", []string{"http://192.0.2.5", "http://192.0.2.6"}),
  325. newTestMember(1, nil, "", []string{"http://192.0.2.1", "http://192.0.2.2"}),
  326. },
  327. wurls: []string{"http://192.0.2.1", "http://192.0.2.2", "http://192.0.2.3", "http://192.0.2.4", "http://192.0.2.5", "http://192.0.2.6"},
  328. },
  329. // no members
  330. {
  331. mems: []Member{},
  332. wurls: []string{},
  333. },
  334. // peer with no client urls
  335. {
  336. mems: []Member{
  337. newTestMember(3, nil, "", []string{}),
  338. },
  339. wurls: []string{},
  340. },
  341. }
  342. for i, tt := range tests {
  343. c := NewCluster("")
  344. if err := c.AddSlice(tt.mems); err != nil {
  345. t.Errorf("AddSlice error: %v", err)
  346. continue
  347. }
  348. urls := c.ClientURLs()
  349. if !reflect.DeepEqual(urls, tt.wurls) {
  350. t.Errorf("#%d: ClientURLs = %v, want %v", i, urls, tt.wurls)
  351. }
  352. }
  353. }