v2_http_endpoint_test.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. package etcd
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io/ioutil"
  7. "net/http"
  8. "reflect"
  9. "sort"
  10. "strings"
  11. "testing"
  12. "time"
  13. "github.com/coreos/etcd/config"
  14. "github.com/coreos/etcd/store"
  15. )
  16. func TestMachinesEndPoint(t *testing.T) {
  17. es, hs := buildCluster(3, false)
  18. waitCluster(t, es)
  19. w := make([]string, len(hs))
  20. for i := range hs {
  21. w[i] = hs[i].URL
  22. }
  23. for i := range hs {
  24. r, err := http.Get(hs[i].URL + v2machinePrefix)
  25. if err != nil {
  26. t.Errorf("%v", err)
  27. break
  28. }
  29. b, err := ioutil.ReadAll(r.Body)
  30. r.Body.Close()
  31. if err != nil {
  32. t.Errorf("%v", err)
  33. break
  34. }
  35. g := strings.Split(string(b), ",")
  36. sort.Strings(g)
  37. if !reflect.DeepEqual(w, g) {
  38. t.Errorf("machines = %v, want %v", g, w)
  39. }
  40. }
  41. for i := range es {
  42. es[len(es)-i-1].Stop()
  43. }
  44. for i := range hs {
  45. hs[len(hs)-i-1].Close()
  46. }
  47. afterTest(t)
  48. }
  49. func TestLeaderEndPoint(t *testing.T) {
  50. es, hs := buildCluster(3, false)
  51. waitCluster(t, es)
  52. us := make([]string, len(hs))
  53. for i := range hs {
  54. us[i] = hs[i].URL
  55. }
  56. // todo(xiangli) change this to raft port...
  57. w := hs[0].URL + "/raft"
  58. for i := range hs {
  59. r, err := http.Get(hs[i].URL + v2LeaderPrefix)
  60. if err != nil {
  61. t.Errorf("%v", err)
  62. break
  63. }
  64. b, err := ioutil.ReadAll(r.Body)
  65. r.Body.Close()
  66. if err != nil {
  67. t.Errorf("%v", err)
  68. break
  69. }
  70. if string(b) != w {
  71. t.Errorf("leader = %v, want %v", string(b), w)
  72. }
  73. }
  74. for i := range es {
  75. es[len(es)-i-1].Stop()
  76. }
  77. for i := range hs {
  78. hs[len(hs)-i-1].Close()
  79. }
  80. afterTest(t)
  81. }
  82. func TestStoreStatsEndPoint(t *testing.T) {
  83. es, hs := buildCluster(1, false)
  84. waitCluster(t, es)
  85. resp, err := http.Get(hs[0].URL + v2StoreStatsPrefix)
  86. if err != nil {
  87. t.Errorf("%v", err)
  88. }
  89. stats := new(store.Stats)
  90. d := json.NewDecoder(resp.Body)
  91. err = d.Decode(stats)
  92. resp.Body.Close()
  93. if err != nil {
  94. t.Errorf("%v", err)
  95. }
  96. if stats.SetSuccess != 1 {
  97. t.Errorf("setSuccess = %d, want 1", stats.SetSuccess)
  98. }
  99. for i := range es {
  100. es[len(es)-i-1].Stop()
  101. }
  102. for i := range hs {
  103. hs[len(hs)-i-1].Close()
  104. }
  105. afterTest(t)
  106. }
  107. func TestGetAdminConfigEndPoint(t *testing.T) {
  108. es, hs := buildCluster(3, false)
  109. waitCluster(t, es)
  110. for i := range hs {
  111. r, err := http.Get(hs[i].URL + v2adminConfigPrefix)
  112. if err != nil {
  113. t.Errorf("%v", err)
  114. continue
  115. }
  116. if g := r.StatusCode; g != 200 {
  117. t.Errorf("#%d: status = %d, want %d", i, g, 200)
  118. }
  119. if g := r.Header.Get("Content-Type"); g != "application/json" {
  120. t.Errorf("#%d: ContentType = %d, want application/json", i, g)
  121. }
  122. conf := new(config.ClusterConfig)
  123. err = json.NewDecoder(r.Body).Decode(conf)
  124. r.Body.Close()
  125. if err != nil {
  126. t.Errorf("%v", err)
  127. continue
  128. }
  129. w := config.NewClusterConfig()
  130. if !reflect.DeepEqual(conf, w) {
  131. t.Errorf("#%d: config = %+v, want %+v", i, conf, w)
  132. }
  133. }
  134. for i := range es {
  135. es[len(es)-i-1].Stop()
  136. }
  137. for i := range hs {
  138. hs[len(hs)-i-1].Close()
  139. }
  140. afterTest(t)
  141. }
  142. func TestPutAdminConfigEndPoint(t *testing.T) {
  143. tests := []struct {
  144. c, wc string
  145. }{
  146. {
  147. `{"activeSize":1,"removeDelay":1,"syncInterval":1}`,
  148. `{"activeSize":3,"removeDelay":2,"syncInterval":1}`,
  149. },
  150. {
  151. `{"activeSize":5,"removeDelay":20.5,"syncInterval":1.5}`,
  152. `{"activeSize":5,"removeDelay":20.5,"syncInterval":1.5}`,
  153. },
  154. {
  155. `{"activeSize":5 , "removeDelay":20 , "syncInterval": 2 }`,
  156. `{"activeSize":5,"removeDelay":20,"syncInterval":2}`,
  157. },
  158. {
  159. `{"activeSize":3, "removeDelay":60}`,
  160. `{"activeSize":3,"removeDelay":60,"syncInterval":5}`,
  161. },
  162. }
  163. for i, tt := range tests {
  164. es, hs := buildCluster(3, false)
  165. waitCluster(t, es)
  166. r, err := NewTestClient().Put(hs[0].URL+v2adminConfigPrefix, "application/json", bytes.NewBufferString(tt.c))
  167. if err != nil {
  168. t.Fatalf("%v", err)
  169. }
  170. b, err := ioutil.ReadAll(r.Body)
  171. r.Body.Close()
  172. if err != nil {
  173. t.Fatalf("%v", err)
  174. }
  175. if wbody := append([]byte(tt.wc), '\n'); !reflect.DeepEqual(b, wbody) {
  176. t.Errorf("#%d: put result = %s, want %s", i, b, wbody)
  177. }
  178. barrier(t, 0, es)
  179. for j := range es {
  180. e, err := es[j].Get(v2configKVPrefix, false, false)
  181. if err != nil {
  182. t.Errorf("%v", err)
  183. continue
  184. }
  185. if g := *e.Node.Value; g != tt.wc {
  186. t.Errorf("#%d.%d: %s = %s, want %s", i, j, v2configKVPrefix, g, tt.wc)
  187. }
  188. }
  189. for j := range es {
  190. es[len(es)-j-1].Stop()
  191. }
  192. for j := range hs {
  193. hs[len(hs)-j-1].Close()
  194. }
  195. }
  196. afterTest(t)
  197. }
  198. func TestGetAdminMachineEndPoint(t *testing.T) {
  199. es, hs := buildCluster(3, false)
  200. waitCluster(t, es)
  201. for i := range es {
  202. for j := range hs {
  203. name := fmt.Sprint(es[i].id)
  204. r, err := http.Get(hs[j].URL + v2adminMachinesPrefix + name)
  205. if err != nil {
  206. t.Errorf("%v", err)
  207. continue
  208. }
  209. if g := r.StatusCode; g != 200 {
  210. t.Errorf("#%d on %d: status = %d, want %d", i, j, g, 200)
  211. }
  212. if g := r.Header.Get("Content-Type"); g != "application/json" {
  213. t.Errorf("#%d on %d: ContentType = %d, want application/json", i, j, g)
  214. }
  215. m := new(machineMessage)
  216. err = json.NewDecoder(r.Body).Decode(m)
  217. r.Body.Close()
  218. if err != nil {
  219. t.Errorf("%v", err)
  220. continue
  221. }
  222. wm := &machineMessage{
  223. Name: name,
  224. State: stateFollower,
  225. ClientURL: hs[i].URL,
  226. PeerURL: hs[i].URL,
  227. }
  228. if i == 0 {
  229. wm.State = stateLeader
  230. }
  231. if !reflect.DeepEqual(m, wm) {
  232. t.Errorf("#%d on %d: body = %+v, want %+v", i, j, m, wm)
  233. }
  234. }
  235. }
  236. for i := range es {
  237. es[len(es)-i-1].Stop()
  238. }
  239. for i := range hs {
  240. hs[len(hs)-i-1].Close()
  241. }
  242. afterTest(t)
  243. }
  244. func TestGetAdminMachinesEndPoint(t *testing.T) {
  245. es, hs := buildCluster(3, false)
  246. waitCluster(t, es)
  247. w := make([]*machineMessage, len(hs))
  248. for i := range hs {
  249. w[i] = &machineMessage{
  250. Name: fmt.Sprint(es[i].id),
  251. State: stateFollower,
  252. ClientURL: hs[i].URL,
  253. PeerURL: hs[i].URL,
  254. }
  255. }
  256. w[0].State = stateLeader
  257. for i := range hs {
  258. r, err := http.Get(hs[i].URL + v2adminMachinesPrefix)
  259. if err != nil {
  260. t.Errorf("%v", err)
  261. continue
  262. }
  263. m := make([]*machineMessage, 0)
  264. err = json.NewDecoder(r.Body).Decode(&m)
  265. r.Body.Close()
  266. if err != nil {
  267. t.Errorf("%v", err)
  268. continue
  269. }
  270. sm := machineSlice(m)
  271. sw := machineSlice(w)
  272. sort.Sort(sm)
  273. sort.Sort(sw)
  274. if !reflect.DeepEqual(sm, sw) {
  275. t.Errorf("on %d: machines = %+v, want %+v", i, sm, sw)
  276. }
  277. }
  278. for i := range es {
  279. es[len(es)-i-1].Stop()
  280. }
  281. for i := range hs {
  282. hs[len(hs)-i-1].Close()
  283. }
  284. afterTest(t)
  285. }
  286. // barrier ensures that all servers have made further progress on applied index
  287. // compared to the base one.
  288. func barrier(t *testing.T, base int, es []*Server) {
  289. applied := es[base].node.Applied()
  290. // time used for goroutine scheduling
  291. time.Sleep(5 * time.Millisecond)
  292. for i, e := range es {
  293. for j := 0; ; j++ {
  294. if e.node.Applied() >= applied {
  295. break
  296. }
  297. time.Sleep(defaultHeartbeat * defaultTickDuration)
  298. if j == 2 {
  299. t.Fatalf("#%d: applied = %d, want >= %d", i, e.node.Applied(), applied)
  300. }
  301. }
  302. }
  303. }
  304. // int64Slice implements sort interface
  305. type machineSlice []*machineMessage
  306. func (s machineSlice) Len() int { return len(s) }
  307. func (s machineSlice) Less(i, j int) bool { return s[i].Name < s[j].Name }
  308. func (s machineSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }