package cache import ( "errors" "fmt" "github.com/gomodule/redigo/redis" "github.com/rafaeljusto/redigomock" "github.com/stretchr/testify/assert" "testing" "time" ) func TestNewRedisStore(t *testing.T) { asserts := assert.New(t) store := NewRedisStore(10, "tcp", "", "", "", "0") asserts.NotNil(store) asserts.Panics(func() { store.pool.Dial() }) testConn := redigomock.NewConn() cmd := testConn.Command("PING").Expect("PONG") err := store.pool.TestOnBorrow(testConn, time.Now()) if testConn.Stats(cmd) != 1 { fmt.Println("Command was not used") return } asserts.NoError(err) } func TestRedisStore_Set(t *testing.T) { asserts := assert.New(t) conn := redigomock.NewConn() pool := &redis.Pool{ Dial: func() (redis.Conn, error) { return conn, nil }, MaxIdle: 10, } store := &RedisStore{pool: pool} // 正常情况 { cmd := conn.Command("SET", "test", redigomock.NewAnyData()).ExpectStringSlice("OK") err := store.Set("test", "test val", -1) asserts.NoError(err) if conn.Stats(cmd) != 1 { fmt.Println("Command was not used") return } } // 带有TTL // 正常情况 { cmd := conn.Command("SETEX", "test", 10, redigomock.NewAnyData()).ExpectStringSlice("OK") err := store.Set("test", "test val", 10) asserts.NoError(err) if conn.Stats(cmd) != 1 { fmt.Println("Command was not used") return } } // 序列化出错 { value := struct { Key string }{ Key: "123", } err := store.Set("test", value, -1) asserts.Error(err) } // 命令执行失败 { conn.Clear() cmd := conn.Command("SET", "test", redigomock.NewAnyData()).ExpectError(errors.New("error")) err := store.Set("test", "test val", -1) asserts.Error(err) if conn.Stats(cmd) != 1 { fmt.Println("Command was not used") return } } // 获取连接失败 { store.pool = &redis.Pool{ Dial: func() (redis.Conn, error) { return nil, errors.New("error") }, MaxIdle: 10, } err := store.Set("test", "123", -1) asserts.Error(err) } } func TestRedisStore_Get(t *testing.T) { asserts := assert.New(t) conn := redigomock.NewConn() pool := &redis.Pool{ Dial: func() (redis.Conn, error) { return conn, nil }, MaxIdle: 10, } store := &RedisStore{pool: pool} // 正常情况 { expectVal, _ := serializer("test val") cmd := conn.Command("GET", "test").Expect(expectVal) val, ok := store.Get("test") if conn.Stats(cmd) != 1 { fmt.Println("Command was not used") return } asserts.True(ok) asserts.Equal("test val", val.(string)) } // Key不存在 { conn.Clear() cmd := conn.Command("GET", "test").Expect(nil) val, ok := store.Get("test") if conn.Stats(cmd) != 1 { fmt.Println("Command was not used") return } asserts.False(ok) asserts.Nil(val) } // 解码错误 { conn.Clear() cmd := conn.Command("GET", "test").Expect([]byte{0x20}) val, ok := store.Get("test") if conn.Stats(cmd) != 1 { fmt.Println("Command was not used") return } asserts.False(ok) asserts.Nil(val) } // 获取连接失败 { store.pool = &redis.Pool{ Dial: func() (redis.Conn, error) { return nil, errors.New("error") }, MaxIdle: 10, } val, ok := store.Get("test") asserts.False(ok) asserts.Nil(val) } } func TestRedisStore_Gets(t *testing.T) { asserts := assert.New(t) conn := redigomock.NewConn() pool := &redis.Pool{ Dial: func() (redis.Conn, error) { return conn, nil }, MaxIdle: 10, } store := &RedisStore{pool: pool} // 全部命中 { conn.Clear() value1, _ := serializer("1") value2, _ := serializer("2") cmd := conn.Command("MGET", "test_1", "test_2").ExpectSlice( value1, value2) res, missed := store.Gets([]string{"1", "2"}, "test_") if conn.Stats(cmd) != 1 { fmt.Println("Command was not used") return } asserts.Len(missed, 0) asserts.Len(res, 2) asserts.Equal("1", res["1"].(string)) asserts.Equal("2", res["2"].(string)) } // 命中一个 { conn.Clear() value2, _ := serializer("2") cmd := conn.Command("MGET", "test_1", "test_2").ExpectSlice( nil, value2) res, missed := store.Gets([]string{"1", "2"}, "test_") if conn.Stats(cmd) != 1 { fmt.Println("Command was not used") return } asserts.Len(missed, 1) asserts.Len(res, 1) asserts.Equal("1", missed[0]) asserts.Equal("2", res["2"].(string)) } // 命令出错 { conn.Clear() cmd := conn.Command("MGET", "test_1", "test_2").ExpectError(errors.New("error")) res, missed := store.Gets([]string{"1", "2"}, "test_") if conn.Stats(cmd) != 1 { fmt.Println("Command was not used") return } asserts.Len(missed, 2) asserts.Len(res, 0) } // 连接出错 { conn.Clear() store.pool = &redis.Pool{ Dial: func() (redis.Conn, error) { return nil, errors.New("error") }, MaxIdle: 10, } res, missed := store.Gets([]string{"1", "2"}, "test_") asserts.Len(missed, 2) asserts.Len(res, 0) } } func TestRedisStore_Sets(t *testing.T) { asserts := assert.New(t) conn := redigomock.NewConn() pool := &redis.Pool{ Dial: func() (redis.Conn, error) { return conn, nil }, MaxIdle: 10, } store := &RedisStore{pool: pool} // 正常 { cmd := conn.Command("MSET", redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData()).ExpectSlice("OK") err := store.Sets(map[string]interface{}{"1": "1", "2": "2"}, "test_") asserts.NoError(err) if conn.Stats(cmd) != 1 { fmt.Println("Command was not used") return } } // 序列化失败 { conn.Clear() value := struct { Key string }{ Key: "123", } err := store.Sets(map[string]interface{}{"1": value, "2": "2"}, "test_") asserts.Error(err) } // 执行失败 { cmd := conn.Command("MSET", redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData()).ExpectError(errors.New("error")) err := store.Sets(map[string]interface{}{"1": "1", "2": "2"}, "test_") asserts.Error(err) if conn.Stats(cmd) != 1 { fmt.Println("Command was not used") return } } // 连接失败 { conn.Clear() store.pool = &redis.Pool{ Dial: func() (redis.Conn, error) { return nil, errors.New("error") }, MaxIdle: 10, } err := store.Sets(map[string]interface{}{"1": "1", "2": "2"}, "test_") asserts.Error(err) } } func TestRedisStore_Delete(t *testing.T) { asserts := assert.New(t) conn := redigomock.NewConn() pool := &redis.Pool{ Dial: func() (redis.Conn, error) { return conn, nil }, MaxIdle: 10, } store := &RedisStore{pool: pool} // 正常 { cmd := conn.Command("DEL", redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData()).ExpectSlice("OK") err := store.Delete([]string{"1", "2", "3", "4"}, "test_") asserts.NoError(err) if conn.Stats(cmd) != 1 { fmt.Println("Command was not used") return } } // 命令执行失败 { conn.Clear() cmd := conn.Command("DEL", redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData(), redigomock.NewAnyData()).ExpectError(errors.New("error")) err := store.Delete([]string{"1", "2", "3", "4"}, "test_") asserts.Error(err) if conn.Stats(cmd) != 1 { fmt.Println("Command was not used") return } } // 连接失败 { conn.Clear() store.pool = &redis.Pool{ Dial: func() (redis.Conn, error) { return nil, errors.New("error") }, MaxIdle: 10, } err := store.Delete([]string{"1", "2", "3", "4"}, "test_") asserts.Error(err) } }