delete_handler_test.go 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. package v2
  2. import (
  3. "fmt"
  4. "net/url"
  5. "testing"
  6. "github.com/coreos/etcd/server"
  7. "github.com/coreos/etcd/tests"
  8. "github.com/stretchr/testify/assert"
  9. )
  10. // Ensures that a key is deleted.
  11. //
  12. // $ curl -X PUT localhost:4001/v2/keys/foo/bar -d value=XXX
  13. // $ curl -X DELETE localhost:4001/v2/keys/foo/bar
  14. //
  15. func TestV2DeleteKey(t *testing.T) {
  16. tests.RunServer(func(s *server.Server) {
  17. v := url.Values{}
  18. v.Set("value", "XXX")
  19. resp, err := tests.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo/bar"), v)
  20. tests.ReadBody(resp)
  21. resp, err = tests.DeleteForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo/bar"), url.Values{})
  22. body := tests.ReadBody(resp)
  23. assert.Nil(t, err, "")
  24. assert.Equal(t, string(body), `{"action":"delete","node":{"key":"/foo/bar","modifiedIndex":3,"createdIndex":2}}`, "")
  25. })
  26. }
  27. // Ensures that an empty directory is deleted when dir is set.
  28. //
  29. // $ curl -X PUT localhost:4001/v2/keys/foo?dir=true
  30. // $ curl -X PUT localhost:4001/v2/keys/foo ->fail
  31. // $ curl -X DELETE localhost:4001/v2/keys/foo?dir=true
  32. //
  33. func TestV2DeleteEmptyDirectory(t *testing.T) {
  34. tests.RunServer(func(s *server.Server) {
  35. resp, err := tests.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo?dir=true"), url.Values{})
  36. tests.ReadBody(resp)
  37. resp, err = tests.DeleteForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo"), url.Values{})
  38. bodyJson := tests.ReadBodyJSON(resp)
  39. assert.Equal(t, bodyJson["errorCode"], 102, "")
  40. resp, err = tests.DeleteForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo?dir=true"), url.Values{})
  41. body := tests.ReadBody(resp)
  42. assert.Nil(t, err, "")
  43. assert.Equal(t, string(body), `{"action":"delete","node":{"key":"/foo","dir":true,"modifiedIndex":3,"createdIndex":2}}`, "")
  44. })
  45. }
  46. // Ensures that a not-empty directory is deleted when dir is set.
  47. //
  48. // $ curl -X PUT localhost:4001/v2/keys/foo/bar?dir=true
  49. // $ curl -X DELETE localhost:4001/v2/keys/foo?dir=true ->fail
  50. // $ curl -X DELETE localhost:4001/v2/keys/foo?dir=true&recursive=true
  51. //
  52. func TestV2DeleteNonEmptyDirectory(t *testing.T) {
  53. tests.RunServer(func(s *server.Server) {
  54. resp, err := tests.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo/bar?dir=true"), url.Values{})
  55. tests.ReadBody(resp)
  56. resp, err = tests.DeleteForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo?dir=true"), url.Values{})
  57. bodyJson := tests.ReadBodyJSON(resp)
  58. assert.Equal(t, bodyJson["errorCode"], 108, "")
  59. resp, err = tests.DeleteForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo?dir=true&recursive=true"), url.Values{})
  60. body := tests.ReadBody(resp)
  61. assert.Nil(t, err, "")
  62. assert.Equal(t, string(body), `{"action":"delete","node":{"key":"/foo","dir":true,"modifiedIndex":3,"createdIndex":2}}`, "")
  63. })
  64. }
  65. // Ensures that a directory is deleted when recursive is set.
  66. //
  67. // $ curl -X PUT localhost:4001/v2/keys/foo?dir=true
  68. // $ curl -X DELETE localhost:4001/v2/keys/foo?recursive=true
  69. //
  70. func TestV2DeleteDirectoryRecursiveImpliesDir(t *testing.T) {
  71. tests.RunServer(func(s *server.Server) {
  72. resp, err := tests.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo?dir=true"), url.Values{})
  73. tests.ReadBody(resp)
  74. resp, err = tests.DeleteForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/foo?recursive=true"), url.Values{})
  75. body := tests.ReadBody(resp)
  76. assert.Nil(t, err, "")
  77. assert.Equal(t, string(body), `{"action":"delete","node":{"key":"/foo","dir":true,"modifiedIndex":3,"createdIndex":2}}`, "")
  78. })
  79. }
  80. // Ensures that a directory is deleted.
  81. //
  82. // $ curl -X PUT localhost:4001/v2/keys/foo/bar -d value=XXX
  83. // $ curl -X DELETE localhost:4001/v2/keys/foo?recursive=true
  84. //
  85. func TestV2DeleteDirectory(t *testing.T) {
  86. tests.RunServer(func(s *server.Server) {
  87. v := url.Values{}
  88. v.Set("value", "XXX")
  89. resp, err := tests.PutForm(fmt.Sprintf("http://%s%s", s.URL(), "/v2/keys/foo/bar"), v)
  90. tests.ReadBody(resp)
  91. resp, err = tests.DeleteForm(fmt.Sprintf("http://%s%s", s.URL(), "/v2/keys/foo?recursive=true"), url.Values{})
  92. assert.Nil(t, err, "")
  93. body := tests.ReadBodyJSON(resp)
  94. assert.Equal(t, body["action"], "delete", "")
  95. assert.Equal(t, body["dir"], true, "")
  96. assert.Equal(t, body["modifiedIndex"], 2, "")
  97. })
  98. }
  99. // Ensures that a directory is deleted if the previous index matches
  100. //
  101. // $ curl -X PUT localhost:4001/v2/keys/foo/bar -d value=XXX
  102. // $ curl -X DELETE localhost:4001/v2/keys/foo?recursive=true&prevIndex=1
  103. //
  104. func TestV2DeleteDirectoryCADOnIndexSuccess(t *testing.T) {
  105. tests.RunServer(func(s *server.Server) {
  106. v := url.Values{}
  107. v.Set("value", "XXX")
  108. resp, err := tests.PutForm(fmt.Sprintf("http://%s%s", s.URL(), "/v2/keys/foo/bar"), v)
  109. tests.ReadBody(resp)
  110. resp, err = tests.DeleteForm(fmt.Sprintf("http://%s%s", s.URL(), "/v2/keys/foo?recursive=true&prevIndex=1"), url.Values{})
  111. assert.Nil(t, err, "")
  112. body := tests.ReadBodyJSON(resp)
  113. assert.Equal(t, body["action"], "compareAndDelete", "")
  114. assert.Equal(t, body["dir"], true, "")
  115. assert.Equal(t, body["modifiedIndex"], 2, "")
  116. })
  117. }
  118. // Ensures that a directory is not deleted if the previous index does not match
  119. //
  120. // $ curl -X PUT localhost:4001/v2/keys/foo/bar -d value=XXX
  121. // $ curl -X DELETE localhost:4001/v2/keys/foo?recursive=true&prevIndex=100
  122. //
  123. func TestV2DeleteDirectoryCADOnIndexFail(t *testing.T) {
  124. tests.RunServer(func(s *server.Server) {
  125. v := url.Values{}
  126. v.Set("value", "XXX")
  127. resp, err := tests.PutForm(fmt.Sprintf("http://%s%s", s.URL(), "/v2/keys/foo/bar"), v)
  128. tests.ReadBody(resp)
  129. resp, err = tests.DeleteForm(fmt.Sprintf("http://%s%s", s.URL(), "/v2/keys/foo?recursive=true&prevIndex=100"), url.Values{})
  130. assert.Nil(t, err, "")
  131. body := tests.ReadBodyJSON(resp)
  132. assert.Equal(t, body["errorCode"], 101)
  133. })
  134. }
  135. // Ensures that a key is deleted only if the previous index matches.
  136. //
  137. // $ curl -X PUT localhost:4001/v2/keys/foo/bar -d value=XXX
  138. // $ curl -X DELETE localhost:4001/v2/keys/foo/bar?prevIndex=1
  139. //
  140. func TestV2DeleteKeyCADOnIndexSuccess(t *testing.T) {
  141. tests.RunServer(func(s *server.Server) {
  142. v := url.Values{}
  143. v.Set("value", "XXX")
  144. resp, _ := tests.PutForm(fmt.Sprintf("http://%s%s", s.URL(), "/v2/keys/foo/bar"), v)
  145. tests.ReadBody(resp)
  146. resp, _ = tests.DeleteForm(fmt.Sprintf("http://%s%s", s.URL(), "/v2/keys/foo/bar?prevIndex=1"), v)
  147. body := tests.ReadBodyJSON(resp)
  148. assert.Equal(t, body["action"], "compareAndDelete", "")
  149. assert.Equal(t, body["prevValue"], "XXX", "")
  150. assert.Equal(t, body["modifiedIndex"], 2, "")
  151. })
  152. }
  153. // Ensures that a key is not deleted if the previous index does not matche.
  154. //
  155. // $ curl -X PUT localhost:4001/v2/keys/foo/bar -d value=XXX
  156. // $ curl -X DELETE localhost:4001/v2/keys/foo/bar?prevIndex=2
  157. //
  158. func TestV2DeleteKeyCADOnIndexFail(t *testing.T) {
  159. tests.RunServer(func(s *server.Server) {
  160. v := url.Values{}
  161. v.Set("value", "XXX")
  162. resp, _ := tests.PutForm(fmt.Sprintf("http://%s%s", s.URL(), "/v2/keys/foo/bar"), v)
  163. tests.ReadBody(resp)
  164. resp, _ = tests.DeleteForm(fmt.Sprintf("http://%s%s", s.URL(), "/v2/keys/foo/bar?prevIndex=100"), v)
  165. body := tests.ReadBodyJSON(resp)
  166. assert.Equal(t, body["errorCode"], 101)
  167. })
  168. }
  169. // Ensures that an error is thrown if an invalid previous index is provided.
  170. //
  171. // $ curl -X PUT localhost:4001/v2/keys/foo/bar -d value=XXX
  172. // $ curl -X DELETE localhost:4001/v2/keys/foo/bar?prevIndex=bad_index
  173. //
  174. func TestV2DeleteKeyCADWithInvalidIndex(t *testing.T) {
  175. tests.RunServer(func(s *server.Server) {
  176. v := url.Values{}
  177. v.Set("value", "XXX")
  178. resp, _ := tests.PutForm(fmt.Sprintf("http://%s%s", s.URL(), "/v2/keys/foo/bar"), v)
  179. tests.ReadBody(resp)
  180. resp, _ = tests.DeleteForm(fmt.Sprintf("http://%s%s", s.URL(), "/v2/keys/foo/bar?prevIndex=bad_index"), v)
  181. body := tests.ReadBodyJSON(resp)
  182. assert.Equal(t, body["errorCode"], 203)
  183. })
  184. }
  185. // Ensures that a key is deleted only if the previous value matches.
  186. //
  187. // $ curl -X PUT localhost:4001/v2/keys/foo/bar -d value=XXX
  188. // $ curl -X DELETE localhost:4001/v2/keys/foo/bar?prevValue=XXX
  189. //
  190. func TestV2DeleteKeyCADOnValueSuccess(t *testing.T) {
  191. tests.RunServer(func(s *server.Server) {
  192. v := url.Values{}
  193. v.Set("value", "XXX")
  194. resp, _ := tests.PutForm(fmt.Sprintf("http://%s%s", s.URL(), "/v2/keys/foo/bar"), v)
  195. tests.ReadBody(resp)
  196. resp, _ = tests.DeleteForm(fmt.Sprintf("http://%s%s", s.URL(), "/v2/keys/foo/bar?prevValue=XXX"), v)
  197. body := tests.ReadBodyJSON(resp)
  198. assert.Equal(t, body["action"], "compareAndDelete", "")
  199. assert.Equal(t, body["prevValue"], "XXX", "")
  200. assert.Equal(t, body["modifiedIndex"], 2, "")
  201. })
  202. }
  203. // Ensures that a key is not deleted if the previous value does not matche.
  204. //
  205. // $ curl -X PUT localhost:4001/v2/keys/foo/bar -d value=XXX
  206. // $ curl -X DELETE localhost:4001/v2/keys/foo/bar?prevValue=YYY
  207. //
  208. func TestV2DeleteKeyCADOnValueFail(t *testing.T) {
  209. tests.RunServer(func(s *server.Server) {
  210. v := url.Values{}
  211. v.Set("value", "XXX")
  212. resp, _ := tests.PutForm(fmt.Sprintf("http://%s%s", s.URL(), "/v2/keys/foo/bar"), v)
  213. tests.ReadBody(resp)
  214. resp, _ = tests.DeleteForm(fmt.Sprintf("http://%s%s", s.URL(), "/v2/keys/foo/bar?prevValue=YYY"), v)
  215. body := tests.ReadBodyJSON(resp)
  216. assert.Equal(t, body["errorCode"], 101)
  217. })
  218. }
  219. // Ensures that an error is thrown if an invalid previous value is provided.
  220. //
  221. // $ curl -X PUT localhost:4001/v2/keys/foo/bar -d value=XXX
  222. // $ curl -X DELETE localhost:4001/v2/keys/foo/bar?prevIndex=
  223. //
  224. func TestV2DeleteKeyCADWithInvalidValue(t *testing.T) {
  225. tests.RunServer(func(s *server.Server) {
  226. v := url.Values{}
  227. v.Set("value", "XXX")
  228. resp, _ := tests.PutForm(fmt.Sprintf("http://%s%s", s.URL(), "/v2/keys/foo/bar"), v)
  229. tests.ReadBody(resp)
  230. resp, _ = tests.DeleteForm(fmt.Sprintf("http://%s%s", s.URL(), "/v2/keys/foo/bar?prevValue="), v)
  231. body := tests.ReadBodyJSON(resp)
  232. assert.Equal(t, body["errorCode"], 201)
  233. })
  234. }