cluster_test.go 7.4 KB

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