mod_lock_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. package lock
  2. import (
  3. "fmt"
  4. "testing"
  5. "time"
  6. "github.com/coreos/etcd/server"
  7. "github.com/coreos/etcd/tests"
  8. "github.com/coreos/etcd/third_party/github.com/stretchr/testify/assert"
  9. )
  10. // Ensure that a lock can be acquired and released.
  11. func TestModLockAcquireAndRelease(t *testing.T) {
  12. tests.RunServer(func(s *server.Server) {
  13. // Acquire lock.
  14. body, status, err := testAcquireLock(s, "foo", "", 10)
  15. assert.NoError(t, err)
  16. assert.Equal(t, status, 200)
  17. assert.Equal(t, body, "2")
  18. // Check that we have the lock.
  19. body, status, err = testGetLockIndex(s, "foo")
  20. assert.NoError(t, err)
  21. assert.Equal(t, status, 200)
  22. assert.Equal(t, body, "2")
  23. // Release lock.
  24. body, status, err = testReleaseLock(s, "foo", "2", "")
  25. assert.NoError(t, err)
  26. assert.Equal(t, status, 200)
  27. assert.Equal(t, body, "")
  28. // Check that we have the lock.
  29. body, status, err = testGetLockIndex(s, "foo")
  30. assert.NoError(t, err)
  31. assert.Equal(t, status, 200)
  32. assert.Equal(t, body, "")
  33. })
  34. }
  35. // Ensure that a lock can be acquired and another process is blocked until released.
  36. func TestModLockBlockUntilAcquire(t *testing.T) {
  37. tests.RunServer(func(s *server.Server) {
  38. c := make(chan bool)
  39. // Acquire lock #1.
  40. go func() {
  41. body, status, err := testAcquireLock(s, "foo", "", 10)
  42. assert.NoError(t, err)
  43. assert.Equal(t, status, 200)
  44. assert.Equal(t, body, "2")
  45. c <- true
  46. }()
  47. <-c
  48. // Acquire lock #2.
  49. waiting := true
  50. go func() {
  51. c <- true
  52. body, status, err := testAcquireLock(s, "foo", "", 10)
  53. assert.NoError(t, err)
  54. assert.Equal(t, status, 200)
  55. assert.Equal(t, body, "4")
  56. waiting = false
  57. }()
  58. <-c
  59. time.Sleep(1 * time.Second)
  60. // Check that we have the lock #1.
  61. body, status, err := testGetLockIndex(s, "foo")
  62. assert.NoError(t, err)
  63. assert.Equal(t, status, 200)
  64. assert.Equal(t, body, "2")
  65. // Check that we are still waiting for lock #2.
  66. assert.Equal(t, waiting, true)
  67. // Release lock #1.
  68. _, status, err = testReleaseLock(s, "foo", "2", "")
  69. assert.NoError(t, err)
  70. assert.Equal(t, status, 200)
  71. // Check that we have lock #2.
  72. body, status, err = testGetLockIndex(s, "foo")
  73. assert.NoError(t, err)
  74. assert.Equal(t, status, 200)
  75. assert.Equal(t, body, "4")
  76. // Release lock #2.
  77. _, status, err = testReleaseLock(s, "foo", "4", "")
  78. assert.NoError(t, err)
  79. assert.Equal(t, status, 200)
  80. // Check that we have no lock.
  81. body, status, err = testGetLockIndex(s, "foo")
  82. assert.NoError(t, err)
  83. assert.Equal(t, status, 200)
  84. assert.Equal(t, body, "")
  85. })
  86. }
  87. // Ensure that a lock will be released after the TTL.
  88. func TestModLockExpireAndRelease(t *testing.T) {
  89. tests.RunServer(func(s *server.Server) {
  90. c := make(chan bool)
  91. // Acquire lock #1.
  92. go func() {
  93. body, status, err := testAcquireLock(s, "foo", "", 2)
  94. assert.NoError(t, err)
  95. assert.Equal(t, status, 200)
  96. assert.Equal(t, body, "2")
  97. c <- true
  98. }()
  99. <-c
  100. // Acquire lock #2.
  101. go func() {
  102. c <- true
  103. body, status, err := testAcquireLock(s, "foo", "", 10)
  104. assert.NoError(t, err)
  105. assert.Equal(t, status, 200)
  106. assert.Equal(t, body, "4")
  107. }()
  108. <-c
  109. time.Sleep(1 * time.Second)
  110. // Check that we have the lock #1.
  111. body, status, err := testGetLockIndex(s, "foo")
  112. assert.NoError(t, err)
  113. assert.Equal(t, status, 200)
  114. assert.Equal(t, body, "2")
  115. // Wait for lock #1 TTL.
  116. time.Sleep(2 * time.Second)
  117. // Check that we have lock #2.
  118. body, status, err = testGetLockIndex(s, "foo")
  119. assert.NoError(t, err)
  120. assert.Equal(t, status, 200)
  121. assert.Equal(t, body, "4")
  122. })
  123. }
  124. // Ensure that a lock can be renewed.
  125. func TestModLockRenew(t *testing.T) {
  126. tests.RunServer(func(s *server.Server) {
  127. // Acquire lock.
  128. body, status, err := testAcquireLock(s, "foo", "", 3)
  129. assert.NoError(t, err)
  130. assert.Equal(t, status, 200)
  131. assert.Equal(t, body, "2")
  132. time.Sleep(2 * time.Second)
  133. // Check that we have the lock.
  134. body, status, err = testGetLockIndex(s, "foo")
  135. assert.NoError(t, err)
  136. assert.Equal(t, status, 200)
  137. assert.Equal(t, body, "2")
  138. // Renew lock.
  139. body, status, err = testRenewLock(s, "foo", "2", "", 3)
  140. assert.NoError(t, err)
  141. assert.Equal(t, status, 200)
  142. assert.Equal(t, body, "")
  143. time.Sleep(2 * time.Second)
  144. // Check that we still have the lock.
  145. body, status, err = testGetLockIndex(s, "foo")
  146. assert.NoError(t, err)
  147. assert.Equal(t, status, 200)
  148. assert.Equal(t, body, "2")
  149. time.Sleep(2 * time.Second)
  150. // Check that lock was released.
  151. body, status, err = testGetLockIndex(s, "foo")
  152. assert.NoError(t, err)
  153. assert.Equal(t, status, 200)
  154. assert.Equal(t, body, "")
  155. })
  156. }
  157. // Ensure that a lock can be acquired with a value and released by value.
  158. func TestModLockAcquireAndReleaseByValue(t *testing.T) {
  159. tests.RunServer(func(s *server.Server) {
  160. // Acquire lock.
  161. body, status, err := testAcquireLock(s, "foo", "XXX", 10)
  162. assert.NoError(t, err)
  163. assert.Equal(t, status, 200)
  164. assert.Equal(t, body, "2")
  165. // Check that we have the lock.
  166. body, status, err = testGetLockValue(s, "foo")
  167. assert.NoError(t, err)
  168. assert.Equal(t, status, 200)
  169. assert.Equal(t, body, "XXX")
  170. // Release lock.
  171. body, status, err = testReleaseLock(s, "foo", "", "XXX")
  172. assert.NoError(t, err)
  173. assert.Equal(t, status, 200)
  174. assert.Equal(t, body, "")
  175. // Check that we released the lock.
  176. body, status, err = testGetLockValue(s, "foo")
  177. assert.NoError(t, err)
  178. assert.Equal(t, status, 200)
  179. assert.Equal(t, body, "")
  180. })
  181. }
  182. // Ensure that a lock honours the timeout option
  183. func TestModLockAcquireTimeout(t *testing.T) {
  184. tests.RunServer(func(s *server.Server) {
  185. c := make(chan bool)
  186. // Acquire lock #1.
  187. go func() {
  188. body, status, err := testAcquireLock(s, "foo", "first", 10)
  189. assert.NoError(t, err)
  190. assert.Equal(t, status, 200)
  191. assert.Equal(t, body, "2")
  192. c <- true
  193. }()
  194. <-c
  195. // Attempt to acquire lock #2, timing out after 1s.
  196. waiting := true
  197. go func() {
  198. c <- true
  199. _, status, err := testAcquireLockWithTimeout(s, "foo", "second", 10, 1)
  200. assert.NoError(t, err)
  201. assert.Equal(t, status, 500)
  202. waiting = false
  203. }()
  204. <-c
  205. time.Sleep(5 * time.Second)
  206. // Check that we have the lock #1.
  207. body, status, err := testGetLockIndex(s, "foo")
  208. assert.NoError(t, err)
  209. assert.Equal(t, status, 200)
  210. assert.Equal(t, body, "2")
  211. // Check that we are not still waiting for lock #2.
  212. assert.Equal(t, waiting, false)
  213. // Release lock #1.
  214. _, status, err = testReleaseLock(s, "foo", "2", "")
  215. assert.NoError(t, err)
  216. assert.Equal(t, status, 200)
  217. // Check that we have no lock.
  218. body, status, err = testGetLockIndex(s, "foo")
  219. assert.NoError(t, err)
  220. assert.Equal(t, status, 200)
  221. })
  222. }
  223. // Ensure that a lock succeeds when timeout=0 (nowait)
  224. func TestModLockAcquireNoWait(t *testing.T) {
  225. tests.RunServer(func(s *server.Server) {
  226. c := make(chan bool)
  227. // Acquire lock with no waiting.
  228. go func() {
  229. body, status, err := testAcquireLockWithTimeout(s, "foo", "first", 10, 0)
  230. assert.NoError(t, err)
  231. assert.Equal(t, status, 200)
  232. assert.Equal(t, body, "2")
  233. c <- true
  234. }()
  235. <-c
  236. time.Sleep(1 * time.Second)
  237. // Check that we have the lock #1.
  238. body, status, err := testGetLockIndex(s, "foo")
  239. assert.NoError(t, err)
  240. assert.Equal(t, status, 200)
  241. assert.Equal(t, body, "2")
  242. // Release lock #1.
  243. _, status, err = testReleaseLock(s, "foo", "2", "")
  244. assert.NoError(t, err)
  245. assert.Equal(t, status, 200)
  246. // Check that we have no lock.
  247. body, status, err = testGetLockIndex(s, "foo")
  248. assert.NoError(t, err)
  249. assert.Equal(t, status, 200)
  250. })
  251. }
  252. // Ensure that a lock honours the timeout=0 (nowait) option when lock is already held
  253. func TestModLockAcquireNoWaitWhileLocked(t *testing.T) {
  254. tests.RunServer(func(s *server.Server) {
  255. c := make(chan bool)
  256. // Acquire lock #1.
  257. go func() {
  258. body, status, err := testAcquireLock(s, "foo", "first", 10)
  259. assert.NoError(t, err)
  260. assert.Equal(t, status, 200)
  261. assert.Equal(t, body, "2")
  262. c <- true
  263. }()
  264. <-c
  265. // Attempt to acquire lock #2; fail if no lock immediately acquired
  266. waiting := true
  267. go func() {
  268. c <- true
  269. _, status, err := testAcquireLockWithTimeout(s, "foo", "second", 10, 0)
  270. assert.NoError(t, err)
  271. assert.Equal(t, status, 500)
  272. waiting = false
  273. }()
  274. <-c
  275. time.Sleep(1 * time.Second)
  276. // Check that we have the lock #1.
  277. body, status, err := testGetLockIndex(s, "foo")
  278. assert.NoError(t, err)
  279. assert.Equal(t, status, 200)
  280. assert.Equal(t, body, "2")
  281. // Check that we are not still waiting for lock #2.
  282. assert.Equal(t, waiting, false)
  283. // Release lock #1.
  284. _, status, err = testReleaseLock(s, "foo", "2", "")
  285. assert.NoError(t, err)
  286. assert.Equal(t, status, 200)
  287. // Check that we have no lock.
  288. body, status, err = testGetLockIndex(s, "foo")
  289. assert.NoError(t, err)
  290. assert.Equal(t, status, 200)
  291. })
  292. }
  293. func testAcquireLock(s *server.Server, key string, value string, ttl int) (string, int, error) {
  294. resp, err := tests.PostForm(fmt.Sprintf("%s/mod/v2/lock/%s?value=%s&ttl=%d", s.URL(), key, value, ttl), nil)
  295. ret := tests.ReadBody(resp)
  296. return string(ret), resp.StatusCode, err
  297. }
  298. func testAcquireLockWithTimeout(s *server.Server, key string, value string, ttl int, timeout int) (string, int, error) {
  299. resp, err := tests.PostForm(fmt.Sprintf("%s/mod/v2/lock/%s?value=%s&ttl=%d&timeout=%d", s.URL(), key, value, ttl, timeout), nil)
  300. ret := tests.ReadBody(resp)
  301. return string(ret), resp.StatusCode, err
  302. }
  303. func testGetLockIndex(s *server.Server, key string) (string, int, error) {
  304. resp, err := tests.Get(fmt.Sprintf("%s/mod/v2/lock/%s?field=index", s.URL(), key))
  305. ret := tests.ReadBody(resp)
  306. return string(ret), resp.StatusCode, err
  307. }
  308. func testGetLockValue(s *server.Server, key string) (string, int, error) {
  309. resp, err := tests.Get(fmt.Sprintf("%s/mod/v2/lock/%s", s.URL(), key))
  310. ret := tests.ReadBody(resp)
  311. return string(ret), resp.StatusCode, err
  312. }
  313. func testReleaseLock(s *server.Server, key string, index string, value string) (string, int, error) {
  314. resp, err := tests.DeleteForm(fmt.Sprintf("%s/mod/v2/lock/%s?index=%s&value=%s", s.URL(), key, index, value), nil)
  315. ret := tests.ReadBody(resp)
  316. return string(ret), resp.StatusCode, err
  317. }
  318. func testRenewLock(s *server.Server, key string, index string, value string, ttl int) (string, int, error) {
  319. resp, err := tests.PutForm(fmt.Sprintf("%s/mod/v2/lock/%s?index=%s&value=%s&ttl=%d", s.URL(), key, index, value, ttl), nil)
  320. ret := tests.ReadBody(resp)
  321. return string(ret), resp.StatusCode, err
  322. }