2018-06-29 21:06:25 +01:00
|
|
|
// Copyright (C) 2018 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
2018-07-06 20:43:53 +01:00
|
|
|
package pointerdb
|
2018-06-29 21:06:25 +01:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
2018-07-19 23:57:22 +01:00
|
|
|
"errors"
|
2018-06-29 21:06:25 +01:00
|
|
|
"testing"
|
2018-07-19 23:57:22 +01:00
|
|
|
"log"
|
|
|
|
"strings"
|
2018-06-29 21:06:25 +01:00
|
|
|
|
|
|
|
"github.com/golang/protobuf/proto"
|
2018-07-19 23:57:22 +01:00
|
|
|
"github.com/golang/mock/gomock"
|
|
|
|
"github.com/stretchr/testify/assert"
|
2018-06-29 21:06:25 +01:00
|
|
|
|
2018-07-06 20:43:53 +01:00
|
|
|
pb "storj.io/storj/protos/pointerdb"
|
2018-07-19 23:57:22 +01:00
|
|
|
p "storj.io/storj/pkg/paths"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
unauthenticated = "failed API creds"
|
|
|
|
noPathGiven = "file path not given"
|
|
|
|
noLimitGiven = "limit not given"
|
2018-06-29 21:06:25 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
ctx = context.Background()
|
2018-07-19 23:57:22 +01:00
|
|
|
ErrUnauthenticated = errors.New(unauthenticated)
|
|
|
|
ErrNoFileGiven = errors.New(noPathGiven)
|
|
|
|
ErrNoLimitGiven = errors.New(noLimitGiven)
|
2018-06-29 21:06:25 +01:00
|
|
|
)
|
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
func TestNewPointerDBClient(t *testing.T) {
|
|
|
|
// mocked grpcClient so we don't have
|
|
|
|
// to call the network to test the code
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
2018-06-29 21:06:25 +01:00
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
gc:= NewMockPointerDBClient(ctrl)
|
|
|
|
pdb := PointerDB{grpcClient: gc}
|
2018-06-29 21:06:25 +01:00
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
assert.NotNil(t, pdb)
|
|
|
|
assert.NotNil(t, pdb.grpcClient)
|
2018-06-29 21:06:25 +01:00
|
|
|
}
|
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
func makePointer(path p.Path, auth []byte) pb.PutRequest {
|
2018-06-29 21:06:25 +01:00
|
|
|
// rps is an example slice of RemotePieces to add to this
|
|
|
|
// REMOTE pointer type.
|
|
|
|
var rps []*pb.RemotePiece
|
|
|
|
rps = append(rps, &pb.RemotePiece{
|
|
|
|
PieceNum: int64(1),
|
|
|
|
NodeId: "testId",
|
|
|
|
})
|
|
|
|
pr := pb.PutRequest{
|
2018-07-19 23:57:22 +01:00
|
|
|
Path: path.Bytes(),
|
2018-06-29 21:06:25 +01:00
|
|
|
Pointer: &pb.Pointer{
|
|
|
|
Type: pb.Pointer_REMOTE,
|
|
|
|
Remote: &pb.RemoteSegment{
|
|
|
|
Redundancy: &pb.RedundancyScheme{
|
|
|
|
Type: pb.RedundancyScheme_RS,
|
|
|
|
MinReq: int64(1),
|
|
|
|
Total: int64(3),
|
|
|
|
RepairThreshold: int64(2),
|
|
|
|
SuccessThreshold: int64(3),
|
|
|
|
},
|
|
|
|
PieceId: "testId",
|
|
|
|
RemotePieces: rps,
|
|
|
|
},
|
|
|
|
Size: int64(1),
|
|
|
|
},
|
2018-07-19 23:57:22 +01:00
|
|
|
APIKey: auth,
|
2018-06-29 21:06:25 +01:00
|
|
|
}
|
|
|
|
return pr
|
|
|
|
}
|
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
func TestPut(t *testing.T){
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
|
|
|
|
for i, tt := range []struct {
|
|
|
|
APIKey []byte
|
|
|
|
path p.Path
|
|
|
|
err error
|
|
|
|
errString string
|
|
|
|
}{
|
|
|
|
{[]byte("abc123"), p.New("file1/file2"), nil, ""},
|
|
|
|
{[]byte("wrong key"), p.New("file1/file2"), ErrUnauthenticated,unauthenticated},
|
|
|
|
{[]byte("abc123"), p.New(""), ErrNoFileGiven, noPathGiven},
|
|
|
|
{[]byte("wrong key"), p.New(""), ErrUnauthenticated, unauthenticated},
|
|
|
|
{[]byte(""), p.New(""), ErrUnauthenticated, unauthenticated},
|
|
|
|
}{
|
|
|
|
putRequest:= makePointer(tt.path, tt.APIKey)
|
|
|
|
|
|
|
|
errTag := fmt.Sprintf("Test case #%d", i)
|
|
|
|
gc:= NewMockPointerDBClient(ctrl)
|
|
|
|
pdb := PointerDB{grpcClient: gc}
|
|
|
|
|
|
|
|
// here we don't care what type of context we pass
|
|
|
|
gc.EXPECT().Put(gomock.Any(), &putRequest).Return(nil, tt.err)
|
|
|
|
|
|
|
|
err := pdb.Put(ctx, tt.path, putRequest.Pointer, tt.APIKey)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
assert.EqualError(t, err, tt.errString, errTag)
|
|
|
|
} else {
|
|
|
|
assert.NoError(t, err, errTag)
|
|
|
|
}
|
2018-06-29 21:06:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
func TestGet(t *testing.T){
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
|
|
|
|
for i, tt := range []struct {
|
|
|
|
APIKey []byte
|
|
|
|
path p.Path
|
|
|
|
err error
|
|
|
|
errString string
|
|
|
|
}{
|
|
|
|
{[]byte("wrong key"), p.New("file1/file2"), ErrUnauthenticated,unauthenticated},
|
|
|
|
{[]byte("abc123"), p.New(""), ErrNoFileGiven, noPathGiven},
|
|
|
|
{[]byte("wrong key"), p.New(""), ErrUnauthenticated, unauthenticated},
|
|
|
|
{[]byte(""), p.New(""), ErrUnauthenticated, unauthenticated},
|
|
|
|
{[]byte("abc123"), p.New("file1/file2"), nil, ""},
|
|
|
|
}{
|
|
|
|
getPointer := makePointer(tt.path, tt.APIKey)
|
|
|
|
getRequest:= pb.GetRequest{Path: tt.path.Bytes(), APIKey: tt.APIKey}
|
|
|
|
|
|
|
|
data, err := proto.Marshal(getPointer.Pointer)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal("marshaling error: ", err)
|
|
|
|
}
|
2018-06-29 21:06:25 +01:00
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
byteData := []byte(data)
|
2018-06-29 21:06:25 +01:00
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
getResponse := pb.GetResponse{Pointer: byteData}
|
2018-06-29 21:06:25 +01:00
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
errTag := fmt.Sprintf("Test case #%d", i)
|
|
|
|
|
|
|
|
gc:= NewMockPointerDBClient(ctrl)
|
|
|
|
pdb := PointerDB{grpcClient: gc}
|
2018-06-29 21:06:25 +01:00
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
gc.EXPECT().Get(gomock.Any(), &getRequest).Return(&getResponse, tt.err)
|
2018-06-29 21:06:25 +01:00
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
pointer, err := pdb.Get(ctx, tt.path, tt.APIKey)
|
2018-06-29 21:06:25 +01:00
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
if err != nil {
|
|
|
|
assert.EqualError(t, err, tt.errString, errTag)
|
|
|
|
assert.Nil(t, pointer)
|
|
|
|
} else {
|
|
|
|
assert.NotNil(t, pointer)
|
|
|
|
assert.NoError(t, err, errTag)
|
|
|
|
}
|
2018-06-29 21:06:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
func TestList(t *testing.T){
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
|
|
|
|
for i, tt := range []struct {
|
|
|
|
APIKey []byte
|
|
|
|
startingPath p.Path
|
|
|
|
limit int64
|
|
|
|
truncated bool
|
|
|
|
paths []string
|
|
|
|
err error
|
|
|
|
errString string
|
|
|
|
}{
|
|
|
|
{[]byte("wrong key"), p.New(""), 2, true, []string{""}, ErrUnauthenticated, unauthenticated},
|
|
|
|
{[]byte("abc123"), p.New("file1"), 2, true, []string{"test"}, nil, ""},
|
|
|
|
{[]byte("abc123"), p.New(""), 2, true, []string{"file1/file2", "file3/file4", "file1", "file1/file2/great3", "test"}, ErrNoFileGiven, noPathGiven},
|
|
|
|
{[]byte("abc123"), p.New("file1"), 2, false, []string{""}, nil, ""},
|
|
|
|
{[]byte("wrong key"), p.New("file1"), 2, true, []string{"file1/file2", "file3/file4", "file1", "file1/file2/great3", "test"}, ErrUnauthenticated,unauthenticated},
|
|
|
|
{[]byte("abc123"), p.New("file1"), 3, true, []string{"file1/file2", "file3/file4", "file1", "file1/file2/great3", "test"}, nil, ""},
|
|
|
|
{[]byte("abc123"), p.New("file1"), 0, true, []string{"file1/file2", "file3/file4", "file1", "file1/file2/great3", "test"}, ErrNoLimitGiven, noLimitGiven},
|
|
|
|
}{
|
|
|
|
listRequest := pb.ListRequest{
|
|
|
|
StartingPathKey: tt.startingPath.Bytes(),
|
|
|
|
Limit: tt.limit,
|
|
|
|
APIKey: tt.APIKey,
|
|
|
|
}
|
2018-06-29 21:06:25 +01:00
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
var truncatedPathsBytes [][]byte
|
|
|
|
|
|
|
|
getCorrectPaths := func(fileName string) bool { return strings.HasPrefix(fileName, "file1")}
|
|
|
|
filterPaths := filterPathName(tt.paths, getCorrectPaths)
|
|
|
|
|
|
|
|
if len(filterPaths) == 0 {
|
|
|
|
truncatedPathsBytes = [][]byte{}
|
|
|
|
} else{
|
|
|
|
truncatedPaths := filterPaths[0:tt.limit]
|
|
|
|
truncatedPathsBytes := make([][]byte, len(truncatedPaths))
|
|
|
|
|
|
|
|
for i, pathName := range truncatedPaths {
|
|
|
|
bytePathName := []byte(pathName)
|
|
|
|
truncatedPathsBytes[i] = bytePathName
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
listResponse := pb.ListResponse{Paths: truncatedPathsBytes, Truncated: tt.truncated }
|
2018-06-29 21:06:25 +01:00
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
errTag := fmt.Sprintf("Test case #%d", i)
|
2018-06-29 21:06:25 +01:00
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
gc:= NewMockPointerDBClient(ctrl)
|
|
|
|
pdb := PointerDB{grpcClient: gc}
|
2018-06-29 21:06:25 +01:00
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
gc.EXPECT().List(gomock.Any(), &listRequest).Return(&listResponse, tt.err)
|
2018-06-29 21:06:25 +01:00
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
paths, trunc, err := pdb.List(ctx, tt.startingPath, tt.limit, tt.APIKey)
|
|
|
|
|
2018-06-29 21:06:25 +01:00
|
|
|
if err != nil {
|
2018-07-19 23:57:22 +01:00
|
|
|
assert.EqualError(t, err, tt.errString, errTag)
|
|
|
|
assert.NotNil(t, trunc)
|
|
|
|
assert.Nil(t, paths)
|
|
|
|
} else {
|
|
|
|
assert.NoError(t, err, errTag)
|
2018-06-29 21:06:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
func filterPathName(pathString []string, test func(string) bool) (filteredPathNames []string) {
|
|
|
|
for _, name := range pathString{
|
|
|
|
if test(name) {
|
|
|
|
filteredPathNames = append(filteredPathNames, name)
|
2018-06-29 21:06:25 +01:00
|
|
|
}
|
|
|
|
}
|
2018-07-19 23:57:22 +01:00
|
|
|
return
|
2018-06-29 21:06:25 +01:00
|
|
|
}
|
|
|
|
|
2018-07-19 23:57:22 +01:00
|
|
|
func TestDelete(t *testing.T){
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
|
|
|
|
for i, tt := range []struct {
|
|
|
|
APIKey []byte
|
|
|
|
path p.Path
|
|
|
|
err error
|
|
|
|
errString string
|
|
|
|
}{
|
|
|
|
{[]byte("wrong key"), p.New("file1/file2"), ErrUnauthenticated,unauthenticated},
|
|
|
|
{[]byte("abc123"), p.New(""), ErrNoFileGiven, noPathGiven},
|
|
|
|
{[]byte("wrong key"), p.New(""), ErrUnauthenticated, unauthenticated},
|
|
|
|
{[]byte(""), p.New(""), ErrUnauthenticated, unauthenticated},
|
|
|
|
{[]byte("abc123"), p.New("file1/file2"), nil, ""},
|
|
|
|
}{
|
|
|
|
deleteRequest:= pb.DeleteRequest{Path: tt.path.Bytes(), APIKey: tt.APIKey}
|
|
|
|
|
|
|
|
errTag := fmt.Sprintf("Test case #%d", i)
|
|
|
|
gc:= NewMockPointerDBClient(ctrl)
|
|
|
|
pdb := PointerDB{grpcClient: gc}
|
|
|
|
|
|
|
|
gc.EXPECT().Delete(gomock.Any(), &deleteRequest).Return(nil, tt.err)
|
|
|
|
|
|
|
|
err := pdb.Delete(ctx, tt.path, tt.APIKey)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
assert.EqualError(t, err, tt.errString, errTag)
|
|
|
|
} else {
|
|
|
|
assert.NoError(t, err, errTag)
|
|
|
|
}
|
2018-06-29 21:06:25 +01:00
|
|
|
}
|
|
|
|
}
|