github.com/projecteru2/core@v0.0.0-20240321043226-06bcc1c23f58/lock/etcdlock/mutex_test.go (about)

     1  package etcdlock
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/projecteru2/core/store/etcdv3/embedded"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  )
    12  
    13  func TestMutex(t *testing.T) {
    14  	embedd := embedded.NewCluster(t, "/test")
    15  	cli := embedd.RandClient()
    16  
    17  	_, err := New(cli, "", time.Second*1)
    18  	assert.Error(t, err)
    19  	mutex, err := New(cli, "test", time.Second*1)
    20  	assert.NoError(t, err)
    21  
    22  	ctx := context.Background()
    23  	ctx, err = mutex.Lock(ctx)
    24  	assert.Nil(t, ctx.Err())
    25  	assert.NoError(t, err)
    26  	err = mutex.Unlock(ctx)
    27  	assert.NoError(t, err)
    28  	assert.NoError(t, ctx.Err())
    29  
    30  	// round 2: another lock attempt timeout
    31  
    32  	m2, err := New(cli, "test", time.Second)
    33  	assert.NoError(t, err)
    34  	_, err = m2.Lock(context.Background())
    35  	m3, err := New(cli, "test", 100*time.Millisecond)
    36  	assert.NoError(t, err)
    37  	_, err = m3.Lock(context.Background())
    38  	assert.EqualError(t, err, "context deadline exceeded")
    39  	m2.Unlock(context.Background())
    40  	m3.Unlock(context.Background())
    41  
    42  	// round 3: ctx canceled after lock secured
    43  	m4, err := New(cli, "test", time.Second)
    44  	assert.NoError(t, err)
    45  	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    46  	defer cancel()
    47  	rCtx, err := m4.Lock(ctx)
    48  	<-rCtx.Done()
    49  	assert.EqualError(t, rCtx.Err(), "context deadline exceeded")
    50  	m4.Unlock(context.Background())
    51  
    52  	// round 4: passive release
    53  
    54  	m5, err := New(cli, "test", time.Second)
    55  	assert.NoError(t, err)
    56  	_, err = m5.Lock(context.Background())
    57  	assert.NoError(t, err)
    58  	// then after embedded ETCD close, m5 will be unlocked from passive branch
    59  }
    60  
    61  func TestTryLock(t *testing.T) {
    62  	embedd := embedded.NewCluster(t, "/test")
    63  	cli := embedd.RandClient()
    64  
    65  	m1, err := New(cli, "test", time.Second*1)
    66  	assert.NoError(t, err)
    67  	m2, err := New(cli, "test", time.Second*1)
    68  	assert.NoError(t, err)
    69  
    70  	ctx1, err := m1.Lock(context.Background())
    71  	assert.Nil(t, ctx1.Err())
    72  	assert.NoError(t, err)
    73  
    74  	ctx2, err := m2.TryLock(context.Background())
    75  	assert.Nil(t, ctx2)
    76  	assert.Error(t, err)
    77  
    78  	assert.NoError(t, m1.Unlock(context.Background()))
    79  	assert.NoError(t, m2.Unlock(context.Background()))
    80  
    81  	// round 2: lock conflict
    82  
    83  	m3, err := New(cli, "test", time.Second)
    84  	assert.NoError(t, err)
    85  	m4, err := New(cli, "test", time.Second)
    86  	assert.NoError(t, err)
    87  
    88  	rCtx, err := m3.TryLock(context.Background())
    89  	assert.NoError(t, err)
    90  	_, err = m4.TryLock(context.Background())
    91  	assert.EqualError(t, err, "mutex: Locked by another session")
    92  	m4.Unlock(context.Background())
    93  	m3.Unlock(context.Background())
    94  	assert.NoError(t, rCtx.Err())
    95  
    96  	// round 3: ctx canceled after lock secured
    97  	m5, err := New(cli, "test", time.Second)
    98  	assert.NoError(t, err)
    99  	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
   100  	defer cancel()
   101  	rCtx, err = m5.TryLock(ctx)
   102  	<-rCtx.Done()
   103  	assert.EqualError(t, rCtx.Err(), "context deadline exceeded")
   104  	m5.Unlock(context.Background())
   105  
   106  	// round 4: passive release
   107  
   108  	m6, err := New(cli, "test", time.Second)
   109  	assert.NoError(t, err)
   110  	_, err = m6.TryLock(context.Background())
   111  	assert.NoError(t, err)
   112  	// then after embedded ETCD close, m5 will be unlocked from passive branch
   113  }