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 }