github.com/matrixorigin/matrixone@v0.7.0/pkg/lockservice/waiter_test.go (about)

     1  // Copyright 2023 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package lockservice
    16  
    17  import (
    18  	"context"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/stretchr/testify/assert"
    23  	"github.com/stretchr/testify/require"
    24  )
    25  
    26  func TestAcquireWaiter(t *testing.T) {
    27  	w := acquireWaiter([]byte("w"))
    28  	defer w.close()
    29  
    30  	assert.Equal(t, 0, len(w.c))
    31  	assert.Equal(t, int32(1), w.refCount.Load())
    32  	assert.Equal(t, 0, w.waiters.len())
    33  }
    34  
    35  func TestAddNewWaiter(t *testing.T) {
    36  	w := acquireWaiter([]byte("w"))
    37  	w1 := acquireWaiter([]byte("w1"))
    38  	defer func() {
    39  		ctx, cancel := context.WithCancel(context.Background())
    40  		defer cancel()
    41  		assert.NoError(t, w1.wait(ctx))
    42  		w1.close()
    43  	}()
    44  
    45  	w.add(w1)
    46  	assert.Equal(t, 1, w.waiters.len())
    47  	assert.Equal(t, int32(2), w1.refCount.Load())
    48  	w.close()
    49  }
    50  
    51  func TestCloseWaiter(t *testing.T) {
    52  	w := acquireWaiter([]byte("w"))
    53  	w1 := acquireWaiter([]byte("w1"))
    54  	w2 := acquireWaiter([]byte("w2"))
    55  
    56  	w.add(w1)
    57  	w.add(w2)
    58  
    59  	v := w.close()
    60  	assert.NotNil(t, v)
    61  	assert.Equal(t, 1, v.waiters.len())
    62  	assert.Equal(t, w1, v)
    63  
    64  	ctx, cancel := context.WithCancel(context.Background())
    65  	defer cancel()
    66  	assert.NoError(t, w1.wait(ctx))
    67  
    68  	v = w1.close()
    69  	assert.NotNil(t, v)
    70  	assert.Equal(t, 0, v.waiters.len())
    71  	assert.Equal(t, w2, v)
    72  
    73  	assert.NoError(t, w2.wait(ctx))
    74  	assert.Nil(t, w2.close())
    75  }
    76  
    77  func TestWait(t *testing.T) {
    78  	w := acquireWaiter([]byte("w"))
    79  	w1 := acquireWaiter([]byte("w1"))
    80  	defer w1.close()
    81  
    82  	w.add(w1)
    83  	go func() {
    84  		time.Sleep(time.Millisecond * 10)
    85  		w.close()
    86  	}()
    87  
    88  	assert.NoError(t, w1.wait(context.Background()))
    89  }
    90  
    91  func TestWaitWithTimeout(t *testing.T) {
    92  	w := acquireWaiter([]byte("w"))
    93  	defer w.close()
    94  	w1 := acquireWaiter([]byte("w1"))
    95  	defer w1.close()
    96  
    97  	w.add(w1)
    98  
    99  	ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*100)
   100  	defer cancel()
   101  	assert.Error(t, w1.wait(ctx))
   102  }
   103  
   104  func TestWaitAndNotifyConcurrent(t *testing.T) {
   105  	w := acquireWaiter([]byte("w"))
   106  	defer w.close()
   107  
   108  	w.beforeSwapStatusAdjustFunc = func() {
   109  		w.setStatus(notified)
   110  		w.c <- nil
   111  	}
   112  
   113  	ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*10)
   114  	defer cancel()
   115  	assert.NoError(t, w.wait(ctx))
   116  }
   117  
   118  func TestWaitMultiTimes(t *testing.T) {
   119  	w := acquireWaiter([]byte("w"))
   120  	w1 := acquireWaiter([]byte("w1"))
   121  	w2 := acquireWaiter([]byte("w2"))
   122  	defer w2.close()
   123  
   124  	ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*100)
   125  	defer cancel()
   126  
   127  	w.add(w2)
   128  	w.close()
   129  	assert.NoError(t, w2.wait(ctx))
   130  	w2.resetWait()
   131  
   132  	w1.add(w2)
   133  	w1.close()
   134  	assert.NoError(t, w2.wait(ctx))
   135  
   136  }
   137  
   138  func TestSkipCompletedWaiters(t *testing.T) {
   139  	w := acquireWaiter([]byte("w"))
   140  	w1 := acquireWaiter([]byte("w1"))
   141  	defer w1.close()
   142  	w2 := acquireWaiter([]byte("w2"))
   143  	w3 := acquireWaiter([]byte("w3"))
   144  	defer w3.close()
   145  
   146  	w.add(w1)
   147  	w.add(w2)
   148  	w.add(w3)
   149  
   150  	// make w1 completed
   151  	w1.setStatus(completed)
   152  
   153  	v := w.close()
   154  	assert.Equal(t, w2, v)
   155  
   156  	v = w2.close()
   157  	assert.Equal(t, w3, v)
   158  }
   159  
   160  func TestNotifyAfterCompleted(t *testing.T) {
   161  	w := acquireWaiter(nil)
   162  	require.Equal(t, 0, len(w.c))
   163  	defer w.close()
   164  	w.setStatus(completed)
   165  	assert.False(t, w.notify(nil))
   166  }
   167  
   168  func TestNotifyAfterAlreadyNotified(t *testing.T) {
   169  	w := acquireWaiter(nil)
   170  	defer w.close()
   171  	assert.True(t, w.notify(nil))
   172  	assert.NoError(t, w.wait(context.Background()))
   173  	assert.False(t, w.notify(nil))
   174  }
   175  
   176  func TestNotifyWithStatusChanged(t *testing.T) {
   177  	w := acquireWaiter(nil)
   178  	defer w.close()
   179  
   180  	w.beforeSwapStatusAdjustFunc = func() {
   181  		w.setStatus(completed)
   182  	}
   183  	assert.False(t, w.notify(nil))
   184  }