+5
-2
@@ -64,8 +64,11 @@ func (a *API) NetConnect(ctx context.Context, p peer.AddrInfo) error {
|
||||
return a.Host.Connect(ctx, p)
|
||||
}
|
||||
|
||||
func (a *API) NetAddrsListen(context.Context) (api.MultiaddrSlice, error) {
|
||||
return a.Host.Addrs(), nil
|
||||
func (a *API) NetAddrsListen(context.Context) (peer.AddrInfo, error) {
|
||||
return peer.AddrInfo{
|
||||
ID: a.Host.ID(),
|
||||
Addrs: a.Host.Addrs(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
var _ api.API = &API{}
|
||||
|
||||
+23
-19
@@ -68,7 +68,7 @@ const (
|
||||
_nInvokes // keep this last
|
||||
)
|
||||
|
||||
type settings struct {
|
||||
type Settings struct {
|
||||
// modules is a map of constructors for DI
|
||||
//
|
||||
// In most cases the index will be a reflect. Type of element returned by
|
||||
@@ -80,13 +80,13 @@ type settings struct {
|
||||
// type, and must be applied in correct order
|
||||
invokes []fx.Option
|
||||
|
||||
online bool // Online option applied
|
||||
config bool // Config option applied
|
||||
Online bool // Online option applied
|
||||
Config bool // Config option applied
|
||||
}
|
||||
|
||||
// Override option changes constructor for a given type
|
||||
func Override(typ, constructor interface{}) Option {
|
||||
return func(s *settings) error {
|
||||
return func(s *Settings) error {
|
||||
if i, ok := typ.(invoke); ok {
|
||||
s.invokes[i] = fx.Invoke(constructor)
|
||||
return nil
|
||||
@@ -106,18 +106,20 @@ func Override(typ, constructor interface{}) Option {
|
||||
|
||||
var defConf = config.Default()
|
||||
|
||||
var defaults = []Option{
|
||||
Override(new(helpers.MetricsCtx), context.Background),
|
||||
func defaults() []Option {
|
||||
return []Option{
|
||||
Override(new(helpers.MetricsCtx), context.Background),
|
||||
|
||||
randomIdentity(),
|
||||
randomIdentity(),
|
||||
|
||||
Override(new(datastore.Batching), testing.MapDatastore),
|
||||
Override(new(blockstore.Blockstore), testing.MapBlockstore), // NOT on top of ds above
|
||||
Override(new(record.Validator), modules.RecordValidator),
|
||||
Override(new(datastore.Batching), testing.MapDatastore),
|
||||
Override(new(blockstore.Blockstore), testing.MapBlockstore), // NOT on top of ds above
|
||||
Override(new(record.Validator), modules.RecordValidator),
|
||||
|
||||
// Filecoin modules
|
||||
// Filecoin modules
|
||||
|
||||
Override(new(*chain.ChainStore), chain.NewChainStore),
|
||||
Override(new(*chain.ChainStore), chain.NewChainStore),
|
||||
}
|
||||
}
|
||||
|
||||
// Online sets up basic libp2p node
|
||||
@@ -125,8 +127,8 @@ func Online() Option {
|
||||
return Options(
|
||||
// make sure that online is applied before Config.
|
||||
// This is important because Config overrides some of Online units
|
||||
func(s *settings) error { s.online = true; return nil },
|
||||
applyIf(func(s *settings) bool { return s.config },
|
||||
func(s *Settings) error { s.Online = true; return nil },
|
||||
ApplyIf(func(s *Settings) bool { return s.Config },
|
||||
Error(errors.New("the Online option must be set before Config option")),
|
||||
),
|
||||
|
||||
@@ -180,12 +182,12 @@ func Online() Option {
|
||||
)
|
||||
}
|
||||
|
||||
// Config sets up constructors based on the provided config
|
||||
// Config sets up constructors based on the provided Config
|
||||
func Config(cfg *config.Root) Option {
|
||||
return Options(
|
||||
func(s *settings) error { s.config = true; return nil },
|
||||
func(s *Settings) error { s.Config = true; return nil },
|
||||
|
||||
applyIf(func(s *settings) bool { return s.online },
|
||||
ApplyIf(func(s *Settings) bool { return s.Online },
|
||||
Override(StartListeningKey, lp2p.StartListening(cfg.Libp2p.ListenAddresses)),
|
||||
),
|
||||
)
|
||||
@@ -194,13 +196,13 @@ func Config(cfg *config.Root) Option {
|
||||
// New builds and starts new Filecoin node
|
||||
func New(ctx context.Context, opts ...Option) (api.API, error) {
|
||||
resAPI := &API{}
|
||||
settings := settings{
|
||||
settings := Settings{
|
||||
modules: map[interface{}]fx.Option{},
|
||||
invokes: make([]fx.Option, _nInvokes),
|
||||
}
|
||||
|
||||
// apply module options in the right order
|
||||
if err := Options(Options(defaults...), Options(opts...))(&settings); err != nil {
|
||||
if err := Options(Options(defaults()...), Options(opts...))(&settings); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -222,6 +224,8 @@ func New(ctx context.Context, opts ...Option) (api.API, error) {
|
||||
fx.Options(settings.invokes...),
|
||||
|
||||
fx.Extract(resAPI),
|
||||
|
||||
fx.NopLogger,
|
||||
)
|
||||
|
||||
// TODO: we probably should have a 'firewall' for Closing signal
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package node_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/filecoin-project/go-lotus/node"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/api"
|
||||
"github.com/filecoin-project/go-lotus/api/client"
|
||||
"github.com/filecoin-project/go-lotus/api/test"
|
||||
"github.com/filecoin-project/go-lotus/lib/jsonrpc"
|
||||
|
||||
mocknet "github.com/libp2p/go-libp2p/p2p/net/mock"
|
||||
)
|
||||
|
||||
func builder(t *testing.T, n int) []api.API {
|
||||
ctx := context.Background()
|
||||
mn := mocknet.New(ctx)
|
||||
|
||||
out := make([]api.API, n)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
var err error
|
||||
out[i], err = node.New(ctx,
|
||||
node.Online(),
|
||||
MockHost(mn),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := mn.LinkAll(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func TestAPI(t *testing.T) {
|
||||
test.TestApis(t, builder)
|
||||
}
|
||||
|
||||
var nextApi int
|
||||
|
||||
func rpcBuilder(t *testing.T, n int) []api.API {
|
||||
nodeApis := builder(t, n)
|
||||
out := make([]api.API, n)
|
||||
|
||||
for i, a := range nodeApis {
|
||||
rpcServer := jsonrpc.NewServer()
|
||||
rpcServer.Register("Filecoin", a)
|
||||
testServ := httptest.NewServer(rpcServer) // todo: close
|
||||
out[i] = client.NewRPC(testServ.URL)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func TestAPIRPC(t *testing.T) {
|
||||
test.TestApis(t, rpcBuilder)
|
||||
}
|
||||
+5
-5
@@ -8,11 +8,11 @@ import (
|
||||
// change how the node is constructed
|
||||
//
|
||||
// Options are applied in sequence
|
||||
type Option func(*settings) error
|
||||
type Option func(*Settings) error
|
||||
|
||||
// Options groups multiple options into one
|
||||
func Options(opts ...Option) Option {
|
||||
return func(s *settings) error {
|
||||
return func(s *Settings) error {
|
||||
for _, opt := range opts {
|
||||
if err := opt(s); err != nil {
|
||||
return err
|
||||
@@ -24,13 +24,13 @@ func Options(opts ...Option) Option {
|
||||
|
||||
// Error is a special option which returns an error when applied
|
||||
func Error(err error) Option {
|
||||
return func(_ *settings) error {
|
||||
return func(_ *Settings) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func applyIf(check func(s *settings) bool, opts ...Option) Option {
|
||||
return func(s *settings) error {
|
||||
func ApplyIf(check func(s *Settings) bool, opts ...Option) Option {
|
||||
return func(s *Settings) error {
|
||||
if check(s) {
|
||||
return Options(opts...)(s)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package node_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/filecoin-project/go-lotus/node"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/node/modules/lp2p"
|
||||
mocknet "github.com/libp2p/go-libp2p/p2p/net/mock"
|
||||
)
|
||||
|
||||
func MockHost(mn mocknet.Mocknet) node.Option {
|
||||
return node.Options(
|
||||
node.ApplyIf(func(s *node.Settings) bool { return !s.Online },
|
||||
node.Error(errors.New("MockHost must be specified after Online")),
|
||||
),
|
||||
|
||||
node.Override(new(lp2p.RawHost), lp2p.MockHost),
|
||||
node.Override(new(mocknet.Mocknet), mn),
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user