github.com/cloudreve/Cloudreve/v3@v3.0.0-20240224133659-3edb00a6484c/pkg/cache/redis_test.go (about) 1 package cache 2 3 import ( 4 "errors" 5 "fmt" 6 "github.com/gomodule/redigo/redis" 7 "github.com/rafaeljusto/redigomock" 8 "github.com/stretchr/testify/assert" 9 "testing" 10 "time" 11 ) 12 13 func TestNewRedisStore(t *testing.T) { 14 asserts := assert.New(t) 15 16 store := NewRedisStore(10, "tcp", "", "", "", "0") 17 asserts.NotNil(store) 18 19 asserts.Panics(func() { 20 store.pool.Dial() 21 }) 22 23 testConn := redigomock.NewConn() 24 cmd := testConn.Command("PING").Expect("PONG") 25 err := store.pool.TestOnBorrow(testConn, time.Now()) 26 if testConn.Stats(cmd) != 1 { 27 fmt.Println("Command was not used") 28 return 29 } 30 asserts.NoError(err) 31 } 32 33 func TestRedisStore_Set(t *testing.T) { 34 asserts := assert.New(t) 35 conn := redigomock.NewConn() 36 pool := &redis.Pool{ 37 Dial: func() (redis.Conn, error) { return conn, nil }, 38 MaxIdle: 10, 39 } 40 store := &RedisStore{pool: pool} 41 42 // 正常情况 43 { 44 cmd := conn.Command("SET", "test", redigomock.NewAnyData()).ExpectStringSlice("OK") 45 err := store.Set("test", "test val", -1) 46 asserts.NoError(err) 47 if conn.Stats(cmd) != 1 { 48 fmt.Println("Command was not used") 49 return 50 } 51 } 52 53 // 带有TTL 54 // 正常情况 55 { 56 cmd := conn.Command("SETEX", "test", 10, redigomock.NewAnyData()).ExpectStringSlice("OK") 57 err := store.Set("test", "test val", 10) 58 asserts.NoError(err) 59 if conn.Stats(cmd) != 1 { 60 fmt.Println("Command was not used") 61 return 62 } 63 } 64 65 // 序列化出错 66 { 67 value := struct { 68 Key string 69 }{ 70 Key: "123", 71 } 72 err := store.Set("test", value, -1) 73 asserts.Error(err) 74 } 75 76 // 命令执行失败 77 { 78 conn.Clear() 79 cmd := conn.Command("SET", "test", redigomock.NewAnyData()).ExpectError(errors.New("error")) 80 err := store.Set("test", "test val", -1) 81 asserts.Error(err) 82 if conn.Stats(cmd) != 1 { 83 fmt.Println("Command was not used") 84 return 85 } 86 } 87 // 获取连接失败 88 { 89 store.pool = &redis.Pool{ 90 Dial: func() (redis.Conn, error) { return nil, errors.New("error") }, 91 MaxIdle: 10, 92 } 93 err := store.Set("test", "123", -1) 94 asserts.Error(err) 95 } 96 97 } 98 99 func TestRedisStore_Get(t *testing.T) { 100 asserts := assert.New(t) 101 conn := redigomock.NewConn() 102 pool := &redis.Pool{ 103 Dial: func() (redis.Conn, error) { return conn, nil }, 104 MaxIdle: 10, 105 } 106 store := &RedisStore{pool: pool} 107 108 // 正常情况 109 { 110 expectVal, _ := serializer("test val") 111 cmd := conn.Command("GET", "test").Expect(expectVal) 112 val, ok := store.Get("test") 113 if conn.Stats(cmd) != 1 { 114 fmt.Println("Command was not used") 115 return 116 } 117 asserts.True(ok) 118 asserts.Equal("test val", val.(string)) 119 } 120 121 // Key不存在 122 { 123 conn.Clear() 124 cmd := conn.Command("GET", "test").Expect(nil) 125 val, ok := store.Get("test") 126 if conn.Stats(cmd) != 1 { 127 fmt.Println("Command was not used") 128 return 129 } 130 asserts.False(ok) 131 asserts.Nil(val) 132 } 133 // 解码错误 134 { 135 conn.Clear() 136 cmd := conn.Command("GET", "test").Expect([]byte{0x20}) 137 val, ok := store.Get("test") 138 if conn.Stats(cmd) != 1 { 139 fmt.Println("Command was not used") 140 return 141 } 142 asserts.False(ok) 143 asserts.Nil(val) 144 } 145 // 获取连接失败 146 { 147 store.pool = &redis.Pool{ 148 Dial: func() (redis.Conn, error) { return nil, errors.New("error") }, 149 MaxIdle: 10, 150 } 151 val, ok := store.Get("test") 152 asserts.False(ok) 153 asserts.Nil(val) 154 } 155 } 156 157 func TestRedisStore_Gets(t *testing.T) { 158 asserts := assert.New(t) 159 conn := redigomock.NewConn() 160 pool := &redis.Pool{ 161 Dial: func() (redis.Conn, error) { return conn, nil }, 162 MaxIdle: 10, 163 } 164 store := &RedisStore{pool: pool} 165 166 // 全部命中 167 { 168 conn.Clear() 169 value1, _ := serializer("1") 170 value2, _ := serializer("2") 171 cmd := conn.Command("MGET", "test_1", "test_2").ExpectSlice( 172 value1, value2) 173 res, missed := store.Gets([]string{"1", "2"}, "test_") 174 if conn.Stats(cmd) != 1 { 175 fmt.Println("Command was not used") 176 return 177 } 178 asserts.Len(missed, 0) 179 asserts.Len(res, 2) 180 asserts.Equal("1", res["1"].(string)) 181 asserts.Equal("2", res["2"].(string)) 182 } 183 184 // 命中一个 185 { 186 conn.Clear() 187 value2, _ := serializer("2") 188 cmd := conn.Command("MGET", "test_1", "test_2").ExpectSlice( 189 nil, value2) 190 res, missed := store.Gets([]string{"1", "2"}, "test_") 191 if conn.Stats(cmd) != 1 { 192 fmt.Println("Command was not used") 193 return 194 } 195 asserts.Len(missed, 1) 196 asserts.Len(res, 1) 197 asserts.Equal("1", missed[0]) 198 asserts.Equal("2", res["2"].(string)) 199 } 200 201 // 命令出错 202 { 203 conn.Clear() 204 cmd := conn.Command("MGET", "test_1", "test_2").ExpectError(errors.New("error")) 205 res, missed := store.Gets([]string{"1", "2"}, "test_") 206 if conn.Stats(cmd) != 1 { 207 fmt.Println("Command was not used") 208 return 209 } 210 asserts.Len(missed, 2) 211 asserts.Len(res, 0) 212 } 213 214 // 连接出错 215 { 216 conn.Clear() 217 store.pool = &redis.Pool{ 218 Dial: func() (redis.Conn, error) { return nil, errors.New("error") }, 219 MaxIdle: 10, 220 } 221 res, missed := store.Gets([]string{"1", "2"}, "test_") 222 asserts.Len(missed, 2) 223 asserts.Len(res, 0) 224 } 225 } 226 227 func TestRedisStore_Sets(t *testing.T) { 228 asserts := assert.New(t) 229 conn := redigomock.NewConn() 230 pool := &redis.Pool{ 231 Dial: func() (redis.Conn, error) { return conn, nil }, 232 MaxIdle: 10, 233 } 234 store := &RedisStore{pool: pool} 235 236 // 正常 237 { 238 cmd := conn.Command("MSET", redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData()).ExpectSlice("OK") 239 err := store.Sets(map[string]interface{}{"1": "1", "2": "2"}, "test_") 240 asserts.NoError(err) 241 if conn.Stats(cmd) != 1 { 242 fmt.Println("Command was not used") 243 return 244 } 245 } 246 247 // 序列化失败 248 { 249 conn.Clear() 250 value := struct { 251 Key string 252 }{ 253 Key: "123", 254 } 255 err := store.Sets(map[string]interface{}{"1": value, "2": "2"}, "test_") 256 asserts.Error(err) 257 } 258 259 // 执行失败 260 { 261 cmd := conn.Command("MSET", redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData()).ExpectError(errors.New("error")) 262 err := store.Sets(map[string]interface{}{"1": "1", "2": "2"}, "test_") 263 asserts.Error(err) 264 if conn.Stats(cmd) != 1 { 265 fmt.Println("Command was not used") 266 return 267 } 268 } 269 270 // 连接失败 271 { 272 conn.Clear() 273 store.pool = &redis.Pool{ 274 Dial: func() (redis.Conn, error) { return nil, errors.New("error") }, 275 MaxIdle: 10, 276 } 277 err := store.Sets(map[string]interface{}{"1": "1", "2": "2"}, "test_") 278 asserts.Error(err) 279 } 280 } 281 282 func TestRedisStore_Delete(t *testing.T) { 283 asserts := assert.New(t) 284 conn := redigomock.NewConn() 285 pool := &redis.Pool{ 286 Dial: func() (redis.Conn, error) { return conn, nil }, 287 MaxIdle: 10, 288 } 289 store := &RedisStore{pool: pool} 290 291 // 正常 292 { 293 cmd := conn.Command("DEL", redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData()).ExpectSlice("OK") 294 err := store.Delete([]string{"1", "2", "3", "4"}, "test_") 295 asserts.NoError(err) 296 if conn.Stats(cmd) != 1 { 297 fmt.Println("Command was not used") 298 return 299 } 300 } 301 302 // 命令执行失败 303 { 304 conn.Clear() 305 cmd := conn.Command("DEL", redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData()).ExpectError(errors.New("error")) 306 err := store.Delete([]string{"1", "2", "3", "4"}, "test_") 307 asserts.Error(err) 308 if conn.Stats(cmd) != 1 { 309 fmt.Println("Command was not used") 310 return 311 } 312 } 313 314 // 连接失败 315 { 316 conn.Clear() 317 store.pool = &redis.Pool{ 318 Dial: func() (redis.Conn, error) { return nil, errors.New("error") }, 319 MaxIdle: 10, 320 } 321 err := store.Delete([]string{"1", "2", "3", "4"}, "test_") 322 asserts.Error(err) 323 } 324 }