store_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. package store
  2. import (
  3. "testing"
  4. "time"
  5. etcdErr "github.com/coreos/etcd/error"
  6. "github.com/stretchr/testify/assert"
  7. )
  8. // Ensure that the store can retrieve an existing value.
  9. func TestStoreGetValue(t *testing.T) {
  10. s := newStore()
  11. s.Create("/foo", "bar", false, Permanent, 2, 1)
  12. e, err := s.Get("/foo", false, false, 2, 1)
  13. assert.Nil(t, err, "")
  14. assert.Equal(t, e.Action, "get", "")
  15. assert.Equal(t, e.Key, "/foo", "")
  16. assert.Equal(t, e.Value, "bar", "")
  17. }
  18. // Ensure that the store can recrusively retrieve a directory listing.
  19. // Note that hidden files should not be returned.
  20. func TestStoreGetDirectory(t *testing.T) {
  21. s := newStore()
  22. s.Create("/foo", "", false, Permanent, 2, 1)
  23. s.Create("/foo/bar", "X", false, Permanent, 3, 1)
  24. s.Create("/foo/_hidden", "*", false, Permanent, 4, 1)
  25. s.Create("/foo/baz", "", false, Permanent, 5, 1)
  26. s.Create("/foo/baz/bat", "Y", false, Permanent, 6, 1)
  27. s.Create("/foo/baz/_hidden", "*", false, Permanent, 7, 1)
  28. e, err := s.Get("/foo", true, false, 8, 1)
  29. assert.Nil(t, err, "")
  30. assert.Equal(t, e.Action, "get", "")
  31. assert.Equal(t, e.Key, "/foo", "")
  32. assert.Equal(t, len(e.KVPairs), 2, "")
  33. assert.Equal(t, e.KVPairs[0].Key, "/foo/bar", "")
  34. assert.Equal(t, e.KVPairs[0].Value, "X", "")
  35. assert.Equal(t, e.KVPairs[0].Dir, false, "")
  36. assert.Equal(t, e.KVPairs[1].Key, "/foo/baz", "")
  37. assert.Equal(t, e.KVPairs[1].Dir, true, "")
  38. assert.Equal(t, len(e.KVPairs[1].KVPairs), 1, "")
  39. assert.Equal(t, e.KVPairs[1].KVPairs[0].Key, "/foo/baz/bat", "")
  40. assert.Equal(t, e.KVPairs[1].KVPairs[0].Value, "Y", "")
  41. assert.Equal(t, e.KVPairs[1].KVPairs[0].Dir, false, "")
  42. }
  43. // Ensure that the store can retrieve a directory in sorted order.
  44. func TestStoreGetSorted(t *testing.T) {
  45. s := newStore()
  46. s.Create("/foo", "", false, Permanent, 2, 1)
  47. s.Create("/foo/x", "0", false, Permanent, 3, 1)
  48. s.Create("/foo/z", "0", false, Permanent, 4, 1)
  49. s.Create("/foo/y", "", false, Permanent, 5, 1)
  50. s.Create("/foo/y/a", "0", false, Permanent, 6, 1)
  51. s.Create("/foo/y/b", "0", false, Permanent, 7, 1)
  52. e, err := s.Get("/foo", true, true, 8, 1)
  53. assert.Nil(t, err, "")
  54. assert.Equal(t, e.KVPairs[0].Key, "/foo/x", "")
  55. assert.Equal(t, e.KVPairs[1].Key, "/foo/y", "")
  56. assert.Equal(t, e.KVPairs[1].KVPairs[0].Key, "/foo/y/a", "")
  57. assert.Equal(t, e.KVPairs[1].KVPairs[1].Key, "/foo/y/b", "")
  58. assert.Equal(t, e.KVPairs[2].Key, "/foo/z", "")
  59. }
  60. // Ensure that the store can create a new key if it doesn't already exist.
  61. func TestStoreCreateValue(t *testing.T) {
  62. s := newStore()
  63. e, err := s.Create("/foo", "bar", false, Permanent, 2, 1)
  64. assert.Nil(t, err, "")
  65. assert.Equal(t, e.Action, "create", "")
  66. assert.Equal(t, e.Key, "/foo", "")
  67. assert.False(t, e.Dir, "")
  68. assert.Equal(t, e.PrevValue, "", "")
  69. assert.Equal(t, e.Value, "bar", "")
  70. assert.Nil(t, e.KVPairs, "")
  71. assert.Nil(t, e.Expiration, "")
  72. assert.Equal(t, e.TTL, 0, "")
  73. assert.Equal(t, e.Index, uint64(2), "")
  74. assert.Equal(t, e.Term, uint64(1), "")
  75. }
  76. // Ensure that the store can create a new directory if it doesn't already exist.
  77. func TestStoreCreateDirectory(t *testing.T) {
  78. s := newStore()
  79. e, err := s.Create("/foo", "", false, Permanent, 2, 1)
  80. assert.Nil(t, err, "")
  81. assert.Equal(t, e.Action, "create", "")
  82. assert.Equal(t, e.Key, "/foo", "")
  83. assert.True(t, e.Dir, "")
  84. }
  85. // Ensure that the store fails to create a key if it already exists.
  86. func TestStoreCreateFailsIfExists(t *testing.T) {
  87. s := newStore()
  88. s.Create("/foo", "", false, Permanent, 2, 1)
  89. e, _err := s.Create("/foo", "", false, Permanent, 3, 1)
  90. err := _err.(*etcdErr.Error)
  91. assert.Equal(t, err.ErrorCode, etcdErr.EcodeNodeExist, "")
  92. assert.Equal(t, err.Message, "Already exists", "")
  93. assert.Equal(t, err.Cause, "/foo", "")
  94. assert.Equal(t, err.Index, uint64(3), "")
  95. assert.Equal(t, err.Term, uint64(1), "")
  96. assert.Nil(t, e, 0, "")
  97. }
  98. // Ensure that the store can update a key if it already exists.
  99. func TestStoreUpdateValue(t *testing.T) {
  100. s := newStore()
  101. s.Create("/foo", "bar", false, Permanent, 2, 1)
  102. e, err := s.Update("/foo", "baz", Permanent, 3, 1)
  103. assert.Nil(t, err, "")
  104. assert.Equal(t, e.Action, "update", "")
  105. assert.Equal(t, e.Key, "/foo", "")
  106. assert.False(t, e.Dir, "")
  107. assert.Equal(t, e.PrevValue, "bar", "")
  108. assert.Equal(t, e.Value, "baz", "")
  109. assert.Equal(t, e.TTL, 0, "")
  110. assert.Equal(t, e.Index, uint64(3), "")
  111. assert.Equal(t, e.Term, uint64(1), "")
  112. e, _ = s.Get("/foo", false, false, 3, 1)
  113. assert.Equal(t, e.Value, "baz", "")
  114. }
  115. // Ensure that the store cannot update a directory.
  116. func TestStoreUpdateFailsIfDirectory(t *testing.T) {
  117. s := newStore()
  118. s.Create("/foo", "", false, Permanent, 2, 1)
  119. e, _err := s.Update("/foo", "baz", Permanent, 3, 1)
  120. err := _err.(*etcdErr.Error)
  121. assert.Equal(t, err.ErrorCode, etcdErr.EcodeNotFile, "")
  122. assert.Equal(t, err.Message, "Not A File", "")
  123. assert.Equal(t, err.Cause, "/foo", "")
  124. assert.Nil(t, e, "")
  125. }
  126. // Ensure that the store can update the TTL on a value.
  127. func TestStoreUpdateValueTTL(t *testing.T) {
  128. s := newStore()
  129. s.Create("/foo", "bar", false, Permanent, 2, 1)
  130. _, err := s.Update("/foo", "baz", time.Now().Add(1 * time.Millisecond), 3, 1)
  131. e, _ := s.Get("/foo", false, false, 3, 1)
  132. assert.Equal(t, e.Value, "baz", "")
  133. time.Sleep(2 * time.Millisecond)
  134. e, err = s.Get("/foo", false, false, 3, 1)
  135. assert.Nil(t, e, "")
  136. assert.Equal(t, err.(*etcdErr.Error).ErrorCode, etcdErr.EcodeKeyNotFound, "")
  137. }
  138. // Ensure that the store can update the TTL on a directory.
  139. func TestStoreUpdateDirTTL(t *testing.T) {
  140. s := newStore()
  141. s.Create("/foo", "", false, Permanent, 2, 1)
  142. s.Create("/foo/bar", "baz", false, Permanent, 3, 1)
  143. _, err := s.Update("/foo", "", time.Now().Add(1 * time.Millisecond), 3, 1)
  144. e, _ := s.Get("/foo/bar", false, false, 3, 1)
  145. assert.Equal(t, e.Value, "baz", "")
  146. time.Sleep(2 * time.Millisecond)
  147. e, err = s.Get("/foo/bar", false, false, 3, 1)
  148. assert.Nil(t, e, "")
  149. assert.Equal(t, err.(*etcdErr.Error).ErrorCode, etcdErr.EcodeKeyNotFound, "")
  150. }
  151. // Ensure that the store can delete a value.
  152. func TestStoreDeleteValue(t *testing.T) {
  153. s := newStore()
  154. s.Create("/foo", "bar", false, Permanent, 2, 1)
  155. e, err := s.Delete("/foo", false, 3, 1)
  156. assert.Nil(t, err, "")
  157. assert.Equal(t, e.Action, "delete", "")
  158. }
  159. // Ensure that the store can delete a directory if recursive is specified.
  160. func TestStoreDeleteDiretory(t *testing.T) {
  161. s := newStore()
  162. s.Create("/foo", "", false, Permanent, 2, 1)
  163. e, err := s.Delete("/foo", true, 3, 1)
  164. assert.Nil(t, err, "")
  165. assert.Equal(t, e.Action, "delete", "")
  166. }
  167. // Ensure that the store cannot delete a directory if recursive is not specified.
  168. func TestStoreDeleteDiretoryFailsIfNonRecursive(t *testing.T) {
  169. s := newStore()
  170. s.Create("/foo", "", false, Permanent, 2, 1)
  171. e, _err := s.Delete("/foo", false, 3, 1)
  172. err := _err.(*etcdErr.Error)
  173. assert.Equal(t, err.ErrorCode, etcdErr.EcodeNotFile, "")
  174. assert.Equal(t, err.Message, "Not A File", "")
  175. assert.Nil(t, e, "")
  176. }
  177. // Ensure that the store can conditionally update a key if it has a previous value.
  178. func TestStoreCompareAndSwapPrevValue(t *testing.T) {
  179. s := newStore()
  180. s.Create("/foo", "bar", false, Permanent, 2, 1)
  181. e, err := s.CompareAndSwap("/foo", "bar", 0, "baz", Permanent, 3, 1)
  182. assert.Nil(t, err, "")
  183. assert.Equal(t, e.Action, "compareAndSwap", "")
  184. assert.Equal(t, e.PrevValue, "bar", "")
  185. assert.Equal(t, e.Value, "baz", "")
  186. e, _ = s.Get("/foo", false, false, 3, 1)
  187. assert.Equal(t, e.Value, "baz", "")
  188. }
  189. // Ensure that the store cannot conditionally update a key if it has the wrong previous value.
  190. func TestStoreCompareAndSwapPrevValueFailsIfNotMatch(t *testing.T) {
  191. s := newStore()
  192. s.Create("/foo", "bar", false, Permanent, 2, 1)
  193. e, _err := s.CompareAndSwap("/foo", "wrong_value", 0, "baz", Permanent, 3, 1)
  194. err := _err.(*etcdErr.Error)
  195. assert.Equal(t, err.ErrorCode, etcdErr.EcodeTestFailed, "")
  196. assert.Equal(t, err.Message, "Test Failed", "")
  197. assert.Nil(t, e, "")
  198. e, _ = s.Get("/foo", false, false, 3, 1)
  199. assert.Equal(t, e.Value, "bar", "")
  200. }
  201. // Ensure that the store can conditionally update a key if it has a previous index.
  202. func TestStoreCompareAndSwapPrevIndex(t *testing.T) {
  203. s := newStore()
  204. s.Create("/foo", "bar", false, Permanent, 2, 1)
  205. e, err := s.CompareAndSwap("/foo", "", 2, "baz", Permanent, 3, 1)
  206. assert.Nil(t, err, "")
  207. assert.Equal(t, e.Action, "compareAndSwap", "")
  208. assert.Equal(t, e.PrevValue, "bar", "")
  209. assert.Equal(t, e.Value, "baz", "")
  210. e, _ = s.Get("/foo", false, false, 3, 1)
  211. assert.Equal(t, e.Value, "baz", "")
  212. }
  213. // Ensure that the store cannot conditionally update a key if it has the wrong previous index.
  214. func TestStoreCompareAndSwapPrevIndexFailsIfNotMatch(t *testing.T) {
  215. s := newStore()
  216. s.Create("/foo", "bar", false, Permanent, 2, 1)
  217. e, _err := s.CompareAndSwap("/foo", "", 100, "baz", Permanent, 3, 1)
  218. err := _err.(*etcdErr.Error)
  219. assert.Equal(t, err.ErrorCode, etcdErr.EcodeTestFailed, "")
  220. assert.Equal(t, err.Message, "Test Failed", "")
  221. assert.Nil(t, e, "")
  222. e, _ = s.Get("/foo", false, false, 3, 1)
  223. assert.Equal(t, e.Value, "bar", "")
  224. }
  225. // Ensure that the store can watch for key creation.
  226. func TestStoreWatchCreate(t *testing.T) {
  227. s := newStore()
  228. c, _ := s.Watch("/foo", false, 0, 0, 1)
  229. s.Create("/foo", "bar", false, Permanent, 2, 1)
  230. e := nbselect(c)
  231. assert.Equal(t, e.Action, "create", "")
  232. assert.Equal(t, e.Key, "/foo", "")
  233. e = nbselect(c)
  234. assert.Nil(t, e, "")
  235. }
  236. // Ensure that the store can watch for recursive key creation.
  237. func TestStoreWatchRecursiveCreate(t *testing.T) {
  238. s := newStore()
  239. c, _ := s.Watch("/foo", true, 0, 0, 1)
  240. s.Create("/foo/bar", "baz", false, Permanent, 2, 1)
  241. e := nbselect(c)
  242. assert.Equal(t, e.Action, "create", "")
  243. assert.Equal(t, e.Key, "/foo/bar", "")
  244. }
  245. // Ensure that the store can watch for key updates.
  246. func TestStoreWatchUpdate(t *testing.T) {
  247. s := newStore()
  248. s.Create("/foo", "bar", false, Permanent, 2, 1)
  249. c, _ := s.Watch("/foo", false, 0, 0, 1)
  250. s.Update("/foo", "baz", Permanent, 3, 1)
  251. e := nbselect(c)
  252. assert.Equal(t, e.Action, "update", "")
  253. assert.Equal(t, e.Key, "/foo", "")
  254. }
  255. // Ensure that the store can watch for recursive key updates.
  256. func TestStoreWatchRecursiveUpdate(t *testing.T) {
  257. s := newStore()
  258. s.Create("/foo/bar", "baz", false, Permanent, 2, 1)
  259. c, _ := s.Watch("/foo", true, 0, 0, 1)
  260. s.Update("/foo/bar", "baz", Permanent, 3, 1)
  261. e := nbselect(c)
  262. assert.Equal(t, e.Action, "update", "")
  263. assert.Equal(t, e.Key, "/foo/bar", "")
  264. }
  265. // Ensure that the store can watch for key deletions.
  266. func TestStoreWatchDelete(t *testing.T) {
  267. s := newStore()
  268. s.Create("/foo", "bar", false, Permanent, 2, 1)
  269. c, _ := s.Watch("/foo", false, 0, 0, 1)
  270. s.Delete("/foo", false, 3, 1)
  271. e := nbselect(c)
  272. assert.Equal(t, e.Action, "delete", "")
  273. assert.Equal(t, e.Key, "/foo", "")
  274. }
  275. // Ensure that the store can watch for recursive key deletions.
  276. func TestStoreWatchRecursiveDelete(t *testing.T) {
  277. s := newStore()
  278. s.Create("/foo/bar", "baz", false, Permanent, 2, 1)
  279. c, _ := s.Watch("/foo", true, 0, 0, 1)
  280. s.Delete("/foo/bar", false, 3, 1)
  281. e := nbselect(c)
  282. assert.Equal(t, e.Action, "delete", "")
  283. assert.Equal(t, e.Key, "/foo/bar", "")
  284. }
  285. // Ensure that the store can watch for CAS updates.
  286. func TestStoreWatchCompareAndSwap(t *testing.T) {
  287. s := newStore()
  288. s.Create("/foo", "bar", false, Permanent, 2, 1)
  289. c, _ := s.Watch("/foo", false, 0, 0, 1)
  290. s.CompareAndSwap("/foo", "bar", 0, "baz", Permanent, 3, 1)
  291. e := nbselect(c)
  292. assert.Equal(t, e.Action, "compareAndSwap", "")
  293. assert.Equal(t, e.Key, "/foo", "")
  294. }
  295. // Ensure that the store can watch for recursive CAS updates.
  296. func TestStoreWatchRecursiveCompareAndSwap(t *testing.T) {
  297. s := newStore()
  298. s.Create("/foo/bar", "baz", false, Permanent, 2, 1)
  299. c, _ := s.Watch("/foo", true, 0, 0, 1)
  300. s.CompareAndSwap("/foo/bar", "baz", 0, "bat", Permanent, 3, 1)
  301. e := nbselect(c)
  302. assert.Equal(t, e.Action, "compareAndSwap", "")
  303. assert.Equal(t, e.Key, "/foo/bar", "")
  304. }
  305. // Ensure that the store can watch for key expiration.
  306. func TestStoreWatchExpire(t *testing.T) {
  307. s := newStore()
  308. s.Create("/foo", "bar", false, time.Now().Add(1 * time.Millisecond), 2, 1)
  309. c, _ := s.Watch("/foo", false, 0, 0, 1)
  310. e := nbselect(c)
  311. assert.Nil(t, e, "")
  312. time.Sleep(2 * time.Millisecond)
  313. e = nbselect(c)
  314. assert.Equal(t, e.Action, "expire", "")
  315. assert.Equal(t, e.Key, "/foo", "")
  316. }
  317. // Ensure that the store can recover from a previously saved state.
  318. func TestStoreRecover(t *testing.T) {
  319. s := newStore()
  320. s.Create("/foo", "", false, Permanent, 2, 1)
  321. s.Create("/foo/x", "bar", false, Permanent, 3, 1)
  322. s.Create("/foo/y", "baz", false, Permanent, 4, 1)
  323. b, err := s.Save()
  324. s2 := newStore()
  325. s2.Recovery(b)
  326. e, err := s.Get("/foo/x", false, false, 4, 1)
  327. assert.Nil(t, err, "")
  328. assert.Equal(t, e.Value, "bar", "")
  329. e, err = s.Get("/foo/y", false, false, 4, 1)
  330. assert.Nil(t, err, "")
  331. assert.Equal(t, e.Value, "baz", "")
  332. }
  333. // Ensure that the store can recover from a previously saved state that includes an expiring key.
  334. func TestStoreRecoverWithExpiration(t *testing.T) {
  335. s := newStore()
  336. s.Create("/foo", "", false, Permanent, 2, 1)
  337. s.Create("/foo/x", "bar", false, Permanent, 3, 1)
  338. s.Create("/foo/y", "baz", false, time.Now().Add(5 * time.Millisecond), 4, 1)
  339. b, err := s.Save()
  340. time.Sleep(10 * time.Millisecond)
  341. s2 := newStore()
  342. s2.Recovery(b)
  343. e, err := s.Get("/foo/x", false, false, 4, 1)
  344. assert.Nil(t, err, "")
  345. assert.Equal(t, e.Value, "bar", "")
  346. e, err = s.Get("/foo/y", false, false, 4, 1)
  347. assert.NotNil(t, err, "")
  348. assert.Nil(t, e, "")
  349. }
  350. // Performs a non-blocking select on an event channel.
  351. func nbselect(c <-chan *Event) *Event {
  352. select {
  353. case e := <-c:
  354. return e
  355. default:
  356. return nil
  357. }
  358. }