store_test.go 28 KB

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