peers_test.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. package etcdhttp
  2. import (
  3. "net/http"
  4. "net/http/httptest"
  5. "reflect"
  6. "sort"
  7. "strings"
  8. "testing"
  9. "github.com/coreos/etcd/raft/raftpb"
  10. )
  11. func TestPeers(t *testing.T) {
  12. tests := []struct {
  13. in string
  14. wids []int64
  15. wep []string
  16. waddrs []string
  17. wstring string
  18. }{
  19. {
  20. "1=1.1.1.1",
  21. []int64{1},
  22. []string{"http://1.1.1.1"},
  23. []string{"1.1.1.1"},
  24. "1=1.1.1.1",
  25. },
  26. {
  27. "2=2.2.2.2",
  28. []int64{2},
  29. []string{"http://2.2.2.2"},
  30. []string{"2.2.2.2"},
  31. "2=2.2.2.2",
  32. },
  33. {
  34. "1=1.1.1.1&1=1.1.1.2&2=2.2.2.2",
  35. []int64{1, 2},
  36. []string{"http://1.1.1.1", "http://1.1.1.2", "http://2.2.2.2"},
  37. []string{"1.1.1.1", "1.1.1.2", "2.2.2.2"},
  38. "1=1.1.1.1&1=1.1.1.2&2=2.2.2.2",
  39. },
  40. {
  41. "3=3.3.3.3&4=4.4.4.4&1=1.1.1.1&1=1.1.1.2&2=2.2.2.2",
  42. []int64{1, 2, 3, 4},
  43. []string{"http://1.1.1.1", "http://1.1.1.2", "http://2.2.2.2",
  44. "http://3.3.3.3", "http://4.4.4.4"},
  45. []string{"1.1.1.1", "1.1.1.2", "2.2.2.2", "3.3.3.3", "4.4.4.4"},
  46. "1=1.1.1.1&1=1.1.1.2&2=2.2.2.2&3=3.3.3.3&4=4.4.4.4",
  47. },
  48. }
  49. for i, tt := range tests {
  50. p := &Peers{}
  51. err := p.Set(tt.in)
  52. if err != nil {
  53. t.Errorf("#%d: err=%v, want nil", i, err)
  54. }
  55. ids := int64Slice(p.IDs())
  56. sort.Sort(ids)
  57. if !reflect.DeepEqual([]int64(ids), tt.wids) {
  58. t.Errorf("#%d: IDs=%#v, want %#v", i, []int64(ids), tt.wids)
  59. }
  60. ep := p.Endpoints()
  61. if !reflect.DeepEqual(ep, tt.wep) {
  62. t.Errorf("#%d: Endpoints=%#v, want %#v", i, ep, tt.wep)
  63. }
  64. addrs := p.Addrs()
  65. if !reflect.DeepEqual(addrs, tt.waddrs) {
  66. t.Errorf("#%d: addrs=%#v, want %#v", i, ep, tt.waddrs)
  67. }
  68. s := p.String()
  69. if s != tt.wstring {
  70. t.Errorf("#%d: string=%q, want %q", i, s, tt.wstring)
  71. }
  72. }
  73. }
  74. type int64Slice []int64
  75. func (p int64Slice) Len() int { return len(p) }
  76. func (p int64Slice) Less(i, j int) bool { return p[i] < p[j] }
  77. func (p int64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
  78. func TestPeersSetBad(t *testing.T) {
  79. tests := []string{
  80. // garbage URL
  81. "asdf%%",
  82. // non-int64 keys
  83. "a=1.2.3.4",
  84. "-1-23=1.2.3.4",
  85. }
  86. for i, tt := range tests {
  87. p := &Peers{}
  88. if err := p.Set(tt); err == nil {
  89. t.Errorf("#%d: err=nil unexpectedly", i)
  90. }
  91. }
  92. }
  93. func TestPeersPick(t *testing.T) {
  94. ps := &Peers{
  95. 1: []string{"abc", "def", "ghi", "jkl", "mno", "pqr", "stu"},
  96. 2: []string{"xyz"},
  97. 3: []string{},
  98. }
  99. ids := map[string]bool{
  100. "abc": true,
  101. "def": true,
  102. "ghi": true,
  103. "jkl": true,
  104. "mno": true,
  105. "pqr": true,
  106. "stu": true,
  107. }
  108. for i := 0; i < 1000; i++ {
  109. a := ps.Pick(1)
  110. if _, ok := ids[a]; !ok {
  111. t.Errorf("returned ID %q not in expected range!", a)
  112. break
  113. }
  114. }
  115. if b := ps.Pick(2); b != "xyz" {
  116. t.Errorf("id=%q, want %q", b, "xyz")
  117. }
  118. if c := ps.Pick(3); c != "" {
  119. t.Errorf("id=%q, want \"\"", c)
  120. }
  121. }
  122. func TestHttpPost(t *testing.T) {
  123. var tr *http.Request
  124. tests := []struct {
  125. h http.HandlerFunc
  126. w bool
  127. }{
  128. {
  129. http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  130. tr = r
  131. w.WriteHeader(http.StatusNoContent)
  132. }),
  133. true,
  134. },
  135. {
  136. http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  137. tr = r
  138. w.WriteHeader(http.StatusNotFound)
  139. }),
  140. false,
  141. },
  142. {
  143. http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  144. tr = r
  145. w.WriteHeader(http.StatusInternalServerError)
  146. }),
  147. false,
  148. },
  149. }
  150. for i, tt := range tests {
  151. ts := httptest.NewServer(tt.h)
  152. if g := httpPost(http.DefaultClient, ts.URL, []byte("adsf")); g != tt.w {
  153. t.Errorf("#%d: httpPost()=%t, want %t", i, g, tt.w)
  154. }
  155. if tr.Method != "POST" {
  156. t.Errorf("#%d: Method=%q, want %q", i, tr.Method, "POST")
  157. }
  158. if ct := tr.Header.Get("Content-Type"); ct != "application/protobuf" {
  159. t.Errorf("#%d: Content-Type=%q, want %q", i, ct, "application/protobuf")
  160. }
  161. tr = nil
  162. ts.Close()
  163. }
  164. if httpPost(http.DefaultClient, "garbage url", []byte("data")) {
  165. t.Errorf("httpPost with bad URL returned true unexpectedly!")
  166. }
  167. }
  168. func TestSend(t *testing.T) {
  169. var tr *http.Request
  170. var rc int
  171. h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  172. tr = r
  173. w.WriteHeader(rc)
  174. })
  175. tests := []struct {
  176. m raftpb.Message
  177. code int
  178. ok bool
  179. }{
  180. {
  181. // all good
  182. raftpb.Message{
  183. To: 42,
  184. Type: 4,
  185. },
  186. http.StatusNoContent,
  187. true,
  188. },
  189. {
  190. // bad response from server should be silently ignored
  191. raftpb.Message{
  192. To: 42,
  193. Type: 2,
  194. },
  195. http.StatusInternalServerError,
  196. true,
  197. },
  198. {
  199. // unknown destination!
  200. raftpb.Message{
  201. To: 3,
  202. Type: 2,
  203. },
  204. 0,
  205. false,
  206. },
  207. }
  208. for i, tt := range tests {
  209. tr = nil
  210. rc = tt.code
  211. ts := httptest.NewServer(h)
  212. ps := Peers{
  213. 42: []string{strings.TrimPrefix(ts.URL, "http://")},
  214. }
  215. send(http.DefaultClient, "http", ps, tt.m)
  216. if !tt.ok {
  217. if tr != nil {
  218. t.Errorf("#%d: got request=%#v, want nil", i, tr)
  219. }
  220. ts.Close()
  221. continue
  222. }
  223. if tr.Method != "POST" {
  224. t.Errorf("#%d: Method=%q, want %q", i, tr.Method, "POST")
  225. }
  226. if ct := tr.Header.Get("Content-Type"); ct != "application/protobuf" {
  227. t.Errorf("#%d: Content-Type=%q, want %q", i, ct, "application/protobuf")
  228. }
  229. if tr.URL.String() != "/raft" {
  230. t.Errorf("#%d: URL=%q, want %q", i, tr.URL.String(), "/raft")
  231. }
  232. ts.Close()
  233. }
  234. }