mod_lock_test.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  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/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. func testAcquireLock(s *server.Server, key string, value string, ttl int) (string, int, error) {
  183. resp, err := tests.PostForm(fmt.Sprintf("%s/mod/v2/lock/%s?value=%s&ttl=%d", s.URL(), key, value, ttl), nil)
  184. ret := tests.ReadBody(resp)
  185. return string(ret), resp.StatusCode, err
  186. }
  187. func testGetLockIndex(s *server.Server, key string) (string, int, error) {
  188. resp, err := tests.Get(fmt.Sprintf("%s/mod/v2/lock/%s?field=index", s.URL(), key))
  189. ret := tests.ReadBody(resp)
  190. return string(ret), resp.StatusCode, err
  191. }
  192. func testGetLockValue(s *server.Server, key string) (string, int, error) {
  193. resp, err := tests.Get(fmt.Sprintf("%s/mod/v2/lock/%s", s.URL(), key))
  194. ret := tests.ReadBody(resp)
  195. return string(ret), resp.StatusCode, err
  196. }
  197. func testReleaseLock(s *server.Server, key string, index string, value string) (string, int, error) {
  198. resp, err := tests.DeleteForm(fmt.Sprintf("%s/mod/v2/lock/%s?index=%s&value=%s", s.URL(), key, index, value), nil)
  199. ret := tests.ReadBody(resp)
  200. return string(ret), resp.StatusCode, err
  201. }
  202. func testRenewLock(s *server.Server, key string, index string, value string, ttl int) (string, int, error) {
  203. resp, err := tests.PutForm(fmt.Sprintf("%s/mod/v2/lock/%s?index=%s&value=%s&ttl=%d", s.URL(), key, index, value, ttl), nil)
  204. ret := tests.ReadBody(resp)
  205. return string(ret), resp.StatusCode, err
  206. }