testcontext package (#545)

This commit is contained in:
Egon Elbre 2018-10-29 16:16:36 +02:00 committed by GitHub
parent 68796d7964
commit 47d056d627
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 146 additions and 31 deletions

1
go.mod
View File

@ -112,6 +112,7 @@ require (
github.com/prometheus/client_golang v0.9.0-pre1.0.20180416233856-82f5ff156b29 // indirect
github.com/segmentio/go-prompt v1.2.1-0.20161017233205-f0d19b6901ad // indirect
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f
)
exclude gopkg.in/olivere/elastic.v5 v5.0.72 // buggy import, see https://github.com/olivere/elastic/pull/869

View File

@ -1,22 +0,0 @@
// Copyright (C) 2018 Storj Labs, Inc.
// See LICENSE for copying information.
package test
import (
"testing"
"github.com/gogo/protobuf/proto"
"github.com/stretchr/testify/assert"
"storj.io/storj/pkg/pb"
"storj.io/storj/storage"
)
// NewNodeStorageValue provides a convient way to create a node as a storage.Value for testing purposes
func NewNodeStorageValue(t *testing.T, address string) storage.Value {
na := &pb.Node{Id: "", Address: &pb.NodeAddress{Transport: pb.NodeTransport_TCP_TLS_GRPC, Address: address}}
d, err := proto.Marshal(na)
assert.NoError(t, err)
return d
}

View File

@ -0,0 +1,100 @@
// Copyright (C) 2018 Storj Labs, Inc.
// See LICENSE for copying information.
package testcontext
import (
"context"
"io/ioutil"
"os"
"path/filepath"
"sync"
"testing"
"golang.org/x/sync/errgroup"
)
// Context is a context that has utility methods for testing and waiting for asynchronous errors.
type Context struct {
context.Context
group *errgroup.Group
test testing.TB
once sync.Once
directory string
}
// New creates a new test context
func New(test testing.TB) *Context {
group, ctx := errgroup.WithContext(context.Background())
return &Context{
Context: ctx,
group: group,
test: test,
}
}
// Go runs fn in a goroutine.
// Call Wait to check the result
func (ctx *Context) Go(fn func() error) {
ctx.test.Helper()
ctx.group.Go(fn)
}
// Check calls fn and checks result
func (ctx *Context) Check(fn func() error) {
ctx.test.Helper()
err := fn()
if err != nil {
ctx.test.Fatal(err)
}
}
// Dir returns a directory path inside temp
func (ctx *Context) Dir(subs ...string) string {
ctx.test.Helper()
ctx.once.Do(func() {
var err error
ctx.directory, err = ioutil.TempDir("", ctx.test.Name())
if err != nil {
ctx.test.Fatal(err)
}
})
dir := filepath.Join(append([]string{ctx.directory}, subs...)...)
_ = os.MkdirAll(dir, 0644)
return dir
}
// File returns a filepath inside temp
func (ctx *Context) File(subs ...string) string {
ctx.test.Helper()
if len(subs) == 0 {
ctx.test.Fatal("expected more than one argument")
}
dir := ctx.Dir(subs[:len(subs)-1]...)
return filepath.Join(dir, subs[len(subs)-1])
}
// Cleanup waits everything to be completed,
// checks errors and tries to cleanup directories
func (ctx *Context) Cleanup() {
ctx.test.Helper()
defer ctx.deleteTemporary()
err := ctx.group.Wait()
if err != nil {
ctx.test.Fatal(err)
}
}
// deleteTemporary tries to delete temporary directory
func (ctx *Context) deleteTemporary() {
err := os.RemoveAll(ctx.directory)
if err != nil {
ctx.test.Fatal(err)
}
}

View File

@ -0,0 +1,21 @@
package testcontext_test
import (
"testing"
"time"
"storj.io/storj/internal/testcontext"
)
func TestBasic(t *testing.T) {
ctx := testcontext.New(t)
defer ctx.Cleanup()
ctx.Go(func() error {
time.Sleep(time.Millisecond)
return nil
})
t.Log(ctx.Dir("a", "b", "c"))
t.Log(ctx.File("a", "w", "c.txt"))
}

View File

@ -12,6 +12,7 @@ import (
"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
"storj.io/storj/internal/testcontext"
"storj.io/storj/pkg/dht/mocks"
"storj.io/storj/pkg/pb"
"storj.io/storj/pkg/provider"
@ -20,6 +21,9 @@ import (
var ctx = context.Background()
func TestLookup(t *testing.T) {
ctx := testcontext.New(t)
defer ctx.Cleanup()
cases := []struct {
self pb.Node
to pb.Node
@ -43,8 +47,10 @@ func TestLookup(t *testing.T) {
id := newTestIdentity(t)
srv, mock, err := newTestServer(ctx, &mockNodeServer{queryCalled: 0}, id)
assert.NoError(t, err)
go func() { assert.NoError(t, srv.Serve(lis)) }()
ctx.Go(func() error { return srv.Serve(lis) })
defer srv.Stop()
ctrl := gomock.NewController(t)
mdht := mock_dht.NewMockDHT(ctrl)
@ -68,7 +74,9 @@ func TestLookup(t *testing.T) {
}
func TestPing(t *testing.T) {
ctx := context.Background()
ctx := testcontext.New(t)
defer ctx.Cleanup()
cases := []struct {
self pb.Node
toID string
@ -96,7 +104,7 @@ func TestPing(t *testing.T) {
assert.NoError(t, err)
// start gRPC server
go func() { assert.NoError(t, msrv.Serve(lis)) }()
ctx.Go(func() error { return msrv.Serve(lis) })
defer msrv.Stop()
nc, err := NewNodeClient(v.toIdentity, v.self, mdht)
@ -116,7 +124,6 @@ func newTestServer(ctx context.Context, ns pb.NodesServer, identity *provider.Fu
}
grpcServer := grpc.NewServer(identOpt)
pb.RegisterNodesServer(grpcServer, ns)
return grpcServer, ns, nil

View File

@ -8,10 +8,10 @@ import (
"net"
"testing"
"github.com/gogo/protobuf/proto"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
"storj.io/storj/internal/test"
"storj.io/storj/pkg/node"
"storj.io/storj/pkg/pb"
"storj.io/storj/storage"
@ -29,10 +29,10 @@ func TestFindStorageNodes(t *testing.T) {
srv := NewMockServer([]storage.ListItem{
{
Key: storage.Key(fid.ID.String()),
Value: test.NewNodeStorageValue(t, "127.0.0.1:9090"),
Value: newNodeStorageValue(t, "127.0.0.1:9090"),
}, {
Key: storage.Key(fid2.ID.String()),
Value: test.NewNodeStorageValue(t, "127.0.0.1:9090"),
Value: newNodeStorageValue(t, "127.0.0.1:9090"),
},
})
assert.NotNil(t, srv)
@ -62,7 +62,7 @@ func TestOverlayLookup(t *testing.T) {
srv := NewMockServer([]storage.ListItem{
{
Key: storage.Key(fid.ID.String()),
Value: test.NewNodeStorageValue(t, "127.0.0.1:9090"),
Value: newNodeStorageValue(t, "127.0.0.1:9090"),
},
})
go func() { assert.NoError(t, srv.Serve(lis)) }()
@ -89,7 +89,7 @@ func TestOverlayBulkLookup(t *testing.T) {
srv := NewMockServer([]storage.ListItem{
{
Key: storage.Key(fid.ID.String()),
Value: test.NewNodeStorageValue(t, "127.0.0.1:9090"),
Value: newNodeStorageValue(t, "127.0.0.1:9090"),
},
})
go func() { assert.NoError(t, srv.Serve(lis)) }()
@ -106,3 +106,11 @@ func TestOverlayBulkLookup(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, r)
}
// newNodeStorageValue provides a convient way to create a node as a storage.Value for testing purposes
func newNodeStorageValue(t *testing.T, address string) storage.Value {
na := &pb.Node{Id: "", Address: &pb.NodeAddress{Transport: pb.NodeTransport_TCP_TLS_GRPC, Address: address}}
d, err := proto.Marshal(na)
assert.NoError(t, err)
return d
}