store_test.go 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984
  1. /*
  2. Copyright 2014 CoreOS, Inc.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package store
  14. import (
  15. "testing"
  16. "time"
  17. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/jonboulle/clockwork"
  18. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/stretchr/testify/assert"
  19. etcdErr "github.com/coreos/etcd/error"
  20. )
  21. // Ensure that the store can retrieve an existing value.
  22. func TestStoreGetValue(t *testing.T) {
  23. s := newStore()
  24. s.Create("/foo", false, "bar", false, Permanent)
  25. var eidx uint64 = 1
  26. e, err := s.Get("/foo", false, false)
  27. assert.Nil(t, err, "")
  28. assert.Equal(t, e.EtcdIndex, eidx, "")
  29. assert.Equal(t, e.Action, "get", "")
  30. assert.Equal(t, e.Node.Key, "/foo", "")
  31. assert.Equal(t, *e.Node.Value, "bar", "")
  32. }
  33. // Ensure that any TTL <= minExpireTime becomes Permanent
  34. func TestMinExpireTime(t *testing.T) {
  35. s := newStore()
  36. fc := clockwork.NewFakeClock()
  37. s.clock = fc
  38. // FakeClock starts at 0, so minExpireTime should be far in the future.. but just in case
  39. assert.True(t, minExpireTime.After(fc.Now()), "minExpireTime should be ahead of FakeClock!")
  40. s.Create("/foo", false, "Y", false, fc.Now().Add(3*time.Second))
  41. fc.Advance(5 * time.Second)
  42. // Ensure it hasn't expired
  43. s.DeleteExpiredKeys(fc.Now())
  44. var eidx uint64 = 1
  45. e, err := s.Get("/foo", true, false)
  46. assert.Nil(t, err, "")
  47. assert.Equal(t, e.EtcdIndex, eidx, "")
  48. assert.Equal(t, e.Action, "get", "")
  49. assert.Equal(t, e.Node.Key, "/foo", "")
  50. assert.Equal(t, e.Node.TTL, 0)
  51. }
  52. // Ensure that the store can recrusively retrieve a directory listing.
  53. // Note that hidden files should not be returned.
  54. func TestStoreGetDirectory(t *testing.T) {
  55. s := newStore()
  56. fc := newFakeClock()
  57. s.clock = fc
  58. s.Create("/foo", true, "", false, Permanent)
  59. s.Create("/foo/bar", false, "X", false, Permanent)
  60. s.Create("/foo/_hidden", false, "*", false, Permanent)
  61. s.Create("/foo/baz", true, "", false, Permanent)
  62. s.Create("/foo/baz/bat", false, "Y", false, Permanent)
  63. s.Create("/foo/baz/_hidden", false, "*", false, Permanent)
  64. s.Create("/foo/baz/ttl", false, "Y", false, fc.Now().Add(time.Second*3))
  65. var eidx uint64 = 7
  66. e, err := s.Get("/foo", true, false)
  67. assert.Nil(t, err, "")
  68. assert.Equal(t, e.EtcdIndex, eidx, "")
  69. assert.Equal(t, e.Action, "get", "")
  70. assert.Equal(t, e.Node.Key, "/foo", "")
  71. assert.Equal(t, len(e.Node.Nodes), 2, "")
  72. var bazNodes NodeExterns
  73. for _, node := range e.Node.Nodes {
  74. switch node.Key {
  75. case "/foo/bar":
  76. assert.Equal(t, *node.Value, "X", "")
  77. assert.Equal(t, node.Dir, false, "")
  78. case "/foo/baz":
  79. assert.Equal(t, node.Dir, true, "")
  80. assert.Equal(t, len(node.Nodes), 2, "")
  81. bazNodes = node.Nodes
  82. default:
  83. t.Errorf("key = %s, not matched", node.Key)
  84. }
  85. }
  86. for _, node := range bazNodes {
  87. switch node.Key {
  88. case "/foo/baz/bat":
  89. assert.Equal(t, *node.Value, "Y", "")
  90. assert.Equal(t, node.Dir, false, "")
  91. case "/foo/baz/ttl":
  92. assert.Equal(t, *node.Value, "Y", "")
  93. assert.Equal(t, node.Dir, false, "")
  94. assert.Equal(t, node.TTL, 3, "")
  95. default:
  96. t.Errorf("key = %s, not matched", node.Key)
  97. }
  98. }
  99. }
  100. // Ensure that the store can retrieve a directory in sorted order.
  101. func TestStoreGetSorted(t *testing.T) {
  102. s := newStore()
  103. s.Create("/foo", true, "", false, Permanent)
  104. s.Create("/foo/x", false, "0", false, Permanent)
  105. s.Create("/foo/z", false, "0", false, Permanent)
  106. s.Create("/foo/y", true, "", false, Permanent)
  107. s.Create("/foo/y/a", false, "0", false, Permanent)
  108. s.Create("/foo/y/b", false, "0", false, Permanent)
  109. var eidx uint64 = 6
  110. e, err := s.Get("/foo", true, true)
  111. assert.Nil(t, err, "")
  112. assert.Equal(t, e.EtcdIndex, eidx, "")
  113. var yNodes NodeExterns
  114. for _, node := range e.Node.Nodes {
  115. switch node.Key {
  116. case "/foo/x":
  117. case "/foo/y":
  118. yNodes = node.Nodes
  119. case "/foo/z":
  120. default:
  121. t.Errorf("key = %s, not matched", node.Key)
  122. }
  123. }
  124. for _, node := range yNodes {
  125. switch node.Key {
  126. case "/foo/y/a":
  127. case "/foo/y/b":
  128. default:
  129. t.Errorf("key = %s, not matched", node.Key)
  130. }
  131. }
  132. }
  133. func TestSet(t *testing.T) {
  134. s := newStore()
  135. // Set /foo=""
  136. var eidx uint64 = 1
  137. e, err := s.Set("/foo", false, "", Permanent)
  138. assert.Nil(t, err, "")
  139. assert.Equal(t, e.EtcdIndex, eidx, "")
  140. assert.Equal(t, e.Action, "set", "")
  141. assert.Equal(t, e.Node.Key, "/foo", "")
  142. assert.False(t, e.Node.Dir, "")
  143. assert.Equal(t, *e.Node.Value, "", "")
  144. assert.Nil(t, e.Node.Nodes, "")
  145. assert.Nil(t, e.Node.Expiration, "")
  146. assert.Equal(t, e.Node.TTL, 0, "")
  147. assert.Equal(t, e.Node.ModifiedIndex, uint64(1), "")
  148. // Set /foo="bar"
  149. eidx = 2
  150. e, err = s.Set("/foo", false, "bar", Permanent)
  151. assert.Nil(t, err, "")
  152. assert.Equal(t, e.EtcdIndex, eidx, "")
  153. assert.Equal(t, e.Action, "set", "")
  154. assert.Equal(t, e.Node.Key, "/foo", "")
  155. assert.False(t, e.Node.Dir, "")
  156. assert.Equal(t, *e.Node.Value, "bar", "")
  157. assert.Nil(t, e.Node.Nodes, "")
  158. assert.Nil(t, e.Node.Expiration, "")
  159. assert.Equal(t, e.Node.TTL, 0, "")
  160. assert.Equal(t, e.Node.ModifiedIndex, uint64(2), "")
  161. // check prevNode
  162. assert.NotNil(t, e.PrevNode, "")
  163. assert.Equal(t, e.PrevNode.Key, "/foo", "")
  164. assert.Equal(t, *e.PrevNode.Value, "", "")
  165. assert.Equal(t, e.PrevNode.ModifiedIndex, uint64(1), "")
  166. // Set /foo="baz" (for testing prevNode)
  167. eidx = 3
  168. e, err = s.Set("/foo", false, "baz", Permanent)
  169. assert.Nil(t, err, "")
  170. assert.Equal(t, e.EtcdIndex, eidx, "")
  171. assert.Equal(t, e.Action, "set", "")
  172. assert.Equal(t, e.Node.Key, "/foo", "")
  173. assert.False(t, e.Node.Dir, "")
  174. assert.Equal(t, *e.Node.Value, "baz", "")
  175. assert.Nil(t, e.Node.Nodes, "")
  176. assert.Nil(t, e.Node.Expiration, "")
  177. assert.Equal(t, e.Node.TTL, 0, "")
  178. assert.Equal(t, e.Node.ModifiedIndex, uint64(3), "")
  179. // check prevNode
  180. assert.NotNil(t, e.PrevNode, "")
  181. assert.Equal(t, e.PrevNode.Key, "/foo", "")
  182. assert.Equal(t, *e.PrevNode.Value, "bar", "")
  183. assert.Equal(t, e.PrevNode.ModifiedIndex, uint64(2), "")
  184. // Set /dir as a directory
  185. eidx = 4
  186. e, err = s.Set("/dir", true, "", Permanent)
  187. assert.Nil(t, err, "")
  188. assert.Equal(t, e.EtcdIndex, eidx, "")
  189. assert.Equal(t, e.Action, "set", "")
  190. assert.Equal(t, e.Node.Key, "/dir", "")
  191. assert.True(t, e.Node.Dir, "")
  192. assert.Nil(t, e.Node.Value)
  193. assert.Nil(t, e.Node.Nodes, "")
  194. assert.Nil(t, e.Node.Expiration, "")
  195. assert.Equal(t, e.Node.TTL, 0, "")
  196. assert.Equal(t, e.Node.ModifiedIndex, uint64(4), "")
  197. }
  198. // Ensure that the store can create a new key if it doesn't already exist.
  199. func TestStoreCreateValue(t *testing.T) {
  200. s := newStore()
  201. // Create /foo=bar
  202. var eidx uint64 = 1
  203. e, err := s.Create("/foo", false, "bar", false, Permanent)
  204. assert.Nil(t, err, "")
  205. assert.Equal(t, e.EtcdIndex, eidx, "")
  206. assert.Equal(t, e.Action, "create", "")
  207. assert.Equal(t, e.Node.Key, "/foo", "")
  208. assert.False(t, e.Node.Dir, "")
  209. assert.Equal(t, *e.Node.Value, "bar", "")
  210. assert.Nil(t, e.Node.Nodes, "")
  211. assert.Nil(t, e.Node.Expiration, "")
  212. assert.Equal(t, e.Node.TTL, 0, "")
  213. assert.Equal(t, e.Node.ModifiedIndex, uint64(1), "")
  214. // Create /empty=""
  215. eidx = 2
  216. e, err = s.Create("/empty", false, "", false, Permanent)
  217. assert.Nil(t, err, "")
  218. assert.Equal(t, e.EtcdIndex, eidx, "")
  219. assert.Equal(t, e.Action, "create", "")
  220. assert.Equal(t, e.Node.Key, "/empty", "")
  221. assert.False(t, e.Node.Dir, "")
  222. assert.Equal(t, *e.Node.Value, "", "")
  223. assert.Nil(t, e.Node.Nodes, "")
  224. assert.Nil(t, e.Node.Expiration, "")
  225. assert.Equal(t, e.Node.TTL, 0, "")
  226. assert.Equal(t, e.Node.ModifiedIndex, uint64(2), "")
  227. }
  228. // Ensure that the store can create a new directory if it doesn't already exist.
  229. func TestStoreCreateDirectory(t *testing.T) {
  230. s := newStore()
  231. var eidx uint64 = 1
  232. e, err := s.Create("/foo", true, "", false, Permanent)
  233. assert.Nil(t, err, "")
  234. assert.Equal(t, e.EtcdIndex, eidx, "")
  235. assert.Equal(t, e.Action, "create", "")
  236. assert.Equal(t, e.Node.Key, "/foo", "")
  237. assert.True(t, e.Node.Dir, "")
  238. }
  239. // Ensure that the store fails to create a key if it already exists.
  240. func TestStoreCreateFailsIfExists(t *testing.T) {
  241. s := newStore()
  242. // create /foo as dir
  243. s.Create("/foo", true, "", false, Permanent)
  244. // create /foo as dir again
  245. e, _err := s.Create("/foo", true, "", false, Permanent)
  246. err := _err.(*etcdErr.Error)
  247. assert.Equal(t, err.ErrorCode, etcdErr.EcodeNodeExist, "")
  248. assert.Equal(t, err.Message, "Key already exists", "")
  249. assert.Equal(t, err.Cause, "/foo", "")
  250. assert.Equal(t, err.Index, uint64(1), "")
  251. assert.Nil(t, e, 0, "")
  252. }
  253. // Ensure that the store can update a key if it already exists.
  254. func TestStoreUpdateValue(t *testing.T) {
  255. s := newStore()
  256. // create /foo=bar
  257. s.Create("/foo", false, "bar", false, Permanent)
  258. // update /foo="bzr"
  259. var eidx uint64 = 2
  260. e, err := s.Update("/foo", "baz", Permanent)
  261. assert.Nil(t, err, "")
  262. assert.Equal(t, e.EtcdIndex, eidx, "")
  263. assert.Equal(t, e.Action, "update", "")
  264. assert.Equal(t, e.Node.Key, "/foo", "")
  265. assert.False(t, e.Node.Dir, "")
  266. assert.Equal(t, *e.Node.Value, "baz", "")
  267. assert.Equal(t, e.Node.TTL, 0, "")
  268. assert.Equal(t, e.Node.ModifiedIndex, uint64(2), "")
  269. // check prevNode
  270. assert.Equal(t, e.PrevNode.Key, "/foo", "")
  271. assert.Equal(t, *e.PrevNode.Value, "bar", "")
  272. assert.Equal(t, e.PrevNode.TTL, 0, "")
  273. assert.Equal(t, e.PrevNode.ModifiedIndex, uint64(1), "")
  274. e, _ = s.Get("/foo", false, false)
  275. assert.Equal(t, *e.Node.Value, "baz", "")
  276. assert.Equal(t, e.EtcdIndex, eidx, "")
  277. // update /foo=""
  278. eidx = 3
  279. e, err = s.Update("/foo", "", Permanent)
  280. assert.Nil(t, err, "")
  281. assert.Equal(t, e.EtcdIndex, eidx, "")
  282. assert.Equal(t, e.Action, "update", "")
  283. assert.Equal(t, e.Node.Key, "/foo", "")
  284. assert.False(t, e.Node.Dir, "")
  285. assert.Equal(t, *e.Node.Value, "", "")
  286. assert.Equal(t, e.Node.TTL, 0, "")
  287. assert.Equal(t, e.Node.ModifiedIndex, uint64(3), "")
  288. // check prevNode
  289. assert.Equal(t, e.PrevNode.Key, "/foo", "")
  290. assert.Equal(t, *e.PrevNode.Value, "baz", "")
  291. assert.Equal(t, e.PrevNode.TTL, 0, "")
  292. assert.Equal(t, e.PrevNode.ModifiedIndex, uint64(2), "")
  293. e, _ = s.Get("/foo", false, false)
  294. assert.Equal(t, e.EtcdIndex, eidx, "")
  295. assert.Equal(t, *e.Node.Value, "", "")
  296. }
  297. // Ensure that the store cannot update a directory.
  298. func TestStoreUpdateFailsIfDirectory(t *testing.T) {
  299. s := newStore()
  300. s.Create("/foo", true, "", false, Permanent)
  301. e, _err := s.Update("/foo", "baz", Permanent)
  302. err := _err.(*etcdErr.Error)
  303. assert.Equal(t, err.ErrorCode, etcdErr.EcodeNotFile, "")
  304. assert.Equal(t, err.Message, "Not a file", "")
  305. assert.Equal(t, err.Cause, "/foo", "")
  306. assert.Nil(t, e, "")
  307. }
  308. // Ensure that the store can update the TTL on a value.
  309. func TestStoreUpdateValueTTL(t *testing.T) {
  310. s := newStore()
  311. fc := newFakeClock()
  312. s.clock = fc
  313. var eidx uint64 = 2
  314. s.Create("/foo", false, "bar", false, Permanent)
  315. _, err := s.Update("/foo", "baz", fc.Now().Add(500*time.Millisecond))
  316. e, _ := s.Get("/foo", false, false)
  317. assert.Equal(t, *e.Node.Value, "baz", "")
  318. assert.Equal(t, e.EtcdIndex, eidx, "")
  319. fc.Advance(600 * time.Millisecond)
  320. s.DeleteExpiredKeys(fc.Now())
  321. e, err = s.Get("/foo", false, false)
  322. assert.Nil(t, e, "")
  323. assert.Equal(t, err.(*etcdErr.Error).ErrorCode, etcdErr.EcodeKeyNotFound, "")
  324. }
  325. // Ensure that the store can update the TTL on a directory.
  326. func TestStoreUpdateDirTTL(t *testing.T) {
  327. s := newStore()
  328. fc := newFakeClock()
  329. s.clock = fc
  330. var eidx uint64 = 3
  331. s.Create("/foo", true, "", false, Permanent)
  332. s.Create("/foo/bar", false, "baz", false, Permanent)
  333. e, err := s.Update("/foo", "", fc.Now().Add(500*time.Millisecond))
  334. assert.Equal(t, e.Node.Dir, true, "")
  335. assert.Equal(t, e.EtcdIndex, eidx, "")
  336. e, _ = s.Get("/foo/bar", false, false)
  337. assert.Equal(t, *e.Node.Value, "baz", "")
  338. assert.Equal(t, e.EtcdIndex, eidx, "")
  339. fc.Advance(600 * time.Millisecond)
  340. s.DeleteExpiredKeys(fc.Now())
  341. e, err = s.Get("/foo/bar", false, false)
  342. assert.Nil(t, e, "")
  343. assert.Equal(t, err.(*etcdErr.Error).ErrorCode, etcdErr.EcodeKeyNotFound, "")
  344. }
  345. // Ensure that the store can delete a value.
  346. func TestStoreDeleteValue(t *testing.T) {
  347. s := newStore()
  348. var eidx uint64 = 2
  349. s.Create("/foo", false, "bar", false, Permanent)
  350. e, err := s.Delete("/foo", false, false)
  351. assert.Nil(t, err, "")
  352. assert.Equal(t, e.EtcdIndex, eidx, "")
  353. assert.Equal(t, e.Action, "delete", "")
  354. // check prevNode
  355. assert.NotNil(t, e.PrevNode, "")
  356. assert.Equal(t, e.PrevNode.Key, "/foo", "")
  357. assert.Equal(t, *e.PrevNode.Value, "bar", "")
  358. }
  359. // Ensure that the store can delete a directory if recursive is specified.
  360. func TestStoreDeleteDiretory(t *testing.T) {
  361. s := newStore()
  362. // create directory /foo
  363. var eidx uint64 = 2
  364. s.Create("/foo", true, "", false, Permanent)
  365. // delete /foo with dir = true and recursive = false
  366. // this should succeed, since the directory is empty
  367. e, err := s.Delete("/foo", true, false)
  368. assert.Nil(t, err, "")
  369. assert.Equal(t, e.EtcdIndex, eidx, "")
  370. assert.Equal(t, e.Action, "delete", "")
  371. // check prevNode
  372. assert.NotNil(t, e.PrevNode, "")
  373. assert.Equal(t, e.PrevNode.Key, "/foo", "")
  374. assert.Equal(t, e.PrevNode.Dir, true, "")
  375. // create directory /foo and directory /foo/bar
  376. s.Create("/foo/bar", true, "", false, Permanent)
  377. // delete /foo with dir = true and recursive = false
  378. // this should fail, since the directory is not empty
  379. _, err = s.Delete("/foo", true, false)
  380. assert.NotNil(t, err, "")
  381. // delete /foo with dir=false and recursive = true
  382. // this should succeed, since recursive implies dir=true
  383. // and recursively delete should be able to delete all
  384. // items under the given directory
  385. e, err = s.Delete("/foo", false, true)
  386. assert.Nil(t, err, "")
  387. assert.Equal(t, e.Action, "delete", "")
  388. }
  389. // Ensure that the store cannot delete a directory if both of recursive
  390. // and dir are not specified.
  391. func TestStoreDeleteDiretoryFailsIfNonRecursiveAndDir(t *testing.T) {
  392. s := newStore()
  393. s.Create("/foo", true, "", false, Permanent)
  394. e, _err := s.Delete("/foo", false, false)
  395. err := _err.(*etcdErr.Error)
  396. assert.Equal(t, err.ErrorCode, etcdErr.EcodeNotFile, "")
  397. assert.Equal(t, err.Message, "Not a file", "")
  398. assert.Nil(t, e, "")
  399. }
  400. func TestRootRdOnly(t *testing.T) {
  401. s := newStore()
  402. _, err := s.Set("/", true, "", Permanent)
  403. assert.NotNil(t, err, "")
  404. _, err = s.Delete("/", true, true)
  405. assert.NotNil(t, err, "")
  406. _, err = s.Create("/", true, "", false, Permanent)
  407. assert.NotNil(t, err, "")
  408. _, err = s.Update("/", "", Permanent)
  409. assert.NotNil(t, err, "")
  410. _, err = s.CompareAndSwap("/", "", 0, "", Permanent)
  411. assert.NotNil(t, err, "")
  412. }
  413. func TestStoreCompareAndDeletePrevValue(t *testing.T) {
  414. s := newStore()
  415. var eidx uint64 = 2
  416. s.Create("/foo", false, "bar", false, Permanent)
  417. e, err := s.CompareAndDelete("/foo", "bar", 0)
  418. assert.Nil(t, err, "")
  419. assert.Equal(t, e.EtcdIndex, eidx, "")
  420. assert.Equal(t, e.Action, "compareAndDelete", "")
  421. assert.Equal(t, e.Node.Key, "/foo", "")
  422. // check pervNode
  423. assert.NotNil(t, e.PrevNode, "")
  424. assert.Equal(t, e.PrevNode.Key, "/foo", "")
  425. assert.Equal(t, *e.PrevNode.Value, "bar", "")
  426. assert.Equal(t, e.PrevNode.ModifiedIndex, uint64(1), "")
  427. assert.Equal(t, e.PrevNode.CreatedIndex, uint64(1), "")
  428. }
  429. func TestStoreCompareAndDeletePrevValueFailsIfNotMatch(t *testing.T) {
  430. s := newStore()
  431. var eidx uint64 = 1
  432. s.Create("/foo", false, "bar", false, Permanent)
  433. e, _err := s.CompareAndDelete("/foo", "baz", 0)
  434. err := _err.(*etcdErr.Error)
  435. assert.Equal(t, err.ErrorCode, etcdErr.EcodeTestFailed, "")
  436. assert.Equal(t, err.Message, "Compare failed", "")
  437. assert.Nil(t, e, "")
  438. e, _ = s.Get("/foo", false, false)
  439. assert.Equal(t, e.EtcdIndex, eidx, "")
  440. assert.Equal(t, *e.Node.Value, "bar", "")
  441. }
  442. func TestStoreCompareAndDeletePrevIndex(t *testing.T) {
  443. s := newStore()
  444. var eidx uint64 = 2
  445. s.Create("/foo", false, "bar", false, Permanent)
  446. e, err := s.CompareAndDelete("/foo", "", 1)
  447. assert.Nil(t, err, "")
  448. assert.Equal(t, e.EtcdIndex, eidx, "")
  449. assert.Equal(t, e.Action, "compareAndDelete", "")
  450. // check pervNode
  451. assert.NotNil(t, e.PrevNode, "")
  452. assert.Equal(t, e.PrevNode.Key, "/foo", "")
  453. assert.Equal(t, *e.PrevNode.Value, "bar", "")
  454. assert.Equal(t, e.PrevNode.ModifiedIndex, uint64(1), "")
  455. assert.Equal(t, e.PrevNode.CreatedIndex, uint64(1), "")
  456. }
  457. func TestStoreCompareAndDeletePrevIndexFailsIfNotMatch(t *testing.T) {
  458. s := newStore()
  459. var eidx uint64 = 1
  460. s.Create("/foo", false, "bar", false, Permanent)
  461. e, _err := s.CompareAndDelete("/foo", "", 100)
  462. assert.NotNil(t, _err, "")
  463. err := _err.(*etcdErr.Error)
  464. assert.Equal(t, err.ErrorCode, etcdErr.EcodeTestFailed, "")
  465. assert.Equal(t, err.Message, "Compare failed", "")
  466. assert.Nil(t, e, "")
  467. e, _ = s.Get("/foo", false, false)
  468. assert.Equal(t, e.EtcdIndex, eidx, "")
  469. assert.Equal(t, *e.Node.Value, "bar", "")
  470. }
  471. // Ensure that the store cannot delete a directory.
  472. func TestStoreCompareAndDeleteDiretoryFail(t *testing.T) {
  473. s := newStore()
  474. s.Create("/foo", true, "", false, Permanent)
  475. _, _err := s.CompareAndDelete("/foo", "", 0)
  476. assert.NotNil(t, _err, "")
  477. err := _err.(*etcdErr.Error)
  478. assert.Equal(t, err.ErrorCode, etcdErr.EcodeNotFile, "")
  479. }
  480. // Ensure that the store can conditionally update a key if it has a previous value.
  481. func TestStoreCompareAndSwapPrevValue(t *testing.T) {
  482. s := newStore()
  483. var eidx uint64 = 2
  484. s.Create("/foo", false, "bar", false, Permanent)
  485. e, err := s.CompareAndSwap("/foo", "bar", 0, "baz", Permanent)
  486. assert.Nil(t, err, "")
  487. assert.Equal(t, e.EtcdIndex, eidx, "")
  488. assert.Equal(t, e.Action, "compareAndSwap", "")
  489. assert.Equal(t, *e.Node.Value, "baz", "")
  490. // check pervNode
  491. assert.NotNil(t, e.PrevNode, "")
  492. assert.Equal(t, e.PrevNode.Key, "/foo", "")
  493. assert.Equal(t, *e.PrevNode.Value, "bar", "")
  494. assert.Equal(t, e.PrevNode.ModifiedIndex, uint64(1), "")
  495. assert.Equal(t, e.PrevNode.CreatedIndex, uint64(1), "")
  496. e, _ = s.Get("/foo", false, false)
  497. assert.Equal(t, *e.Node.Value, "baz", "")
  498. }
  499. // Ensure that the store cannot conditionally update a key if it has the wrong previous value.
  500. func TestStoreCompareAndSwapPrevValueFailsIfNotMatch(t *testing.T) {
  501. s := newStore()
  502. var eidx uint64 = 1
  503. s.Create("/foo", false, "bar", false, Permanent)
  504. e, _err := s.CompareAndSwap("/foo", "wrong_value", 0, "baz", Permanent)
  505. err := _err.(*etcdErr.Error)
  506. assert.Equal(t, err.ErrorCode, etcdErr.EcodeTestFailed, "")
  507. assert.Equal(t, err.Message, "Compare failed", "")
  508. assert.Nil(t, e, "")
  509. e, _ = s.Get("/foo", false, false)
  510. assert.Equal(t, *e.Node.Value, "bar", "")
  511. assert.Equal(t, e.EtcdIndex, eidx, "")
  512. }
  513. // Ensure that the store can conditionally update a key if it has a previous index.
  514. func TestStoreCompareAndSwapPrevIndex(t *testing.T) {
  515. s := newStore()
  516. var eidx uint64 = 2
  517. s.Create("/foo", false, "bar", false, Permanent)
  518. e, err := s.CompareAndSwap("/foo", "", 1, "baz", Permanent)
  519. assert.Nil(t, err, "")
  520. assert.Equal(t, e.EtcdIndex, eidx, "")
  521. assert.Equal(t, e.Action, "compareAndSwap", "")
  522. assert.Equal(t, *e.Node.Value, "baz", "")
  523. // check prevNode
  524. assert.NotNil(t, e.PrevNode, "")
  525. assert.Equal(t, e.PrevNode.Key, "/foo", "")
  526. assert.Equal(t, *e.PrevNode.Value, "bar", "")
  527. assert.Equal(t, e.PrevNode.ModifiedIndex, uint64(1), "")
  528. assert.Equal(t, e.PrevNode.CreatedIndex, uint64(1), "")
  529. e, _ = s.Get("/foo", false, false)
  530. assert.Equal(t, *e.Node.Value, "baz", "")
  531. assert.Equal(t, e.EtcdIndex, eidx, "")
  532. }
  533. // Ensure that the store cannot conditionally update a key if it has the wrong previous index.
  534. func TestStoreCompareAndSwapPrevIndexFailsIfNotMatch(t *testing.T) {
  535. s := newStore()
  536. var eidx uint64 = 1
  537. s.Create("/foo", false, "bar", false, Permanent)
  538. e, _err := s.CompareAndSwap("/foo", "", 100, "baz", Permanent)
  539. err := _err.(*etcdErr.Error)
  540. assert.Equal(t, err.ErrorCode, etcdErr.EcodeTestFailed, "")
  541. assert.Equal(t, err.Message, "Compare failed", "")
  542. assert.Nil(t, e, "")
  543. e, _ = s.Get("/foo", false, false)
  544. assert.Equal(t, e.EtcdIndex, eidx, "")
  545. assert.Equal(t, *e.Node.Value, "bar", "")
  546. }
  547. // Ensure that the store can watch for key creation.
  548. func TestStoreWatchCreate(t *testing.T) {
  549. s := newStore()
  550. var eidx uint64 = 0
  551. w, _ := s.Watch("/foo", false, false, 0)
  552. c := w.EventChan()
  553. assert.Equal(t, w.StartIndex(), eidx, "")
  554. s.Create("/foo", false, "bar", false, Permanent)
  555. eidx = 1
  556. e := nbselect(c)
  557. assert.Equal(t, e.EtcdIndex, eidx, "")
  558. assert.Equal(t, e.Action, "create", "")
  559. assert.Equal(t, e.Node.Key, "/foo", "")
  560. e = nbselect(c)
  561. assert.Nil(t, e, "")
  562. }
  563. // Ensure that the store can watch for recursive key creation.
  564. func TestStoreWatchRecursiveCreate(t *testing.T) {
  565. s := newStore()
  566. var eidx uint64 = 0
  567. w, _ := s.Watch("/foo", true, false, 0)
  568. assert.Equal(t, w.StartIndex(), eidx, "")
  569. eidx = 1
  570. s.Create("/foo/bar", false, "baz", false, Permanent)
  571. e := nbselect(w.EventChan())
  572. assert.Equal(t, e.EtcdIndex, eidx, "")
  573. assert.Equal(t, e.Action, "create", "")
  574. assert.Equal(t, e.Node.Key, "/foo/bar", "")
  575. }
  576. // Ensure that the store can watch for key updates.
  577. func TestStoreWatchUpdate(t *testing.T) {
  578. s := newStore()
  579. var eidx uint64 = 1
  580. s.Create("/foo", false, "bar", false, Permanent)
  581. w, _ := s.Watch("/foo", false, false, 0)
  582. assert.Equal(t, w.StartIndex(), eidx, "")
  583. eidx = 2
  584. s.Update("/foo", "baz", Permanent)
  585. e := nbselect(w.EventChan())
  586. assert.Equal(t, e.EtcdIndex, eidx, "")
  587. assert.Equal(t, e.Action, "update", "")
  588. assert.Equal(t, e.Node.Key, "/foo", "")
  589. }
  590. // Ensure that the store can watch for recursive key updates.
  591. func TestStoreWatchRecursiveUpdate(t *testing.T) {
  592. s := newStore()
  593. var eidx uint64 = 1
  594. s.Create("/foo/bar", false, "baz", false, Permanent)
  595. w, _ := s.Watch("/foo", true, false, 0)
  596. assert.Equal(t, w.StartIndex(), eidx, "")
  597. eidx = 2
  598. s.Update("/foo/bar", "baz", Permanent)
  599. e := nbselect(w.EventChan())
  600. assert.Equal(t, e.EtcdIndex, eidx, "")
  601. assert.Equal(t, e.Action, "update", "")
  602. assert.Equal(t, e.Node.Key, "/foo/bar", "")
  603. }
  604. // Ensure that the store can watch for key deletions.
  605. func TestStoreWatchDelete(t *testing.T) {
  606. s := newStore()
  607. var eidx uint64 = 1
  608. s.Create("/foo", false, "bar", false, Permanent)
  609. w, _ := s.Watch("/foo", false, false, 0)
  610. assert.Equal(t, w.StartIndex(), eidx, "")
  611. eidx = 2
  612. s.Delete("/foo", false, false)
  613. e := nbselect(w.EventChan())
  614. assert.Equal(t, e.EtcdIndex, eidx, "")
  615. assert.Equal(t, e.Action, "delete", "")
  616. assert.Equal(t, e.Node.Key, "/foo", "")
  617. }
  618. // Ensure that the store can watch for recursive key deletions.
  619. func TestStoreWatchRecursiveDelete(t *testing.T) {
  620. s := newStore()
  621. var eidx uint64 = 1
  622. s.Create("/foo/bar", false, "baz", false, Permanent)
  623. w, _ := s.Watch("/foo", true, false, 0)
  624. assert.Equal(t, w.StartIndex(), eidx, "")
  625. eidx = 2
  626. s.Delete("/foo/bar", false, false)
  627. e := nbselect(w.EventChan())
  628. assert.Equal(t, e.EtcdIndex, eidx, "")
  629. assert.Equal(t, e.Action, "delete", "")
  630. assert.Equal(t, e.Node.Key, "/foo/bar", "")
  631. }
  632. // Ensure that the store can watch for CAS updates.
  633. func TestStoreWatchCompareAndSwap(t *testing.T) {
  634. s := newStore()
  635. var eidx uint64 = 1
  636. s.Create("/foo", false, "bar", false, Permanent)
  637. w, _ := s.Watch("/foo", false, false, 0)
  638. assert.Equal(t, w.StartIndex(), eidx, "")
  639. eidx = 2
  640. s.CompareAndSwap("/foo", "bar", 0, "baz", Permanent)
  641. e := nbselect(w.EventChan())
  642. assert.Equal(t, e.EtcdIndex, eidx, "")
  643. assert.Equal(t, e.Action, "compareAndSwap", "")
  644. assert.Equal(t, e.Node.Key, "/foo", "")
  645. }
  646. // Ensure that the store can watch for recursive CAS updates.
  647. func TestStoreWatchRecursiveCompareAndSwap(t *testing.T) {
  648. s := newStore()
  649. var eidx uint64 = 1
  650. s.Create("/foo/bar", false, "baz", false, Permanent)
  651. w, _ := s.Watch("/foo", true, false, 0)
  652. assert.Equal(t, w.StartIndex(), eidx, "")
  653. eidx = 2
  654. s.CompareAndSwap("/foo/bar", "baz", 0, "bat", Permanent)
  655. e := nbselect(w.EventChan())
  656. assert.Equal(t, e.EtcdIndex, eidx, "")
  657. assert.Equal(t, e.Action, "compareAndSwap", "")
  658. assert.Equal(t, e.Node.Key, "/foo/bar", "")
  659. }
  660. // Ensure that the store can watch for key expiration.
  661. func TestStoreWatchExpire(t *testing.T) {
  662. s := newStore()
  663. fc := newFakeClock()
  664. s.clock = fc
  665. var eidx uint64 = 2
  666. s.Create("/foo", false, "bar", false, fc.Now().Add(500*time.Millisecond))
  667. s.Create("/foofoo", false, "barbarbar", false, fc.Now().Add(500*time.Millisecond))
  668. w, _ := s.Watch("/", true, false, 0)
  669. assert.Equal(t, w.StartIndex(), eidx, "")
  670. c := w.EventChan()
  671. e := nbselect(c)
  672. assert.Nil(t, e, "")
  673. fc.Advance(600 * time.Millisecond)
  674. s.DeleteExpiredKeys(fc.Now())
  675. eidx = 3
  676. e = nbselect(c)
  677. assert.Equal(t, e.EtcdIndex, eidx, "")
  678. assert.Equal(t, e.Action, "expire", "")
  679. assert.Equal(t, e.Node.Key, "/foo", "")
  680. w, _ = s.Watch("/", true, false, 4)
  681. eidx = 4
  682. assert.Equal(t, w.StartIndex(), eidx, "")
  683. e = nbselect(w.EventChan())
  684. assert.Equal(t, e.EtcdIndex, eidx, "")
  685. assert.Equal(t, e.Action, "expire", "")
  686. assert.Equal(t, e.Node.Key, "/foofoo", "")
  687. }
  688. // Ensure that the store can watch in streaming mode.
  689. func TestStoreWatchStream(t *testing.T) {
  690. s := newStore()
  691. var eidx uint64 = 1
  692. w, _ := s.Watch("/foo", false, true, 0)
  693. // first modification
  694. s.Create("/foo", false, "bar", false, Permanent)
  695. e := nbselect(w.EventChan())
  696. assert.Equal(t, e.EtcdIndex, eidx, "")
  697. assert.Equal(t, e.Action, "create", "")
  698. assert.Equal(t, e.Node.Key, "/foo", "")
  699. assert.Equal(t, *e.Node.Value, "bar", "")
  700. e = nbselect(w.EventChan())
  701. assert.Nil(t, e, "")
  702. // second modification
  703. eidx = 2
  704. s.Update("/foo", "baz", Permanent)
  705. e = nbselect(w.EventChan())
  706. assert.Equal(t, e.EtcdIndex, eidx, "")
  707. assert.Equal(t, e.Action, "update", "")
  708. assert.Equal(t, e.Node.Key, "/foo", "")
  709. assert.Equal(t, *e.Node.Value, "baz", "")
  710. e = nbselect(w.EventChan())
  711. assert.Nil(t, e, "")
  712. }
  713. // Ensure that the store can recover from a previously saved state.
  714. func TestStoreRecover(t *testing.T) {
  715. s := newStore()
  716. var eidx uint64 = 3
  717. s.Create("/foo", true, "", false, Permanent)
  718. s.Create("/foo/x", false, "bar", false, Permanent)
  719. s.Create("/foo/y", false, "baz", false, Permanent)
  720. b, err := s.Save()
  721. s2 := newStore()
  722. s2.Recovery(b)
  723. e, err := s.Get("/foo/x", false, false)
  724. assert.Equal(t, e.EtcdIndex, eidx, "")
  725. assert.Nil(t, err, "")
  726. assert.Equal(t, *e.Node.Value, "bar", "")
  727. e, err = s.Get("/foo/y", false, false)
  728. assert.Equal(t, e.EtcdIndex, eidx, "")
  729. assert.Nil(t, err, "")
  730. assert.Equal(t, *e.Node.Value, "baz", "")
  731. }
  732. // Ensure that the store can recover from a previously saved state that includes an expiring key.
  733. func TestStoreRecoverWithExpiration(t *testing.T) {
  734. s := newStore()
  735. s.clock = newFakeClock()
  736. fc := newFakeClock()
  737. var eidx uint64 = 4
  738. s.Create("/foo", true, "", false, Permanent)
  739. s.Create("/foo/x", false, "bar", false, Permanent)
  740. s.Create("/foo/y", false, "baz", false, fc.Now().Add(5*time.Millisecond))
  741. b, err := s.Save()
  742. time.Sleep(10 * time.Millisecond)
  743. s2 := newStore()
  744. s2.clock = fc
  745. s2.Recovery(b)
  746. fc.Advance(600 * time.Millisecond)
  747. s.DeleteExpiredKeys(fc.Now())
  748. e, err := s.Get("/foo/x", false, false)
  749. assert.Nil(t, err, "")
  750. assert.Equal(t, e.EtcdIndex, eidx, "")
  751. assert.Equal(t, *e.Node.Value, "bar", "")
  752. e, err = s.Get("/foo/y", false, false)
  753. assert.NotNil(t, err, "")
  754. assert.Nil(t, e, "")
  755. }
  756. // Ensure that the store can watch for hidden keys as long as it's an exact path match.
  757. func TestStoreWatchCreateWithHiddenKey(t *testing.T) {
  758. s := newStore()
  759. var eidx uint64 = 1
  760. w, _ := s.Watch("/_foo", false, false, 0)
  761. s.Create("/_foo", false, "bar", false, Permanent)
  762. e := nbselect(w.EventChan())
  763. assert.Equal(t, e.EtcdIndex, eidx, "")
  764. assert.Equal(t, e.Action, "create", "")
  765. assert.Equal(t, e.Node.Key, "/_foo", "")
  766. e = nbselect(w.EventChan())
  767. assert.Nil(t, e, "")
  768. }
  769. // Ensure that the store doesn't see hidden key creates without an exact path match in recursive mode.
  770. func TestStoreWatchRecursiveCreateWithHiddenKey(t *testing.T) {
  771. s := newStore()
  772. w, _ := s.Watch("/foo", true, false, 0)
  773. s.Create("/foo/_bar", false, "baz", false, Permanent)
  774. e := nbselect(w.EventChan())
  775. assert.Nil(t, e, "")
  776. w, _ = s.Watch("/foo", true, false, 0)
  777. s.Create("/foo/_baz", true, "", false, Permanent)
  778. e = nbselect(w.EventChan())
  779. assert.Nil(t, e, "")
  780. s.Create("/foo/_baz/quux", false, "quux", false, Permanent)
  781. e = nbselect(w.EventChan())
  782. assert.Nil(t, e, "")
  783. }
  784. // Ensure that the store doesn't see hidden key updates.
  785. func TestStoreWatchUpdateWithHiddenKey(t *testing.T) {
  786. s := newStore()
  787. s.Create("/_foo", false, "bar", false, Permanent)
  788. w, _ := s.Watch("/_foo", false, false, 0)
  789. s.Update("/_foo", "baz", Permanent)
  790. e := nbselect(w.EventChan())
  791. assert.Equal(t, e.Action, "update", "")
  792. assert.Equal(t, e.Node.Key, "/_foo", "")
  793. e = nbselect(w.EventChan())
  794. assert.Nil(t, e, "")
  795. }
  796. // Ensure that the store doesn't see hidden key updates without an exact path match in recursive mode.
  797. func TestStoreWatchRecursiveUpdateWithHiddenKey(t *testing.T) {
  798. s := newStore()
  799. s.Create("/foo/_bar", false, "baz", false, Permanent)
  800. w, _ := s.Watch("/foo", true, false, 0)
  801. s.Update("/foo/_bar", "baz", Permanent)
  802. e := nbselect(w.EventChan())
  803. assert.Nil(t, e, "")
  804. }
  805. // Ensure that the store can watch for key deletions.
  806. func TestStoreWatchDeleteWithHiddenKey(t *testing.T) {
  807. s := newStore()
  808. var eidx uint64 = 2
  809. s.Create("/_foo", false, "bar", false, Permanent)
  810. w, _ := s.Watch("/_foo", false, false, 0)
  811. s.Delete("/_foo", false, false)
  812. e := nbselect(w.EventChan())
  813. assert.Equal(t, e.EtcdIndex, eidx, "")
  814. assert.Equal(t, e.Action, "delete", "")
  815. assert.Equal(t, e.Node.Key, "/_foo", "")
  816. e = nbselect(w.EventChan())
  817. assert.Nil(t, e, "")
  818. }
  819. // Ensure that the store doesn't see hidden key deletes without an exact path match in recursive mode.
  820. func TestStoreWatchRecursiveDeleteWithHiddenKey(t *testing.T) {
  821. s := newStore()
  822. s.Create("/foo/_bar", false, "baz", false, Permanent)
  823. w, _ := s.Watch("/foo", true, false, 0)
  824. s.Delete("/foo/_bar", false, false)
  825. e := nbselect(w.EventChan())
  826. assert.Nil(t, e, "")
  827. }
  828. // Ensure that the store doesn't see expirations of hidden keys.
  829. func TestStoreWatchExpireWithHiddenKey(t *testing.T) {
  830. s := newStore()
  831. fc := newFakeClock()
  832. s.clock = fc
  833. s.Create("/_foo", false, "bar", false, fc.Now().Add(500*time.Millisecond))
  834. s.Create("/foofoo", false, "barbarbar", false, fc.Now().Add(1000*time.Millisecond))
  835. w, _ := s.Watch("/", true, false, 0)
  836. c := w.EventChan()
  837. e := nbselect(c)
  838. assert.Nil(t, e, "")
  839. fc.Advance(600 * time.Millisecond)
  840. s.DeleteExpiredKeys(fc.Now())
  841. e = nbselect(c)
  842. assert.Nil(t, e, "")
  843. fc.Advance(600 * time.Millisecond)
  844. s.DeleteExpiredKeys(fc.Now())
  845. e = nbselect(c)
  846. assert.Equal(t, e.Action, "expire", "")
  847. assert.Equal(t, e.Node.Key, "/foofoo", "")
  848. }
  849. // Ensure that the store does see hidden key creates if watching deeper than a hidden key in recursive mode.
  850. func TestStoreWatchRecursiveCreateDeeperThanHiddenKey(t *testing.T) {
  851. s := newStore()
  852. var eidx uint64 = 1
  853. w, _ := s.Watch("/_foo/bar", true, false, 0)
  854. s.Create("/_foo/bar/baz", false, "baz", false, Permanent)
  855. e := nbselect(w.EventChan())
  856. assert.NotNil(t, e, "")
  857. assert.Equal(t, e.EtcdIndex, eidx, "")
  858. assert.Equal(t, e.Action, "create", "")
  859. assert.Equal(t, e.Node.Key, "/_foo/bar/baz", "")
  860. }
  861. // Ensure that slow consumers are handled properly.
  862. //
  863. // Since Watcher.EventChan() has a buffer of size 1 we can only queue 1
  864. // event per watcher. If the consumer cannot consume the event on time and
  865. // another event arrives, the channel is closed and event is discarded.
  866. // This test ensures that after closing the channel, the store can continue
  867. // to operate correctly.
  868. func TestStoreWatchSlowConsumer(t *testing.T) {
  869. s := newStore()
  870. s.Watch("/foo", true, true, 0) // stream must be true
  871. s.Set("/foo", false, "1", Permanent) // ok
  872. s.Set("/foo", false, "2", Permanent) // ok
  873. s.Set("/foo", false, "3", Permanent) // must not panic
  874. }
  875. // Performs a non-blocking select on an event channel.
  876. func nbselect(c <-chan *Event) *Event {
  877. select {
  878. case e := <-c:
  879. return e
  880. default:
  881. return nil
  882. }
  883. }
  884. // newFakeClock creates a new FakeClock that has been advanced to at least minExpireTime
  885. func newFakeClock() clockwork.FakeClock {
  886. fc := clockwork.NewFakeClock()
  887. for minExpireTime.After(fc.Now()) {
  888. fc.Advance((0x1 << 62) * time.Nanosecond)
  889. }
  890. return fc
  891. }