Simplify and fix tests (#660)
This commit is contained in:
parent
3e99861e04
commit
6fe16e48ba
@ -5,11 +5,14 @@ package main
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"storj.io/storj/pkg/overlay"
|
||||
"storj.io/storj/storage"
|
||||
"storj.io/storj/storage/boltdb"
|
||||
"storj.io/storj/storage/redis"
|
||||
"storj.io/storj/storage/storelogger"
|
||||
)
|
||||
|
||||
type cacheConfig struct {
|
||||
@ -23,27 +26,27 @@ func (c cacheConfig) open() (*overlay.Cache, error) {
|
||||
return nil, Error.Wrap(err)
|
||||
}
|
||||
|
||||
var cache *overlay.Cache
|
||||
var db storage.KeyValueStore
|
||||
|
||||
switch dburl.Scheme {
|
||||
case "bolt":
|
||||
cache, err = overlay.NewBoltOverlayCache(dburl.Path, nil)
|
||||
db, err = boltdb.New(dburl.Path, overlay.OverlayBucket)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, Error.New("invalid overlay cache database: %s", err)
|
||||
}
|
||||
zap.S().Info("Starting overlay cache with BoltDB")
|
||||
case "redis":
|
||||
db, err := strconv.Atoi(dburl.Query().Get("db"))
|
||||
db, err = redis.NewClientFrom(c.DatabaseURL)
|
||||
if err != nil {
|
||||
return nil, Error.New("invalid db: %s", err)
|
||||
}
|
||||
cache, err = overlay.NewRedisOverlayCache(dburl.Host, overlay.GetUserPassword(dburl), db, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, Error.New("invalid overlay cache database: %s", err)
|
||||
}
|
||||
zap.S().Info("Starting overlay cache with Redis")
|
||||
default:
|
||||
return nil, Error.New("database scheme not supported: %s", dburl.Scheme)
|
||||
}
|
||||
|
||||
return cache, nil
|
||||
// add logger
|
||||
db = storelogger.New(zap.L(), db)
|
||||
|
||||
return overlay.NewOverlayCache(db, nil), nil
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import (
|
||||
"storj.io/storj/pkg/provider"
|
||||
"storj.io/storj/pkg/storage/meta"
|
||||
"storj.io/storj/pkg/storj"
|
||||
"storj.io/storj/storage/redis/redisserver"
|
||||
"storj.io/storj/storage/teststore"
|
||||
)
|
||||
|
||||
@ -125,17 +124,7 @@ func TestAuditSegment(t *testing.T) {
|
||||
db := teststore.New()
|
||||
c := pointerdb.Config{MaxInlineSegmentSize: 8000}
|
||||
|
||||
redisAddr, cleanup, err := redisserver.Start()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer cleanup()
|
||||
|
||||
cache, err := overlay.NewRedisOverlayCache(redisAddr, "", 1, nil)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, cache)
|
||||
cache := overlay.NewOverlayCache(teststore.New(), nil)
|
||||
|
||||
pdbw := newPointerDBWrapper(pointerdb.NewServer(db, cache, zap.NewNop(), c, identity))
|
||||
pointers := pdbclient.New(pdbw)
|
||||
|
@ -11,13 +11,11 @@ import (
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/zeebo/errs"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"storj.io/storj/pkg/dht"
|
||||
"storj.io/storj/pkg/node"
|
||||
"storj.io/storj/pkg/pb"
|
||||
"storj.io/storj/storage"
|
||||
"storj.io/storj/storage/boltdb"
|
||||
"storj.io/storj/storage/redis"
|
||||
"storj.io/storj/storage/storelogger"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -34,24 +32,6 @@ type Cache struct {
|
||||
DHT dht.DHT
|
||||
}
|
||||
|
||||
// NewRedisOverlayCache returns a pointer to a new Cache instance with an initialized connection to Redis.
|
||||
func NewRedisOverlayCache(address, password string, dbindex int, dht dht.DHT) (*Cache, error) {
|
||||
db, err := redis.NewClient(address, password, dbindex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewOverlayCache(storelogger.New(zap.L(), db), dht), nil
|
||||
}
|
||||
|
||||
// NewBoltOverlayCache returns a pointer to a new Cache instance with an initialized connection to a Bolt db.
|
||||
func NewBoltOverlayCache(dbPath string, dht dht.DHT) (*Cache, error) {
|
||||
db, err := boltdb.New(dbPath, OverlayBucket)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewOverlayCache(storelogger.New(zap.L(), db), dht), nil
|
||||
}
|
||||
|
||||
// NewOverlayCache returns a new Cache
|
||||
func NewOverlayCache(db storage.KeyValueStore, dht dht.DHT) *Cache {
|
||||
return &Cache{DB: db, DHT: dht}
|
||||
|
@ -7,55 +7,171 @@ import (
|
||||
"context"
|
||||
"math/rand"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/zeebo/errs"
|
||||
"go.uber.org/zap/zaptest"
|
||||
|
||||
"storj.io/storj/internal/testcontext"
|
||||
"storj.io/storj/pkg/dht"
|
||||
"storj.io/storj/pkg/kademlia"
|
||||
"storj.io/storj/pkg/node"
|
||||
"storj.io/storj/pkg/pb"
|
||||
"storj.io/storj/pkg/provider"
|
||||
"storj.io/storj/pkg/utils"
|
||||
"storj.io/storj/storage"
|
||||
"storj.io/storj/storage/boltdb"
|
||||
"storj.io/storj/storage/redis"
|
||||
"storj.io/storj/storage/redis/redisserver"
|
||||
"storj.io/storj/storage/storelogger"
|
||||
"storj.io/storj/storage/teststore"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = context.Background()
|
||||
)
|
||||
|
||||
type dbClient int
|
||||
type responses map[dbClient]*pb.Node
|
||||
type responsesB map[dbClient][]*pb.Node
|
||||
type errors map[dbClient]*errs.Class
|
||||
|
||||
const (
|
||||
mock dbClient = iota
|
||||
bolt
|
||||
_redis
|
||||
testNetSize = 30
|
||||
)
|
||||
|
||||
func newTestKademlia(t *testing.T, ip, port string, d dht.DHT, b pb.Node) *kademlia.Kademlia {
|
||||
func testOverlay(ctx context.Context, t *testing.T, store storage.KeyValueStore) {
|
||||
overlay := Cache{DB: store}
|
||||
|
||||
t.Run("Put", func(t *testing.T) {
|
||||
err := overlay.Put("valid1", pb.Node{Address: &pb.NodeAddress{Transport: pb.NodeTransport_TCP_TLS_GRPC, Address: "127.0.0.1:9001"}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = overlay.Put("valid2", pb.Node{Address: &pb.NodeAddress{Transport: pb.NodeTransport_TCP_TLS_GRPC, Address: "127.0.0.1:9002"}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Get", func(t *testing.T) {
|
||||
valid2, err := overlay.Get(ctx, "valid2")
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, valid2.Address.Address, "127.0.0.1:9002")
|
||||
}
|
||||
|
||||
invalid2, err := overlay.Get(ctx, "invalid2")
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, invalid2)
|
||||
|
||||
if storeClient, ok := store.(*teststore.Client); ok {
|
||||
storeClient.ForceError++
|
||||
_, err := overlay.Get(ctx, "valid1")
|
||||
assert.Error(t, err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("GetAll", func(t *testing.T) {
|
||||
nodes, err := overlay.GetAll(ctx, []string{"valid2", "valid1", "valid2"})
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, nodes[0].Address.Address, "127.0.0.1:9002")
|
||||
assert.Equal(t, nodes[1].Address.Address, "127.0.0.1:9001")
|
||||
assert.Equal(t, nodes[2].Address.Address, "127.0.0.1:9002")
|
||||
}
|
||||
|
||||
nodes, err = overlay.GetAll(ctx, []string{"valid1", "invalid"})
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, nodes[0].Address.Address, "127.0.0.1:9001")
|
||||
assert.Nil(t, nodes[1])
|
||||
}
|
||||
|
||||
nodes, err = overlay.GetAll(ctx, []string{"", ""})
|
||||
if assert.NoError(t, err) {
|
||||
assert.Nil(t, nodes[0])
|
||||
assert.Nil(t, nodes[1])
|
||||
}
|
||||
|
||||
_, err = overlay.GetAll(ctx, []string{})
|
||||
assert.True(t, OverlayError.Has(err))
|
||||
|
||||
if storeClient, ok := store.(*teststore.Client); ok {
|
||||
storeClient.ForceError++
|
||||
_, err := overlay.GetAll(ctx, []string{"valid1", "valid2"})
|
||||
assert.Error(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRedis(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
defer ctx.Cleanup()
|
||||
|
||||
redisAddr, cleanup, err := redisserver.Start()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
store, err := redis.NewClient(redisAddr, "", 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer ctx.Check(store.Close)
|
||||
|
||||
testOverlay(ctx, t, store)
|
||||
}
|
||||
|
||||
func TestBolt(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
defer ctx.Cleanup()
|
||||
|
||||
client, err := boltdb.New(ctx.File("overlay.db"), "overlay")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer ctx.Check(client.Close)
|
||||
|
||||
testOverlay(ctx, t, client)
|
||||
}
|
||||
|
||||
func TestStore(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
defer ctx.Cleanup()
|
||||
|
||||
testOverlay(ctx, t, teststore.New())
|
||||
}
|
||||
|
||||
func TestRefresh(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
dhts, bootstrap := bootstrapTestNetwork(t, "127.0.0.1", "9999")
|
||||
dht := newTestKademlia(t, "127.0.0.1", "9999", dhts[rand.Intn(testNetSize)], bootstrap)
|
||||
|
||||
cache := &Cache{
|
||||
DB: teststore.New(),
|
||||
DHT: dht,
|
||||
}
|
||||
|
||||
err := cache.Bootstrap(ctx)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = cache.Refresh(ctx)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func newTestKademlia(t *testing.T, ip, port string, d dht.DHT, bootstrap pb.Node) *kademlia.Kademlia {
|
||||
ctx := context.Background()
|
||||
fid, err := node.NewFullIdentity(ctx, 12, 4)
|
||||
assert.NoError(t, err)
|
||||
n := []pb.Node{b}
|
||||
kad, err := kademlia.NewKademlia(fid.ID, n, net.JoinHostPort(ip, port), fid, "db", 5)
|
||||
assert.NoError(t, err)
|
||||
bootstrapNodes := []pb.Node{bootstrap}
|
||||
|
||||
self := pb.Node{Id: fid.ID.String(), Address: &pb.NodeAddress{Address: net.JoinHostPort(ip, port)}}
|
||||
|
||||
routing, err := kademlia.NewRoutingTable(self, teststore.New(), teststore.New())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
kad, err := kademlia.NewKademliaWithRoutingTable(self, bootstrapNodes, fid, 5, routing)
|
||||
if err != nil {
|
||||
t.Fatal(utils.CombineErrors(err, routing.Close()))
|
||||
}
|
||||
|
||||
return kad
|
||||
}
|
||||
|
||||
func bootstrapTestNetwork(t *testing.T, ip, port string) ([]dht.DHT, pb.Node) {
|
||||
ctx := context.Background()
|
||||
bid, err := node.NewFullIdentity(ctx, 12, 4)
|
||||
assert.NoError(t, err)
|
||||
|
||||
@ -73,12 +189,19 @@ func bootstrapTestNetwork(t *testing.T, ip, port string) ([]dht.DHT, pb.Node) {
|
||||
identity, err := ca.NewIdentity()
|
||||
assert.NoError(t, err)
|
||||
|
||||
boot, err := kademlia.NewKademlia(bid.ID, []pb.Node{*intro}, net.JoinHostPort(ip, pm), identity, "db", 5)
|
||||
self := pb.Node{Id: bid.ID.String(), Address: &pb.NodeAddress{Address: net.JoinHostPort(ip, port)}}
|
||||
|
||||
assert.NoError(t, err)
|
||||
rt, err := boot.GetRoutingTable(context.Background())
|
||||
assert.NoError(t, err)
|
||||
bootNode := rt.Local()
|
||||
routing, err := kademlia.NewRoutingTable(self, teststore.New(), teststore.New())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
boot, err := kademlia.NewKademliaWithRoutingTable(self, []pb.Node{*intro}, identity, 5, routing)
|
||||
if err != nil {
|
||||
t.Fatal(utils.CombineErrors(err, routing.Close()))
|
||||
}
|
||||
|
||||
bootNode := routing.Local()
|
||||
|
||||
go func() {
|
||||
err = boot.ListenAndServe()
|
||||
@ -94,8 +217,17 @@ func bootstrapTestNetwork(t *testing.T, ip, port string) ([]dht.DHT, pb.Node) {
|
||||
fid, err := node.NewFullIdentity(ctx, 12, 4)
|
||||
assert.NoError(t, err)
|
||||
|
||||
dht, err := kademlia.NewKademlia(fid.ID, []pb.Node{bootNode}, net.JoinHostPort(ip, gg), fid, "db", 5)
|
||||
assert.NoError(t, err)
|
||||
self := pb.Node{Id: fid.ID.String(), Address: &pb.NodeAddress{Address: net.JoinHostPort(ip, gg)}}
|
||||
|
||||
routing, err := kademlia.NewRoutingTable(self, teststore.New(), teststore.New())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
dht, err := kademlia.NewKademliaWithRoutingTable(self, []pb.Node{bootNode}, fid, 5, routing)
|
||||
if err != nil {
|
||||
t.Fatal(utils.CombineErrors(err, routing.Close()))
|
||||
}
|
||||
|
||||
p++
|
||||
dhts = append(dhts, dht)
|
||||
@ -109,566 +241,3 @@ func bootstrapTestNetwork(t *testing.T, ip, port string) ([]dht.DHT, pb.Node) {
|
||||
|
||||
return dhts, bootNode
|
||||
}
|
||||
|
||||
var (
|
||||
getCases = []struct {
|
||||
testID string
|
||||
expectedTimesCalled int
|
||||
key string
|
||||
expectedResponses responses
|
||||
expectedErrors errors
|
||||
data []storage.ListItem
|
||||
}{
|
||||
{
|
||||
testID: "valid Get",
|
||||
expectedTimesCalled: 1,
|
||||
key: "foo",
|
||||
expectedResponses: func() responses {
|
||||
na := &pb.Node{Address: &pb.NodeAddress{Transport: pb.NodeTransport_TCP_TLS_GRPC, Address: "127.0.0.1:9999"}}
|
||||
return responses{
|
||||
mock: na,
|
||||
bolt: na,
|
||||
_redis: na,
|
||||
}
|
||||
}(),
|
||||
expectedErrors: errors{
|
||||
mock: nil,
|
||||
bolt: nil,
|
||||
_redis: nil,
|
||||
},
|
||||
data: []storage.ListItem{{
|
||||
Key: storage.Key("foo"),
|
||||
Value: func() storage.Value {
|
||||
na := &pb.Node{Address: &pb.NodeAddress{Transport: pb.NodeTransport_TCP_TLS_GRPC, Address: "127.0.0.1:9999"}}
|
||||
d, err := proto.Marshal(na)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return d
|
||||
}(),
|
||||
}},
|
||||
}, {
|
||||
testID: "forced get error",
|
||||
expectedTimesCalled: 1,
|
||||
key: "error",
|
||||
expectedResponses: func() responses {
|
||||
na := &pb.Node{Address: &pb.NodeAddress{Transport: pb.NodeTransport_TCP_TLS_GRPC, Address: "127.0.0.1:9999"}}
|
||||
return responses{
|
||||
mock: nil,
|
||||
bolt: na,
|
||||
_redis: na,
|
||||
}
|
||||
}(),
|
||||
expectedErrors: errors{
|
||||
mock: nil,
|
||||
bolt: nil,
|
||||
_redis: nil,
|
||||
},
|
||||
data: []storage.ListItem{{
|
||||
Key: storage.Key("error"),
|
||||
Value: func() storage.Value {
|
||||
na := &pb.Node{Address: &pb.NodeAddress{Transport: pb.NodeTransport_TCP_TLS_GRPC, Address: "127.0.0.1:9999"}}
|
||||
d, err := proto.Marshal(na)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return d
|
||||
}(),
|
||||
}},
|
||||
},
|
||||
{
|
||||
testID: "get missing key",
|
||||
expectedTimesCalled: 1,
|
||||
key: "bar",
|
||||
expectedResponses: responses{
|
||||
mock: nil,
|
||||
bolt: nil,
|
||||
_redis: nil,
|
||||
},
|
||||
expectedErrors: errors{
|
||||
mock: &storage.ErrKeyNotFound,
|
||||
bolt: &storage.ErrKeyNotFound,
|
||||
_redis: &storage.ErrKeyNotFound,
|
||||
},
|
||||
data: []storage.ListItem{{
|
||||
Key: storage.Key("foo"),
|
||||
Value: func() storage.Value {
|
||||
na := &pb.Node{Address: &pb.NodeAddress{Transport: pb.NodeTransport_TCP_TLS_GRPC, Address: "127.0.0.1:9999"}}
|
||||
d, err := proto.Marshal(na)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return d
|
||||
}(),
|
||||
}},
|
||||
},
|
||||
}
|
||||
getAllCases = []struct {
|
||||
testID string
|
||||
expectedTimesCalled int
|
||||
keys []string
|
||||
expectedResponses responsesB
|
||||
expectedErrors errors
|
||||
data []storage.ListItem
|
||||
}{
|
||||
{testID: "valid GetAll",
|
||||
expectedTimesCalled: 1,
|
||||
keys: []string{"key1"},
|
||||
expectedResponses: func() responsesB {
|
||||
n1 := &pb.Node{Address: &pb.NodeAddress{Transport: pb.NodeTransport_TCP_TLS_GRPC, Address: "127.0.0.1:9999"}}
|
||||
ns := []*pb.Node{n1}
|
||||
return responsesB{
|
||||
mock: ns,
|
||||
bolt: ns,
|
||||
_redis: ns,
|
||||
}
|
||||
}(),
|
||||
expectedErrors: errors{
|
||||
mock: nil,
|
||||
bolt: nil,
|
||||
_redis: nil,
|
||||
},
|
||||
data: []storage.ListItem{
|
||||
{
|
||||
Key: storage.Key("key1"),
|
||||
Value: func() storage.Value {
|
||||
na := &pb.Node{Address: &pb.NodeAddress{Transport: pb.NodeTransport_TCP_TLS_GRPC, Address: "127.0.0.1:9999"}}
|
||||
d, err := proto.Marshal(na)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return d
|
||||
}(),
|
||||
},
|
||||
},
|
||||
},
|
||||
{testID: "valid GetAll",
|
||||
expectedTimesCalled: 1,
|
||||
keys: []string{"key1", "key2"},
|
||||
expectedResponses: func() responsesB {
|
||||
n1 := &pb.Node{Address: &pb.NodeAddress{Transport: pb.NodeTransport_TCP_TLS_GRPC, Address: "127.0.0.1:9999"}}
|
||||
n2 := &pb.Node{Address: &pb.NodeAddress{Transport: pb.NodeTransport_TCP_TLS_GRPC, Address: "127.0.0.1:9998"}}
|
||||
ns := []*pb.Node{n1, n2}
|
||||
return responsesB{
|
||||
mock: ns,
|
||||
bolt: ns,
|
||||
_redis: ns,
|
||||
}
|
||||
}(),
|
||||
expectedErrors: errors{
|
||||
mock: nil,
|
||||
bolt: nil,
|
||||
_redis: nil,
|
||||
},
|
||||
data: []storage.ListItem{
|
||||
{
|
||||
Key: storage.Key("key1"),
|
||||
Value: func() storage.Value {
|
||||
na := &pb.Node{Address: &pb.NodeAddress{Transport: pb.NodeTransport_TCP_TLS_GRPC, Address: "127.0.0.1:9999"}}
|
||||
d, err := proto.Marshal(na)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return d
|
||||
}(),
|
||||
}, {
|
||||
Key: storage.Key("key2"),
|
||||
Value: func() storage.Value {
|
||||
na := &pb.Node{Address: &pb.NodeAddress{Transport: pb.NodeTransport_TCP_TLS_GRPC, Address: "127.0.0.1:9998"}}
|
||||
d, err := proto.Marshal(na)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return d
|
||||
}(),
|
||||
},
|
||||
},
|
||||
},
|
||||
{testID: "mix of valid and nil nodes returned",
|
||||
expectedTimesCalled: 1,
|
||||
keys: []string{"key1", "key3"},
|
||||
expectedResponses: func() responsesB {
|
||||
n1 := &pb.Node{Address: &pb.NodeAddress{Transport: pb.NodeTransport_TCP_TLS_GRPC, Address: "127.0.0.1:9999"}}
|
||||
ns := []*pb.Node{n1, nil}
|
||||
return responsesB{
|
||||
mock: ns,
|
||||
bolt: ns,
|
||||
_redis: ns,
|
||||
}
|
||||
}(),
|
||||
expectedErrors: errors{
|
||||
mock: nil,
|
||||
bolt: nil,
|
||||
_redis: nil,
|
||||
},
|
||||
data: []storage.ListItem{
|
||||
{
|
||||
Key: storage.Key("key1"),
|
||||
Value: func() storage.Value {
|
||||
na := &pb.Node{Address: &pb.NodeAddress{Transport: pb.NodeTransport_TCP_TLS_GRPC, Address: "127.0.0.1:9999"}}
|
||||
d, err := proto.Marshal(na)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return d
|
||||
}(),
|
||||
},
|
||||
},
|
||||
},
|
||||
{testID: "empty string keys",
|
||||
expectedTimesCalled: 1,
|
||||
keys: []string{"", ""},
|
||||
expectedResponses: func() responsesB {
|
||||
ns := []*pb.Node{nil, nil}
|
||||
return responsesB{
|
||||
mock: ns,
|
||||
bolt: ns,
|
||||
_redis: ns,
|
||||
}
|
||||
}(),
|
||||
expectedErrors: errors{
|
||||
mock: nil,
|
||||
bolt: nil,
|
||||
_redis: nil,
|
||||
},
|
||||
},
|
||||
{testID: "empty keys",
|
||||
expectedTimesCalled: 0,
|
||||
keys: []string{},
|
||||
expectedResponses: func() responsesB {
|
||||
return responsesB{
|
||||
mock: nil,
|
||||
bolt: nil,
|
||||
_redis: nil,
|
||||
}
|
||||
}(),
|
||||
expectedErrors: errors{
|
||||
mock: &OverlayError,
|
||||
bolt: &OverlayError,
|
||||
_redis: &OverlayError,
|
||||
},
|
||||
},
|
||||
}
|
||||
putCases = []struct {
|
||||
testID string
|
||||
expectedTimesCalled int
|
||||
key string
|
||||
value pb.Node
|
||||
expectedErrors errors
|
||||
data []storage.ListItem
|
||||
}{
|
||||
{
|
||||
testID: "valid Put",
|
||||
expectedTimesCalled: 1,
|
||||
key: "foo",
|
||||
value: pb.Node{Id: "foo", Address: &pb.NodeAddress{Transport: pb.NodeTransport_TCP_TLS_GRPC, Address: "127.0.0.1:9999"}},
|
||||
expectedErrors: errors{
|
||||
mock: nil,
|
||||
bolt: nil,
|
||||
_redis: nil,
|
||||
},
|
||||
data: []storage.ListItem{},
|
||||
},
|
||||
}
|
||||
|
||||
refreshCases = []struct {
|
||||
testID string
|
||||
expectedTimesCalled int
|
||||
expectedErr error
|
||||
data []storage.ListItem
|
||||
}{
|
||||
{
|
||||
testID: "valid update",
|
||||
expectedTimesCalled: 1,
|
||||
expectedErr: nil,
|
||||
data: []storage.ListItem{},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func redisTestClient(t *testing.T, addr string, items []storage.ListItem) storage.KeyValueStore {
|
||||
client, err := redis.NewClient(addr, "", 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := storage.PutAll(client, items...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
func boltTestClient(t *testing.T, items []storage.ListItem) (_ storage.KeyValueStore, _ func()) {
|
||||
boltPath, err := filepath.Abs("test_bolt.db")
|
||||
assert.NoError(t, err)
|
||||
|
||||
client, err := boltdb.New(boltPath, "testBoltdb")
|
||||
assert.NoError(t, err)
|
||||
|
||||
cleanup := func() {
|
||||
assert.NoError(t, client.Close())
|
||||
assert.NoError(t, os.Remove(boltPath))
|
||||
}
|
||||
|
||||
if err := storage.PutAll(client, items...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return storelogger.New(zaptest.NewLogger(t), client), cleanup
|
||||
}
|
||||
|
||||
func TestRedisGet(t *testing.T) {
|
||||
redisAddr, cleanup, err := redisserver.Start()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
for _, c := range getCases {
|
||||
t.Run(c.testID, func(t *testing.T) {
|
||||
db := redisTestClient(t, redisAddr, c.data)
|
||||
oc := Cache{DB: db}
|
||||
|
||||
resp, err := oc.Get(ctx, c.key)
|
||||
assertErrClass(t, c.expectedErrors[_redis], err)
|
||||
assert.Equal(t, c.expectedResponses[_redis], resp)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedisGetAll(t *testing.T) {
|
||||
redisAddr, cleanup, err := redisserver.Start()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cleanup()
|
||||
for _, c := range getAllCases {
|
||||
t.Run(c.testID, func(t *testing.T) {
|
||||
db := redisTestClient(t, redisAddr, c.data)
|
||||
oc := Cache{DB: db}
|
||||
|
||||
resp, err := oc.GetAll(ctx, c.keys)
|
||||
assertErrClass(t, c.expectedErrors[_redis], err)
|
||||
assert.Equal(t, c.expectedResponses[_redis], resp)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func assertErrClass(t *testing.T, class *errs.Class, err error) {
|
||||
t.Helper()
|
||||
if class != nil {
|
||||
assert.True(t, class.Has(err))
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedisPut(t *testing.T) {
|
||||
redisAddr, cleanup, err := redisserver.Start()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
for _, c := range putCases {
|
||||
t.Run(c.testID, func(t *testing.T) {
|
||||
db := redisTestClient(t, redisAddr, c.data)
|
||||
oc := Cache{DB: db}
|
||||
|
||||
err := oc.Put(c.key, c.value)
|
||||
assertErrClass(t, c.expectedErrors[_redis], err)
|
||||
|
||||
v, err := db.Get([]byte(c.key))
|
||||
assert.NoError(t, err)
|
||||
|
||||
na := &pb.Node{}
|
||||
assert.NoError(t, proto.Unmarshal(v, na))
|
||||
assert.True(t, proto.Equal(na, &c.value))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoltGet(t *testing.T) {
|
||||
for _, c := range getCases {
|
||||
t.Run(c.testID, func(t *testing.T) {
|
||||
db, cleanup := boltTestClient(t, c.data)
|
||||
defer cleanup()
|
||||
|
||||
oc := Cache{DB: db}
|
||||
|
||||
resp, err := oc.Get(ctx, c.key)
|
||||
assertErrClass(t, c.expectedErrors[bolt], err)
|
||||
assert.Equal(t, c.expectedResponses[bolt], resp)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoltGetAll(t *testing.T) {
|
||||
for _, c := range getAllCases {
|
||||
t.Run(c.testID, func(t *testing.T) {
|
||||
db, cleanup := boltTestClient(t, c.data)
|
||||
defer cleanup()
|
||||
oc := Cache{DB: db}
|
||||
resp, err := oc.GetAll(ctx, c.keys)
|
||||
assertErrClass(t, c.expectedErrors[bolt], err)
|
||||
assert.Equal(t, c.expectedResponses[bolt], resp)
|
||||
})
|
||||
}
|
||||
}
|
||||
func TestBoltPut(t *testing.T) {
|
||||
for _, c := range putCases {
|
||||
t.Run(c.testID, func(t *testing.T) {
|
||||
db, cleanup := boltTestClient(t, c.data)
|
||||
defer cleanup()
|
||||
|
||||
oc := Cache{DB: db}
|
||||
|
||||
err := oc.Put(c.key, c.value)
|
||||
assertErrClass(t, c.expectedErrors[_redis], err)
|
||||
|
||||
v, err := db.Get([]byte(c.key))
|
||||
assert.NoError(t, err)
|
||||
na := &pb.Node{}
|
||||
|
||||
assert.NoError(t, proto.Unmarshal(v, na))
|
||||
assert.True(t, proto.Equal(na, &c.value))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMockGet(t *testing.T) {
|
||||
for _, c := range getCases {
|
||||
t.Run(c.testID, func(t *testing.T) {
|
||||
|
||||
db := teststore.New()
|
||||
if err := storage.PutAll(db, c.data...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
oc := Cache{DB: db}
|
||||
|
||||
if c.key == "error" {
|
||||
db.ForceError = 1
|
||||
}
|
||||
assert.Equal(t, 0, db.CallCount.Get)
|
||||
|
||||
resp, err := oc.Get(ctx, c.key)
|
||||
if c.key == "error" {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assertErrClass(t, c.expectedErrors[mock], err)
|
||||
}
|
||||
assert.Equal(t, c.expectedResponses[mock], resp)
|
||||
assert.Equal(t, c.expectedTimesCalled, db.CallCount.Get)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMockGetAll(t *testing.T) {
|
||||
for _, c := range getAllCases {
|
||||
t.Run(c.testID, func(t *testing.T) {
|
||||
|
||||
db := teststore.New()
|
||||
if err := storage.PutAll(db, c.data...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
oc := Cache{DB: db}
|
||||
|
||||
assert.Equal(t, 0, db.CallCount.GetAll)
|
||||
|
||||
resp, err := oc.GetAll(ctx, c.keys)
|
||||
assertErrClass(t, c.expectedErrors[mock], err)
|
||||
assert.Equal(t, c.expectedResponses[mock], resp)
|
||||
assert.Equal(t, c.expectedTimesCalled, db.CallCount.GetAll)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMockPut(t *testing.T) {
|
||||
for _, c := range putCases {
|
||||
t.Run(c.testID, func(t *testing.T) {
|
||||
db := teststore.New()
|
||||
if err := storage.PutAll(db, c.data...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
db.CallCount.Put = 0
|
||||
|
||||
oc := Cache{DB: db}
|
||||
|
||||
err := oc.Put(c.key, c.value)
|
||||
assertErrClass(t, c.expectedErrors[mock], err)
|
||||
assert.Equal(t, c.expectedTimesCalled, db.CallCount.Put)
|
||||
|
||||
v, err := db.Get(storage.Key(c.key))
|
||||
assert.NoError(t, err)
|
||||
|
||||
na := &pb.Node{}
|
||||
assert.NoError(t, proto.Unmarshal(v, na))
|
||||
assert.True(t, proto.Equal(na, &c.value))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRefresh(t *testing.T) {
|
||||
for _, c := range refreshCases {
|
||||
t.Run(c.testID, func(t *testing.T) {
|
||||
dhts, b := bootstrapTestNetwork(t, "127.0.0.1", "1024")
|
||||
ctx := context.Background()
|
||||
|
||||
db := teststore.New()
|
||||
if err := storage.PutAll(db, c.data...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
dht := newTestKademlia(t, "127.0.0.1", "1024", dhts[rand.Intn(testNetSize)], b)
|
||||
|
||||
_cache := &Cache{DB: db, DHT: dht}
|
||||
|
||||
err := _cache.Bootstrap(ctx)
|
||||
assert.Equal(t, err, c.expectedErr)
|
||||
|
||||
err = _cache.Refresh(ctx)
|
||||
assert.Equal(t, err, c.expectedErr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewRedisOverlayCache(t *testing.T) {
|
||||
redisAddr, cleanup, err := redisserver.Start()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
cases := []struct {
|
||||
testName, address string
|
||||
testFunc func(string)
|
||||
}{
|
||||
{
|
||||
testName: "NewRedisOverlayCache valid",
|
||||
address: redisAddr,
|
||||
testFunc: func(address string) {
|
||||
cache, err := NewRedisOverlayCache(address, "", 1, nil)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, cache)
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "NewRedisOverlayCache fail",
|
||||
address: "",
|
||||
testFunc: func(address string) {
|
||||
cache, err := NewRedisOverlayCache(address, "", 1, nil)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, cache)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.testName, func(t *testing.T) {
|
||||
c.testFunc(c.address)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -10,15 +10,15 @@ import (
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/zeebo/errs"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"storj.io/storj/internal/testcontext"
|
||||
"storj.io/storj/pkg/dht"
|
||||
"storj.io/storj/pkg/node"
|
||||
"storj.io/storj/pkg/pb"
|
||||
"storj.io/storj/pkg/provider"
|
||||
"storj.io/storj/storage"
|
||||
"storj.io/storj/storage/redis/redisserver"
|
||||
"storj.io/storj/storage/teststore"
|
||||
)
|
||||
|
||||
type mockNodeID struct {
|
||||
@ -33,6 +33,9 @@ func (m mockNodeID) Bytes() []byte {
|
||||
}
|
||||
|
||||
func TestNewOverlayClient(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
defer ctx.Cleanup()
|
||||
|
||||
cases := []struct {
|
||||
address string
|
||||
}{
|
||||
@ -59,6 +62,9 @@ func TestNewOverlayClient(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestChoose(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
defer ctx.Cleanup()
|
||||
|
||||
cases := []struct {
|
||||
limit int
|
||||
space int64
|
||||
@ -136,6 +142,9 @@ func TestChoose(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLookup(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
defer ctx.Cleanup()
|
||||
|
||||
cases := []struct {
|
||||
nodeID dht.NodeID
|
||||
expectedCalls int
|
||||
@ -174,7 +183,11 @@ func TestLookup(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestBulkLookup(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
defer ctx.Cleanup()
|
||||
|
||||
cases := []struct {
|
||||
nodeIDs []dht.NodeID
|
||||
expectedCalls int
|
||||
@ -211,17 +224,15 @@ func TestBulkLookup(t *testing.T) {
|
||||
assert.Equal(t, mock.bulkLookupCalled, v.expectedCalls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBulkLookupV2(t *testing.T) {
|
||||
redisAddr, cleanup, err := redisserver.Start()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cleanup()
|
||||
ctx := testcontext.New(t)
|
||||
defer ctx.Cleanup()
|
||||
|
||||
lis, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
assert.NoError(t, err)
|
||||
|
||||
srv, s, err := newServer(ctx, redisAddr)
|
||||
srv, s, err := newServer(ctx)
|
||||
|
||||
assert.NoError(t, err)
|
||||
go func() { assert.NoError(t, srv.Serve(lis)) }()
|
||||
@ -247,60 +258,37 @@ func TestBulkLookupV2(t *testing.T) {
|
||||
assert.NoError(t, s.cache.Put(n.Id, *n))
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
testID string
|
||||
nodeIDs []dht.NodeID
|
||||
responses []*pb.Node
|
||||
errors *errs.Class
|
||||
}{
|
||||
{testID: "empty id",
|
||||
nodeIDs: []dht.NodeID{},
|
||||
responses: nil,
|
||||
errors: &ClientError,
|
||||
},
|
||||
{testID: "valid ids",
|
||||
nodeIDs: func() []dht.NodeID {
|
||||
id1 := node.IDFromString("n1")
|
||||
id2 := node.IDFromString("n2")
|
||||
id3 := node.IDFromString("n3")
|
||||
return []dht.NodeID{id1, id2, id3}
|
||||
}(),
|
||||
responses: nodes,
|
||||
errors: nil,
|
||||
},
|
||||
{testID: "missing ids",
|
||||
nodeIDs: func() []dht.NodeID {
|
||||
id1 := node.IDFromString("n4")
|
||||
id2 := node.IDFromString("n5")
|
||||
return []dht.NodeID{id1, id2}
|
||||
}(),
|
||||
responses: []*pb.Node{nil, nil},
|
||||
errors: nil,
|
||||
},
|
||||
{testID: "random order and nil",
|
||||
nodeIDs: func() []dht.NodeID {
|
||||
id1 := node.IDFromString("n1")
|
||||
id2 := node.IDFromString("n2")
|
||||
id3 := node.IDFromString("n3")
|
||||
id4 := node.IDFromString("n4")
|
||||
return []dht.NodeID{id2, id1, id3, id4}
|
||||
}(),
|
||||
responses: func() []*pb.Node {
|
||||
return []*pb.Node{nodes[1], nodes[0], nodes[2], nil}
|
||||
}(),
|
||||
errors: nil,
|
||||
},
|
||||
nid1 := node.IDFromString("n1")
|
||||
nid2 := node.IDFromString("n2")
|
||||
nid3 := node.IDFromString("n3")
|
||||
nid4 := node.IDFromString("n4")
|
||||
nid5 := node.IDFromString("n5")
|
||||
|
||||
{ // empty id
|
||||
_, err := oc.BulkLookup(ctx, []dht.NodeID{})
|
||||
assert.Error(t, err)
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.testID, func(t *testing.T) {
|
||||
ns, err := oc.BulkLookup(ctx, c.nodeIDs)
|
||||
assertErrClass(t, c.errors, err)
|
||||
assert.Equal(t, c.responses, ns)
|
||||
})
|
||||
|
||||
{ // valid ids
|
||||
ns, err := oc.BulkLookup(ctx, []dht.NodeID{nid1, nid2, nid3})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, nodes, ns)
|
||||
}
|
||||
|
||||
{ // missing ids
|
||||
ns, err := oc.BulkLookup(ctx, []dht.NodeID{nid4, nid5})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []*pb.Node{nil, nil}, ns)
|
||||
}
|
||||
|
||||
{ // different order and missing
|
||||
ns, err := oc.BulkLookup(ctx, []dht.NodeID{nid3, nid4, nid1, nid2, nid5})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []*pb.Node{n3, nil, n1, n2, nil}, ns)
|
||||
}
|
||||
}
|
||||
|
||||
func newServer(ctx context.Context, redisAddr string) (*grpc.Server, *Server, error) {
|
||||
func newServer(ctx context.Context) (*grpc.Server, *Server, error) {
|
||||
ca, err := provider.NewTestCA(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -315,11 +303,7 @@ func newServer(ctx context.Context, redisAddr string) (*grpc.Server, *Server, er
|
||||
}
|
||||
|
||||
grpcServer := grpc.NewServer(identOpt)
|
||||
cache, err := NewRedisOverlayCache(redisAddr, "", 1, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
s := &Server{cache: cache}
|
||||
s := &Server{cache: NewOverlayCache(teststore.New(), nil)}
|
||||
|
||||
pb.RegisterOverlayServer(grpcServer, s)
|
||||
|
||||
|
@ -5,17 +5,19 @@ package overlay
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/zeebo/errs"
|
||||
"go.uber.org/zap"
|
||||
monkit "gopkg.in/spacemonkeygo/monkit.v2"
|
||||
|
||||
"storj.io/storj/pkg/kademlia"
|
||||
"storj.io/storj/pkg/pb"
|
||||
"storj.io/storj/pkg/provider"
|
||||
"storj.io/storj/pkg/utils"
|
||||
"storj.io/storj/storage"
|
||||
"storj.io/storj/storage/boltdb"
|
||||
"storj.io/storj/storage/redis"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -55,28 +57,27 @@ func (c Config) Run(ctx context.Context, server *provider.Provider) (
|
||||
return Error.Wrap(err)
|
||||
}
|
||||
|
||||
var cache *Cache
|
||||
var db storage.KeyValueStore
|
||||
|
||||
switch dburl.Scheme {
|
||||
case "bolt":
|
||||
cache, err = NewBoltOverlayCache(dburl.Path, kad)
|
||||
db, err = boltdb.New(dburl.Path, OverlayBucket)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
zap.L().Info("Starting overlay cache with BoltDB")
|
||||
zap.S().Info("Starting overlay cache with BoltDB")
|
||||
case "redis":
|
||||
db, err := strconv.Atoi(dburl.Query().Get("db"))
|
||||
if err != nil {
|
||||
return Error.New("invalid db: %s", err)
|
||||
}
|
||||
cache, err = NewRedisOverlayCache(dburl.Host, GetUserPassword(dburl), db, kad)
|
||||
db, err = redis.NewClientFrom(c.DatabaseURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
zap.L().Info("Starting overlay cache with Redis")
|
||||
zap.S().Info("Starting overlay cache with Redis")
|
||||
default:
|
||||
return Error.New("database scheme not supported: %s", dburl.Scheme)
|
||||
}
|
||||
|
||||
cache := NewOverlayCache(db, kad)
|
||||
|
||||
err = cache.Bootstrap(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -131,14 +132,3 @@ func LoadServerFromContext(ctx context.Context) *Server {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetUserPassword extracts password from scheme://user:password@hostname
|
||||
func GetUserPassword(u *url.URL) string {
|
||||
if u == nil || u.User == nil {
|
||||
return ""
|
||||
}
|
||||
if pw, ok := u.User.Password(); ok {
|
||||
return pw
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
@ -4,86 +4,35 @@ package overlay
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/zeebo/errs"
|
||||
|
||||
"storj.io/storj/pkg/kademlia"
|
||||
)
|
||||
|
||||
func TestRun(t *testing.T) {
|
||||
config := Config{}
|
||||
bctx := context.Background()
|
||||
kad := &kademlia.Kademlia{}
|
||||
var key kademlia.CtxKey
|
||||
var kadKey kademlia.CtxKey
|
||||
ctxWithKad := context.WithValue(context.Background(), kadKey, kad)
|
||||
|
||||
cases := []struct {
|
||||
testName string
|
||||
testFunc func(t *testing.T)
|
||||
}{
|
||||
{
|
||||
testName: "Run with nil",
|
||||
testFunc: func(t *testing.T) {
|
||||
err := config.Run(bctx, nil)
|
||||
// run with nil
|
||||
err := Config{}.Run(context.Background(), nil)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "overlay error: programmer error: kademlia responsibility unstarted", err.Error())
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, err.Error(), "overlay error: programmer error: kademlia responsibility unstarted")
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "Run with nil, pass pointer to Kademlia in context",
|
||||
testFunc: func(t *testing.T) {
|
||||
ctx := context.WithValue(bctx, key, kad)
|
||||
err := config.Run(ctx, nil)
|
||||
// run with nil, pass pointer to Kademlia in context
|
||||
err = Config{}.Run(ctxWithKad, nil)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "overlay error: database scheme not supported: ", err.Error())
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, err.Error(), "overlay error: database scheme not supported: ")
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "db scheme redis conn fail",
|
||||
testFunc: func(t *testing.T) {
|
||||
ctx := context.WithValue(bctx, key, kad)
|
||||
var config = Config{DatabaseURL: "redis://somedir/overlay.db/?db=1"}
|
||||
err := config.Run(ctx, nil)
|
||||
// db scheme redis conn fail
|
||||
err = Config{DatabaseURL: "redis://somedir/overlay.db/?db=1"}.Run(ctxWithKad, nil)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, err.Error(), "redis error: ping failed: dial tcp: address somedir: missing port in address")
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "db scheme bolt conn fail",
|
||||
testFunc: func(t *testing.T) {
|
||||
ctx := context.WithValue(bctx, key, kad)
|
||||
var config = Config{DatabaseURL: "bolt://somedir/overlay.db"}
|
||||
err := config.Run(ctx, nil)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "redis error: ping failed: dial tcp: address somedir: missing port in address", err.Error())
|
||||
|
||||
assert.Error(t, err)
|
||||
if !os.IsNotExist(errs.Unwrap(err)) {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.testName, c.testFunc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUrlPwd(t *testing.T) {
|
||||
res := GetUserPassword(nil)
|
||||
|
||||
assert.Equal(t, res, "")
|
||||
|
||||
uinfo := url.UserPassword("testUser", "testPassword")
|
||||
|
||||
uri := url.URL{User: uinfo}
|
||||
|
||||
res = GetUserPassword(&uri)
|
||||
|
||||
assert.Equal(t, res, "testPassword")
|
||||
// db scheme bolt conn fail
|
||||
err = Config{DatabaseURL: "bolt://somedir/overlay.db"}.Run(ctxWithKad, nil)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
@ -11,12 +11,17 @@ import (
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"storj.io/storj/internal/testcontext"
|
||||
"storj.io/storj/pkg/node"
|
||||
"storj.io/storj/pkg/pb"
|
||||
"storj.io/storj/storage"
|
||||
)
|
||||
|
||||
func TestFindStorageNodes(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
defer ctx.Cleanup()
|
||||
|
||||
lis, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
assert.NoError(t, err)
|
||||
|
||||
@ -51,6 +56,9 @@ func TestFindStorageNodes(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOverlayLookup(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
defer ctx.Cleanup()
|
||||
|
||||
lis, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
assert.NoError(t, err)
|
||||
|
||||
@ -77,6 +85,9 @@ func TestOverlayLookup(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOverlayBulkLookup(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
defer ctx.Cleanup()
|
||||
|
||||
lis, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
assert.NoError(t, err)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user