github.com/lingyao2333/mo-zero@v1.4.1/core/stores/cache/cachenode_test.go (about)

     1  package cache
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"math/rand"
     7  	"strconv"
     8  	"sync"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/alicebob/miniredis/v2"
    13  	"github.com/lingyao2333/mo-zero/core/logx"
    14  	"github.com/lingyao2333/mo-zero/core/mathx"
    15  	"github.com/lingyao2333/mo-zero/core/stat"
    16  	"github.com/lingyao2333/mo-zero/core/stores/redis"
    17  	"github.com/lingyao2333/mo-zero/core/stores/redis/redistest"
    18  	"github.com/lingyao2333/mo-zero/core/syncx"
    19  	"github.com/stretchr/testify/assert"
    20  )
    21  
    22  var errTestNotFound = errors.New("not found")
    23  
    24  func init() {
    25  	logx.Disable()
    26  	stat.SetReporter(nil)
    27  }
    28  
    29  func TestCacheNode_DelCache(t *testing.T) {
    30  	store, clean, err := redistest.CreateRedis()
    31  	assert.Nil(t, err)
    32  	store.Type = redis.ClusterType
    33  	defer clean()
    34  
    35  	cn := cacheNode{
    36  		rds:            store,
    37  		r:              rand.New(rand.NewSource(time.Now().UnixNano())),
    38  		lock:           new(sync.Mutex),
    39  		unstableExpiry: mathx.NewUnstable(expiryDeviation),
    40  		stat:           NewStat("any"),
    41  		errNotFound:    errTestNotFound,
    42  	}
    43  	assert.Nil(t, cn.Del())
    44  	assert.Nil(t, cn.Del([]string{}...))
    45  	assert.Nil(t, cn.Del(make([]string, 0)...))
    46  	cn.Set("first", "one")
    47  	assert.Nil(t, cn.Del("first"))
    48  	cn.Set("first", "one")
    49  	cn.Set("second", "two")
    50  	assert.Nil(t, cn.Del("first", "second"))
    51  }
    52  
    53  func TestCacheNode_DelCacheWithErrors(t *testing.T) {
    54  	store, clean, err := redistest.CreateRedis()
    55  	assert.Nil(t, err)
    56  	defer clean()
    57  	store.Type = redis.ClusterType
    58  
    59  	cn := cacheNode{
    60  		rds:            store,
    61  		r:              rand.New(rand.NewSource(time.Now().UnixNano())),
    62  		lock:           new(sync.Mutex),
    63  		unstableExpiry: mathx.NewUnstable(expiryDeviation),
    64  		stat:           NewStat("any"),
    65  		errNotFound:    errTestNotFound,
    66  	}
    67  	assert.Nil(t, cn.Del("third", "fourth"))
    68  }
    69  
    70  func TestCacheNode_InvalidCache(t *testing.T) {
    71  	s, err := miniredis.Run()
    72  	assert.Nil(t, err)
    73  	defer s.Close()
    74  
    75  	cn := cacheNode{
    76  		rds:            redis.New(s.Addr()),
    77  		r:              rand.New(rand.NewSource(time.Now().UnixNano())),
    78  		lock:           new(sync.Mutex),
    79  		unstableExpiry: mathx.NewUnstable(expiryDeviation),
    80  		stat:           NewStat("any"),
    81  		errNotFound:    errTestNotFound,
    82  	}
    83  	s.Set("any", "value")
    84  	var str string
    85  	assert.NotNil(t, cn.Get("any", &str))
    86  	assert.Equal(t, "", str)
    87  	_, err = s.Get("any")
    88  	assert.Equal(t, miniredis.ErrKeyNotFound, err)
    89  }
    90  
    91  func TestCacheNode_SetWithExpire(t *testing.T) {
    92  	store, clean, err := redistest.CreateRedis()
    93  	assert.Nil(t, err)
    94  	defer clean()
    95  
    96  	cn := cacheNode{
    97  		rds:            store,
    98  		r:              rand.New(rand.NewSource(time.Now().UnixNano())),
    99  		barrier:        syncx.NewSingleFlight(),
   100  		lock:           new(sync.Mutex),
   101  		unstableExpiry: mathx.NewUnstable(expiryDeviation),
   102  		stat:           NewStat("any"),
   103  		errNotFound:    errors.New("any"),
   104  	}
   105  	assert.NotNil(t, cn.SetWithExpire("key", make(chan int), time.Second))
   106  }
   107  
   108  func TestCacheNode_Take(t *testing.T) {
   109  	store, clean, err := redistest.CreateRedis()
   110  	assert.Nil(t, err)
   111  	defer clean()
   112  
   113  	cn := NewNode(store, syncx.NewSingleFlight(), NewStat("any"), errTestNotFound,
   114  		WithExpiry(time.Second), WithNotFoundExpiry(time.Second))
   115  	var str string
   116  	err = cn.Take(&str, "any", func(v interface{}) error {
   117  		*v.(*string) = "value"
   118  		return nil
   119  	})
   120  	assert.Nil(t, err)
   121  	assert.Equal(t, "value", str)
   122  	assert.Nil(t, cn.Get("any", &str))
   123  	val, err := store.Get("any")
   124  	assert.Nil(t, err)
   125  	assert.Equal(t, `"value"`, val)
   126  }
   127  
   128  func TestCacheNode_TakeNotFound(t *testing.T) {
   129  	store, clean, err := redistest.CreateRedis()
   130  	assert.Nil(t, err)
   131  	defer clean()
   132  
   133  	cn := cacheNode{
   134  		rds:            store,
   135  		r:              rand.New(rand.NewSource(time.Now().UnixNano())),
   136  		barrier:        syncx.NewSingleFlight(),
   137  		lock:           new(sync.Mutex),
   138  		unstableExpiry: mathx.NewUnstable(expiryDeviation),
   139  		stat:           NewStat("any"),
   140  		errNotFound:    errTestNotFound,
   141  	}
   142  	var str string
   143  	err = cn.Take(&str, "any", func(v interface{}) error {
   144  		return errTestNotFound
   145  	})
   146  	assert.True(t, cn.IsNotFound(err))
   147  	assert.True(t, cn.IsNotFound(cn.Get("any", &str)))
   148  	val, err := store.Get("any")
   149  	assert.Nil(t, err)
   150  	assert.Equal(t, `*`, val)
   151  
   152  	store.Set("any", "*")
   153  	err = cn.Take(&str, "any", func(v interface{}) error {
   154  		return nil
   155  	})
   156  	assert.True(t, cn.IsNotFound(err))
   157  	assert.True(t, cn.IsNotFound(cn.Get("any", &str)))
   158  
   159  	store.Del("any")
   160  	errDummy := errors.New("dummy")
   161  	err = cn.Take(&str, "any", func(v interface{}) error {
   162  		return errDummy
   163  	})
   164  	assert.Equal(t, errDummy, err)
   165  }
   166  
   167  func TestCacheNode_TakeWithExpire(t *testing.T) {
   168  	store, clean, err := redistest.CreateRedis()
   169  	assert.Nil(t, err)
   170  	defer clean()
   171  
   172  	cn := cacheNode{
   173  		rds:            store,
   174  		r:              rand.New(rand.NewSource(time.Now().UnixNano())),
   175  		barrier:        syncx.NewSingleFlight(),
   176  		lock:           new(sync.Mutex),
   177  		unstableExpiry: mathx.NewUnstable(expiryDeviation),
   178  		stat:           NewStat("any"),
   179  		errNotFound:    errors.New("any"),
   180  	}
   181  	var str string
   182  	err = cn.TakeWithExpire(&str, "any", func(v interface{}, expire time.Duration) error {
   183  		*v.(*string) = "value"
   184  		return nil
   185  	})
   186  	assert.Nil(t, err)
   187  	assert.Equal(t, "value", str)
   188  	assert.Nil(t, cn.Get("any", &str))
   189  	val, err := store.Get("any")
   190  	assert.Nil(t, err)
   191  	assert.Equal(t, `"value"`, val)
   192  }
   193  
   194  func TestCacheNode_String(t *testing.T) {
   195  	store, clean, err := redistest.CreateRedis()
   196  	assert.Nil(t, err)
   197  	defer clean()
   198  
   199  	cn := cacheNode{
   200  		rds:            store,
   201  		r:              rand.New(rand.NewSource(time.Now().UnixNano())),
   202  		barrier:        syncx.NewSingleFlight(),
   203  		lock:           new(sync.Mutex),
   204  		unstableExpiry: mathx.NewUnstable(expiryDeviation),
   205  		stat:           NewStat("any"),
   206  		errNotFound:    errors.New("any"),
   207  	}
   208  	assert.Equal(t, store.Addr, cn.String())
   209  }
   210  
   211  func TestCacheValueWithBigInt(t *testing.T) {
   212  	store, clean, err := redistest.CreateRedis()
   213  	assert.Nil(t, err)
   214  	defer clean()
   215  
   216  	cn := cacheNode{
   217  		rds:            store,
   218  		r:              rand.New(rand.NewSource(time.Now().UnixNano())),
   219  		barrier:        syncx.NewSingleFlight(),
   220  		lock:           new(sync.Mutex),
   221  		unstableExpiry: mathx.NewUnstable(expiryDeviation),
   222  		stat:           NewStat("any"),
   223  		errNotFound:    errors.New("any"),
   224  	}
   225  
   226  	const (
   227  		key         = "key"
   228  		value int64 = 323427211229009810
   229  	)
   230  
   231  	assert.Nil(t, cn.Set(key, value))
   232  	var val interface{}
   233  	assert.Nil(t, cn.Get(key, &val))
   234  	assert.Equal(t, strconv.FormatInt(value, 10), fmt.Sprintf("%v", val))
   235  }