storage/db_test.go

253 lines
5.3 KiB
Go

package storage
import (
"bytes"
"io/ioutil"
"log"
"net"
"os"
"path"
"sync"
"testing"
)
type mock struct {
m map[string][]byte
}
func (mock *mock) List(ns []string, limits ...string) ([]string, error) {
keys := []string{}
for k := range mock.m {
keys = append(keys, k)
}
return keys, nil
}
func (mock *mock) Get(key string, ns ...string) ([]byte, error) {
namespace := resolveNamespace(ns)
v, ok := mock.m[path.Join(namespace, key)]
if ok {
return v, nil
}
return nil, ErrNotFound
}
func (mock *mock) Set(key string, value []byte, ns ...string) error {
namespace := resolveNamespace(ns)
mock.m[path.Join(namespace, key)] = value
return nil
}
func (mock *mock) Close() error {
return nil
}
func TestImplementations(t *testing.T) {
dir, err := ioutil.TempDir("", "storage_tests_")
if err != nil {
t.Fatalf("cannot create temp dir: %v", err)
return
}
defer os.RemoveAll(dir)
cases := make([]DB, 0)
cases = append(cases, &mock{m: make(map[string][]byte)})
cases = append(cases, NewMap())
if cacheMem, err := NewCache(); err != nil {
t.Errorf("cannot make cache/mem: %v", err)
} else {
cases = append(cases, cacheMem)
}
if cacheFile, err := NewCache(path.Join(dir, "cache")); err != nil {
t.Errorf("cannot make cache/file: %v", err)
} else {
cases = append(cases, cacheFile)
}
if redis, err := NewRedis("localhost:6379", "", ""); err != nil {
t.Errorf("cannot make redis: %v", err)
} else {
cases = append(cases, redis)
}
if bolt, err := NewBolt(path.Join(dir, "bolt")); err != nil {
t.Errorf("cannot make bolt: %v", err)
} else {
cases = append(cases, bolt)
}
if leveldb, err := NewLevelDB(path.Join(dir, "leveldb")); err != nil {
t.Errorf("cannot make leveldb: %v", err)
} else {
cases = append(cases, leveldb)
}
riakLN, err := net.Listen("tcp", "localhost:8087")
if err == nil {
defer riakLN.Close()
go func() {
for {
conn, err := riakLN.Accept()
if err == nil {
conn.Close()
}
}
}()
}
if riak, err := NewRiak("localhost:8087"); err != nil {
t.Errorf("cannot make riak: %v", err)
} else {
cases = append(cases, riak)
}
mongoLN, err := net.Listen("tcp", "localhost:27017")
if err == nil {
defer mongoLN.Close()
go func() {
for {
conn, err := mongoLN.Accept()
if err == nil {
conn.Close()
}
}
}()
}
if mongo1, err := NewMongo("localhost:27017"); err == nil {
cases = append(cases, mongo1)
} else if mongo2, err := NewMongo("localhost:27017", "root", "pass"); err == nil {
cases = append(cases, mongo2)
} else {
t.Errorf("cannot make mongo: %v", err)
}
if memcache, err := NewMemcache("localhost:11211"); err != nil {
t.Errorf("cannot make memcache: %v", err)
} else {
cases = append(cases, memcache)
}
if memcacheCluster, err := NewMemcacheCluster("localhost:11211"); err != nil {
t.Errorf("cannot make memcacheCluster: %v", err)
} else {
cases = append(cases, memcacheCluster)
}
if minio, err := NewMinio("localhost:9000", "accesskey", "secretkey"); err != nil {
t.Errorf("cannot make minio: %v", err)
} else {
cases = append(cases, minio)
}
validKey := "key"
validValue := []byte("value")
for _, db := range cases {
if err := db.Set(validKey, validValue); err != nil {
t.Errorf("cannot set %T: %v", db, err)
}
if v, err := db.Get(validKey); err != nil {
t.Errorf("cannot get %T: %v", db, err)
} else if !bytes.Equal(v, validValue) {
t.Errorf("wrong get %T: %q vs %q", db, v, validValue)
} else if keys, err := db.List(nil); err != nil || len(keys) < 1 {
t.Errorf("cannot List(): %v", err)
} else if keys[0] != validKey {
t.Errorf("List()[0] != %s: %s", validKey, keys[0])
} else if keys, err := db.List(nil, validKey[:1]); err != nil || len(keys) < 1 {
t.Errorf("cannot List(prefix): %v", err)
} else if keys[0] != validKey {
t.Errorf("List(prefix)[0] != %s: %s", validKey, keys[0])
} else {
t.Logf("%25T GET: %s", db, v)
}
if err := db.Close(); err != nil {
t.Errorf("cannot close %T: %v", db, err)
}
}
}
func TestToFromString(t *testing.T) {
cases := []struct {
key string
t Type
}{
{
key: "map",
t: MAP,
},
{
key: "redis",
t: REDIS,
},
{
key: "minio",
t: MINIO,
},
{
key: "bolt",
t: BOLT,
},
{
key: "cache",
t: CACHE,
},
{
key: "leveldb",
t: LEVELDB,
},
{
key: "memcache",
t: MEMCACHE,
},
{
key: "memcachecluster",
t: MEMCACHECLUSTER,
},
{
key: "mongo",
t: MONGO,
},
}
for _, c := range cases {
if TypeFromString(c.key) != c.t {
t.Errorf("wrong type for %v: got %v", c.key, TypeFromString(c.key))
}
if c.key != c.t.String() {
t.Errorf("wrong string for %v (%v): got %v", int(c.t), c.key, c.t.String())
}
}
}
func TestNew(t *testing.T) {
dir, err := ioutil.TempDir("", "storage_tests_")
if err != nil {
t.Fatalf("cannot create temp dir: %v", err)
return
}
defer os.RemoveAll(dir)
if b, err := New(BOLT); err == nil {
t.Errorf("can create bolt without path")
b.Close()
}
if b, err := New(BOLT, path.Join(dir, "bolt")); err != nil {
t.Errorf("cannot create bolt with path")
} else {
b.Close()
}
}
func recoverDeferred(c Type, t *testing.T, wg *sync.WaitGroup) {
if err := recover(); err != nil {
log.Printf("recover deferre fail: %s", c)
t.Errorf("[%s] panic: %v", c, err)
} else {
log.Printf("recover deferre ok: %s", c)
}
defer wg.Done()
}