github.com/jpetazzo/etcd@v0.2.1-0.20140113055439-97f1363afac5/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/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, err := testAcquireLock(s, "foo", "", 10) 18 assert.NoError(t, err) 19 assert.Equal(t, body, "2") 20 21 // Check that we have the lock. 22 body, err = testGetLockIndex(s, "foo") 23 assert.NoError(t, err) 24 assert.Equal(t, body, "2") 25 26 // Release lock. 27 body, err = testReleaseLock(s, "foo", "2", "") 28 assert.NoError(t, err) 29 assert.Equal(t, body, "") 30 31 // Check that we have the lock. 32 body, err = testGetLockIndex(s, "foo") 33 assert.NoError(t, err) 34 assert.Equal(t, body, "") 35 }) 36 } 37 38 // Ensure that a lock can be acquired and another process is blocked until released. 39 func TestModLockBlockUntilAcquire(t *testing.T) { 40 tests.RunServer(func(s *server.Server) { 41 c := make(chan bool) 42 43 // Acquire lock #1. 44 go func() { 45 body, err := testAcquireLock(s, "foo", "", 10) 46 assert.NoError(t, err) 47 assert.Equal(t, body, "2") 48 c <- true 49 }() 50 <- c 51 52 // Acquire lock #2. 53 waiting := true 54 go func() { 55 c <- true 56 body, err := testAcquireLock(s, "foo", "", 10) 57 assert.NoError(t, err) 58 assert.Equal(t, body, "4") 59 waiting = false 60 }() 61 <- c 62 63 time.Sleep(1 * time.Second) 64 65 // Check that we have the lock #1. 66 body, err := testGetLockIndex(s, "foo") 67 assert.NoError(t, err) 68 assert.Equal(t, body, "2") 69 70 // Check that we are still waiting for lock #2. 71 assert.Equal(t, waiting, true) 72 73 // Release lock #1. 74 body, err = testReleaseLock(s, "foo", "2", "") 75 assert.NoError(t, err) 76 77 // Check that we have lock #2. 78 body, err = testGetLockIndex(s, "foo") 79 assert.NoError(t, err) 80 assert.Equal(t, body, "4") 81 82 // Release lock #2. 83 body, err = testReleaseLock(s, "foo", "4", "") 84 assert.NoError(t, err) 85 86 // Check that we have no lock. 87 body, err = testGetLockIndex(s, "foo") 88 assert.NoError(t, err) 89 assert.Equal(t, body, "") 90 }) 91 } 92 93 // Ensure that a lock will be released after the TTL. 94 func TestModLockExpireAndRelease(t *testing.T) { 95 tests.RunServer(func(s *server.Server) { 96 c := make(chan bool) 97 98 // Acquire lock #1. 99 go func() { 100 body, err := testAcquireLock(s, "foo", "", 2) 101 assert.NoError(t, err) 102 assert.Equal(t, body, "2") 103 c <- true 104 }() 105 <- c 106 107 // Acquire lock #2. 108 go func() { 109 c <- true 110 body, err := testAcquireLock(s, "foo", "", 10) 111 assert.NoError(t, err) 112 assert.Equal(t, body, "4") 113 }() 114 <- c 115 116 time.Sleep(1 * time.Second) 117 118 // Check that we have the lock #1. 119 body, err := testGetLockIndex(s, "foo") 120 assert.NoError(t, err) 121 assert.Equal(t, body, "2") 122 123 // Wait for lock #1 TTL. 124 time.Sleep(2 * time.Second) 125 126 // Check that we have lock #2. 127 body, err = testGetLockIndex(s, "foo") 128 assert.NoError(t, err) 129 assert.Equal(t, body, "4") 130 }) 131 } 132 133 // Ensure that a lock can be renewed. 134 func TestModLockRenew(t *testing.T) { 135 tests.RunServer(func(s *server.Server) { 136 // Acquire lock. 137 body, err := testAcquireLock(s, "foo", "", 3) 138 assert.NoError(t, err) 139 assert.Equal(t, body, "2") 140 141 time.Sleep(2 * time.Second) 142 143 // Check that we have the lock. 144 body, err = testGetLockIndex(s, "foo") 145 assert.NoError(t, err) 146 assert.Equal(t, body, "2") 147 148 // Renew lock. 149 body, err = testRenewLock(s, "foo", "2", "", 3) 150 assert.NoError(t, err) 151 assert.Equal(t, body, "") 152 153 time.Sleep(2 * time.Second) 154 155 // Check that we still have the lock. 156 body, err = testGetLockIndex(s, "foo") 157 assert.NoError(t, err) 158 assert.Equal(t, body, "2") 159 160 time.Sleep(2 * time.Second) 161 162 // Check that lock was released. 163 body, err = testGetLockIndex(s, "foo") 164 assert.NoError(t, err) 165 assert.Equal(t, body, "") 166 }) 167 } 168 169 // Ensure that a lock can be acquired with a value and released by value. 170 func TestModLockAcquireAndReleaseByValue(t *testing.T) { 171 tests.RunServer(func(s *server.Server) { 172 // Acquire lock. 173 body, err := testAcquireLock(s, "foo", "XXX", 10) 174 assert.NoError(t, err) 175 assert.Equal(t, body, "2") 176 177 // Check that we have the lock. 178 body, err = testGetLockValue(s, "foo") 179 assert.NoError(t, err) 180 assert.Equal(t, body, "XXX") 181 182 // Release lock. 183 body, err = testReleaseLock(s, "foo", "", "XXX") 184 assert.NoError(t, err) 185 assert.Equal(t, body, "") 186 187 // Check that we released the lock. 188 body, err = testGetLockValue(s, "foo") 189 assert.NoError(t, err) 190 assert.Equal(t, body, "") 191 }) 192 } 193 194 195 196 func testAcquireLock(s *server.Server, key string, value string, ttl int) (string, error) { 197 resp, err := tests.PostForm(fmt.Sprintf("%s/mod/v2/lock/%s?value=%s&ttl=%d", s.URL(), key, value, ttl), nil) 198 ret := tests.ReadBody(resp) 199 return string(ret), err 200 } 201 202 func testGetLockIndex(s *server.Server, key string) (string, error) { 203 resp, err := tests.Get(fmt.Sprintf("%s/mod/v2/lock/%s?field=index", s.URL(), key)) 204 ret := tests.ReadBody(resp) 205 return string(ret), err 206 } 207 208 func testGetLockValue(s *server.Server, key string) (string, error) { 209 resp, err := tests.Get(fmt.Sprintf("%s/mod/v2/lock/%s", s.URL(), key)) 210 ret := tests.ReadBody(resp) 211 return string(ret), err 212 } 213 214 func testReleaseLock(s *server.Server, key string, index string, value string) (string, error) { 215 resp, err := tests.DeleteForm(fmt.Sprintf("%s/mod/v2/lock/%s?index=%s&value=%s", s.URL(), key, index, value), nil) 216 ret := tests.ReadBody(resp) 217 return string(ret), err 218 } 219 220 func testRenewLock(s *server.Server, key string, index string, value string, ttl int) (string, error) { 221 resp, err := tests.PutForm(fmt.Sprintf("%s/mod/v2/lock/%s?index=%s&value=%s&ttl=%d", s.URL(), key, index, value, ttl), nil) 222 ret := tests.ReadBody(resp) 223 return string(ret), err 224 }