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