storj/storage/redis/client_test.go
Dennis Coyle 5de5428d3a
First pass at node restrictions (#146)
* WIP First pass at node restrictions

* adjustments to storage clients

* fix cover

* undo previous import change

* adding copyright

* fix the tests

* check for keys

* moar fixes to tests

* linter

* change how we handle restrictions

* add generated pb.go file

* PR comments addressed

* MockKeyValueStore

* pr comments addressed

* missing )

* past my bedtime

* moar merge issues

* cleanup
2018-08-01 10:15:38 -04:00

336 lines
6.9 KiB
Go

// Copyright (C) 2018 Storj Labs, Inc.
// See LICENSE for copying information.
package redis
import (
"fmt"
"os"
"os/exec"
"testing"
"time"
"github.com/go-redis/redis"
"github.com/stretchr/testify/assert"
"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")
}
}
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 := &Client{
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)
}