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  }