2018-06-29 21:06:25 +01:00
|
|
|
// Copyright (C) 2018 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package redis
|
|
|
|
|
|
|
|
import (
|
2018-07-31 16:23:55 +01:00
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
2018-06-29 21:06:25 +01:00
|
|
|
"testing"
|
2018-07-31 16:23:55 +01:00
|
|
|
"time"
|
2018-06-29 21:06:25 +01:00
|
|
|
|
2018-07-31 16:23:55 +01:00
|
|
|
"github.com/go-redis/redis"
|
|
|
|
"github.com/stretchr/testify/assert"
|
2018-06-29 21:06:25 +01:00
|
|
|
"storj.io/storj/internal/test"
|
|
|
|
"storj.io/storj/storage"
|
|
|
|
)
|
|
|
|
|
|
|
|
type RedisClientTest struct {
|
|
|
|
*testing.T
|
|
|
|
c storage.KeyValueStore
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewRedisClientTest(t *testing.T) *RedisClientTest {
|
|
|
|
kv := make(test.KvStore)
|
|
|
|
c := test.NewMockKeyValueStore(kv)
|
|
|
|
return &RedisClientTest{
|
|
|
|
T: t,
|
|
|
|
c: c,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rt *RedisClientTest) Close() {
|
|
|
|
rt.c.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rt *RedisClientTest) HandleErr(err error, msg string) {
|
|
|
|
rt.Error(msg)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
panic(msg)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestListWithoutStartKey(t *testing.T) {
|
|
|
|
rt := NewRedisClientTest(t)
|
|
|
|
defer rt.Close()
|
|
|
|
|
|
|
|
if err := rt.c.Put(storage.Key([]byte("path/1")), []byte("pointer1")); err != nil {
|
|
|
|
rt.HandleErr(err, "Failed to put")
|
|
|
|
}
|
|
|
|
if err := rt.c.Put(storage.Key([]byte("path/2")), []byte("pointer2")); err != nil {
|
|
|
|
rt.HandleErr(err, "Failed to put")
|
|
|
|
}
|
|
|
|
if err := rt.c.Put(storage.Key([]byte("path/3")), []byte("pointer3")); err != nil {
|
|
|
|
rt.HandleErr(err, "Failed to put")
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err := rt.c.List(nil, storage.Limit(3))
|
|
|
|
if err != nil {
|
|
|
|
rt.HandleErr(err, "Failed to list")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestListWithStartKey(t *testing.T) {
|
|
|
|
rt := NewRedisClientTest(t)
|
|
|
|
defer rt.Close()
|
|
|
|
|
|
|
|
if err := rt.c.Put(storage.Key([]byte("path/1")), []byte("pointer1")); err != nil {
|
|
|
|
rt.HandleErr(err, "Failed to put")
|
|
|
|
}
|
|
|
|
if err := rt.c.Put(storage.Key([]byte("path/2")), []byte("pointer2")); err != nil {
|
|
|
|
rt.HandleErr(err, "Failed to put")
|
|
|
|
}
|
|
|
|
if err := rt.c.Put(storage.Key([]byte("path/3")), []byte("pointer3")); err != nil {
|
|
|
|
rt.HandleErr(err, "Failed to put")
|
|
|
|
}
|
|
|
|
if err := rt.c.Put(storage.Key([]byte("path/4")), []byte("pointer4")); err != nil {
|
|
|
|
rt.HandleErr(err, "Failed to put")
|
|
|
|
}
|
|
|
|
if err := rt.c.Put(storage.Key([]byte("path/5")), []byte("pointer5")); err != nil {
|
|
|
|
rt.HandleErr(err, "Failed to put")
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err := rt.c.List([]byte("path/2"), storage.Limit(2))
|
|
|
|
if err != nil {
|
|
|
|
rt.HandleErr(err, "Failed to list")
|
|
|
|
}
|
|
|
|
}
|
2018-07-31 16:23:55 +01:00
|
|
|
|
|
|
|
var (
|
|
|
|
validConnection = "127.0.0.1:6379"
|
|
|
|
unexistingKey = "unexistingKey"
|
|
|
|
validKey = "validKey"
|
|
|
|
validValue = "validValue"
|
|
|
|
keysList = []string{"key1", "key2", "key3"}
|
|
|
|
dbTest = 1
|
|
|
|
)
|
|
|
|
|
|
|
|
type TestFunc func(t *testing.T, st storage.KeyValueStore)
|
|
|
|
|
|
|
|
func testWithRedis(t *testing.T, testFunc TestFunc) {
|
|
|
|
st, err := NewClient(validConnection, "", dbTest)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotNil(t, st)
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
st.Close()
|
|
|
|
}()
|
|
|
|
|
|
|
|
testFunc(t, st)
|
|
|
|
}
|
|
|
|
|
|
|
|
func testWithInvalidConnection(t *testing.T, testFunc TestFunc) {
|
|
|
|
st := &redisClient{
|
|
|
|
db: redis.NewClient(&redis.Options{
|
|
|
|
Addr: "",
|
|
|
|
Password: "",
|
|
|
|
DB: dbTest,
|
|
|
|
}),
|
|
|
|
TTL: defaultNodeExpiration,
|
|
|
|
}
|
|
|
|
|
|
|
|
testFunc(t, st)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCloseRedis(t *testing.T) {
|
|
|
|
testWithRedis(t, func(t *testing.T, st storage.KeyValueStore) {
|
|
|
|
err := st.Close()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNewClient(t *testing.T) {
|
|
|
|
cases := []struct {
|
|
|
|
testName, address string
|
|
|
|
testFunc func(storage.KeyValueStore, error)
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"NotValidConnection",
|
|
|
|
"",
|
|
|
|
func(st storage.KeyValueStore, err error) {
|
|
|
|
assert.Error(t, err)
|
|
|
|
assert.Nil(t, st)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"ValidConnection",
|
|
|
|
validConnection,
|
|
|
|
func(st storage.KeyValueStore, err error) {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotNil(t, st)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, c := range cases {
|
|
|
|
t.Run(c.testName, func(t *testing.T) {
|
|
|
|
storage, err := NewClient(c.address, "", dbTest)
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
if err == nil {
|
|
|
|
storage.Close()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
c.testFunc(storage, err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCrudValidConnection(t *testing.T) {
|
|
|
|
cases := []struct {
|
|
|
|
testName string
|
|
|
|
testFunc TestFunc
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"GetUnexistingKey",
|
|
|
|
func(t *testing.T, st storage.KeyValueStore) {
|
|
|
|
err := st.Delete(storage.Key(unexistingKey))
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
value, err := st.Get(storage.Key(unexistingKey))
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Nil(t, value)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"GetValidKey",
|
|
|
|
func(t *testing.T, st storage.KeyValueStore) {
|
|
|
|
key := storage.Key(validKey)
|
|
|
|
orgValue := storage.Value(validValue)
|
|
|
|
|
|
|
|
err := st.Put(key, orgValue)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
value, err := st.Get(key)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, orgValue, value)
|
|
|
|
|
|
|
|
err = st.Delete(key)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"UpdateKey",
|
|
|
|
func(t *testing.T, st storage.KeyValueStore) {
|
|
|
|
key := storage.Key(validKey)
|
|
|
|
orgValue := storage.Value(validValue)
|
|
|
|
|
|
|
|
err := st.Put(key, orgValue)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
err = st.Put(key, orgValue)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
err = st.Delete(key)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"GetKeysList",
|
|
|
|
func(t *testing.T, st storage.KeyValueStore) {
|
|
|
|
orgValue := storage.Value(validValue)
|
|
|
|
|
|
|
|
list := storage.Keys{}
|
|
|
|
for _, key := range keysList {
|
|
|
|
list = append(list, storage.Key(key))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, key := range list {
|
|
|
|
err := st.Put(key, orgValue)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
keys, err := st.List(list[0], storage.Limit(len(keysList)))
|
|
|
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.ElementsMatch(t, list, keys)
|
|
|
|
assert.Equal(t, len(list), len(keys))
|
|
|
|
|
|
|
|
for _, key := range list {
|
|
|
|
err := st.Delete(key)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"GetKeysListWithFirstArgNil",
|
|
|
|
func(t *testing.T, st storage.KeyValueStore) {
|
|
|
|
keys, err := st.List(nil, storage.Limit(len(keysList)))
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, len(keys), 0)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, c := range cases {
|
|
|
|
t.Run(c.testName, func(t *testing.T) {
|
|
|
|
testWithRedis(t, c.testFunc)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCrudInvalidConnection(t *testing.T) {
|
|
|
|
cases := []struct {
|
|
|
|
testName string
|
|
|
|
testFunc TestFunc
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"Get",
|
|
|
|
func(t *testing.T, st storage.KeyValueStore) {
|
|
|
|
_, err := st.Get(storage.Key(validKey))
|
|
|
|
assert.Error(t, err)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Put",
|
|
|
|
func(t *testing.T, st storage.KeyValueStore) {
|
|
|
|
err := st.Put(storage.Key(validKey), storage.Value(validValue))
|
|
|
|
assert.Error(t, err)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Delete",
|
|
|
|
func(t *testing.T, st storage.KeyValueStore) {
|
|
|
|
err := st.Delete(storage.Key(validKey))
|
|
|
|
assert.Error(t, err)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"ListArgValid",
|
|
|
|
func(t *testing.T, st storage.KeyValueStore) {
|
|
|
|
keys, err := st.List(storage.Key(validKey), 1)
|
|
|
|
assert.Error(t, err)
|
|
|
|
assert.Nil(t, keys)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"ListArgInvalid",
|
|
|
|
func(t *testing.T, st storage.KeyValueStore) {
|
|
|
|
keys, err := st.List(nil, 1)
|
|
|
|
assert.Error(t, err)
|
|
|
|
assert.Nil(t, keys)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, c := range cases {
|
|
|
|
t.Run(c.testName, func(t *testing.T) {
|
|
|
|
testWithInvalidConnection(t, c.testFunc)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMain(m *testing.M) {
|
|
|
|
cmd := exec.Command("redis-server")
|
|
|
|
|
|
|
|
err := cmd.Start()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
//waiting for "redis-server command" to start
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
|
|
|
|
retCode := m.Run()
|
|
|
|
|
|
|
|
err = cmd.Process.Kill()
|
|
|
|
if err != nil {
|
|
|
|
fmt.Print(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
os.Exit(retCode)
|
|
|
|
}
|