244 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			244 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package test
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"fmt"
 | 
						|
	"os"
 | 
						|
	"testing"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/filecoin-project/lotus/chain/stmgr"
 | 
						|
	"github.com/filecoin-project/lotus/chain/types"
 | 
						|
 | 
						|
	logging "github.com/ipfs/go-log/v2"
 | 
						|
	"github.com/multiformats/go-multiaddr"
 | 
						|
 | 
						|
	"github.com/stretchr/testify/assert"
 | 
						|
	"github.com/stretchr/testify/require"
 | 
						|
 | 
						|
	"github.com/filecoin-project/go-state-types/abi"
 | 
						|
	"github.com/filecoin-project/go-state-types/big"
 | 
						|
	"github.com/filecoin-project/go-state-types/network"
 | 
						|
	"github.com/filecoin-project/lotus/api"
 | 
						|
	"github.com/filecoin-project/lotus/build"
 | 
						|
	"github.com/filecoin-project/lotus/miner"
 | 
						|
	"github.com/filecoin-project/lotus/node"
 | 
						|
)
 | 
						|
 | 
						|
func init() {
 | 
						|
	logging.SetAllLoggers(logging.LevelInfo)
 | 
						|
	err := os.Setenv("BELLMAN_NO_GPU", "1")
 | 
						|
	if err != nil {
 | 
						|
		panic(fmt.Sprintf("failed to set BELLMAN_NO_GPU env variable: %s", err))
 | 
						|
	}
 | 
						|
	build.InsecurePoStValidation = true
 | 
						|
}
 | 
						|
 | 
						|
type TestNode struct {
 | 
						|
	api.FullNode
 | 
						|
	// ListenAddr is the address on which an API server is listening, if an
 | 
						|
	// API server is created for this Node
 | 
						|
	ListenAddr multiaddr.Multiaddr
 | 
						|
}
 | 
						|
 | 
						|
type TestStorageNode struct {
 | 
						|
	api.StorageMiner
 | 
						|
	// ListenAddr is the address on which an API server is listening, if an
 | 
						|
	// API server is created for this Node
 | 
						|
	ListenAddr multiaddr.Multiaddr
 | 
						|
 | 
						|
	MineOne func(context.Context, miner.MineReq) error
 | 
						|
}
 | 
						|
 | 
						|
var PresealGenesis = -1
 | 
						|
 | 
						|
const GenesisPreseals = 2
 | 
						|
 | 
						|
// Options for setting up a mock storage miner
 | 
						|
type StorageMiner struct {
 | 
						|
	Full    int
 | 
						|
	Preseal int
 | 
						|
}
 | 
						|
 | 
						|
type OptionGenerator func([]TestNode) node.Option
 | 
						|
 | 
						|
// Options for setting up a mock full node
 | 
						|
type FullNodeOpts struct {
 | 
						|
	Lite bool            // run node in "lite" mode
 | 
						|
	Opts OptionGenerator // generate dependency injection options
 | 
						|
}
 | 
						|
 | 
						|
// APIBuilder is a function which is invoked in test suite to provide
 | 
						|
// test nodes and networks
 | 
						|
//
 | 
						|
// fullOpts array defines options for each full node
 | 
						|
// storage array defines storage nodes, numbers in the array specify full node
 | 
						|
// index the storage node 'belongs' to
 | 
						|
type APIBuilder func(t *testing.T, full []FullNodeOpts, storage []StorageMiner) ([]TestNode, []TestStorageNode)
 | 
						|
type testSuite struct {
 | 
						|
	makeNodes APIBuilder
 | 
						|
}
 | 
						|
 | 
						|
// TestApis is the entry point to API test suite
 | 
						|
func TestApis(t *testing.T, b APIBuilder) {
 | 
						|
	ts := testSuite{
 | 
						|
		makeNodes: b,
 | 
						|
	}
 | 
						|
 | 
						|
	t.Run("version", ts.testVersion)
 | 
						|
	t.Run("id", ts.testID)
 | 
						|
	t.Run("testConnectTwo", ts.testConnectTwo)
 | 
						|
	t.Run("testMining", ts.testMining)
 | 
						|
	t.Run("testMiningReal", ts.testMiningReal)
 | 
						|
	t.Run("testSearchMsg", ts.testSearchMsg)
 | 
						|
}
 | 
						|
 | 
						|
func DefaultFullOpts(nFull int) []FullNodeOpts {
 | 
						|
	full := make([]FullNodeOpts, nFull)
 | 
						|
	for i := range full {
 | 
						|
		full[i] = FullNodeOpts{
 | 
						|
			Opts: func(nodes []TestNode) node.Option {
 | 
						|
				return node.Options()
 | 
						|
			},
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return full
 | 
						|
}
 | 
						|
 | 
						|
var OneMiner = []StorageMiner{{Full: 0, Preseal: PresealGenesis}}
 | 
						|
var OneFull = DefaultFullOpts(1)
 | 
						|
var TwoFull = DefaultFullOpts(2)
 | 
						|
 | 
						|
var FullNodeWithUpgradeAt = func(upgradeHeight abi.ChainEpoch) FullNodeOpts {
 | 
						|
	return FullNodeOpts{
 | 
						|
		Opts: func(nodes []TestNode) node.Option {
 | 
						|
			return node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
 | 
						|
				// Skip directly to tape height so precommits work.
 | 
						|
				Network:   network.Version5,
 | 
						|
				Height:    upgradeHeight,
 | 
						|
				Migration: stmgr.UpgradeActorsV2,
 | 
						|
			}})
 | 
						|
		},
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
var MineNext = miner.MineReq{
 | 
						|
	InjectNulls: 0,
 | 
						|
	Done:        func(bool, abi.ChainEpoch, error) {},
 | 
						|
}
 | 
						|
 | 
						|
func (ts *testSuite) testVersion(t *testing.T) {
 | 
						|
	build.RunningNodeType = build.NodeFull
 | 
						|
 | 
						|
	ctx := context.Background()
 | 
						|
	apis, _ := ts.makeNodes(t, OneFull, OneMiner)
 | 
						|
	api := apis[0]
 | 
						|
 | 
						|
	v, err := api.Version(ctx)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	require.Equal(t, v.Version, build.BuildVersion)
 | 
						|
}
 | 
						|
 | 
						|
func (ts *testSuite) testSearchMsg(t *testing.T) {
 | 
						|
	apis, miners := ts.makeNodes(t, OneFull, OneMiner)
 | 
						|
 | 
						|
	api := apis[0]
 | 
						|
	ctx, cancel := context.WithCancel(context.Background())
 | 
						|
	defer cancel()
 | 
						|
	senderAddr, err := api.WalletDefaultAddress(ctx)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
 | 
						|
	msg := &types.Message{
 | 
						|
		From:  senderAddr,
 | 
						|
		To:    senderAddr,
 | 
						|
		Value: big.Zero(),
 | 
						|
	}
 | 
						|
	bm := NewBlockMiner(ctx, t, miners[0], 100*time.Millisecond)
 | 
						|
	bm.MineBlocks()
 | 
						|
	defer bm.Stop()
 | 
						|
 | 
						|
	sm, err := api.MpoolPushMessage(ctx, msg, nil)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	res, err := api.StateWaitMsg(ctx, sm.Cid(), 1)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	if res.Receipt.ExitCode != 0 {
 | 
						|
		t.Fatal("did not successfully send message")
 | 
						|
	}
 | 
						|
 | 
						|
	searchRes, err := api.StateSearchMsg(ctx, sm.Cid())
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
 | 
						|
	if searchRes.TipSet != res.TipSet {
 | 
						|
		t.Fatalf("search ts: %s, different from wait ts: %s", searchRes.TipSet, res.TipSet)
 | 
						|
	}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
func (ts *testSuite) testID(t *testing.T) {
 | 
						|
	ctx := context.Background()
 | 
						|
	apis, _ := ts.makeNodes(t, OneFull, OneMiner)
 | 
						|
	api := apis[0]
 | 
						|
 | 
						|
	id, err := api.ID(ctx)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	assert.Regexp(t, "^12", id.Pretty())
 | 
						|
}
 | 
						|
 | 
						|
func (ts *testSuite) testConnectTwo(t *testing.T) {
 | 
						|
	ctx := context.Background()
 | 
						|
	apis, _ := ts.makeNodes(t, TwoFull, OneMiner)
 | 
						|
 | 
						|
	p, err := apis[0].NetPeers(ctx)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	if len(p) != 0 {
 | 
						|
		t.Error("Node 0 has a peer")
 | 
						|
	}
 | 
						|
 | 
						|
	p, err = apis[1].NetPeers(ctx)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	if len(p) != 0 {
 | 
						|
		t.Error("Node 1 has a peer")
 | 
						|
	}
 | 
						|
 | 
						|
	addrs, err := apis[1].NetAddrsListen(ctx)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
 | 
						|
	if err := apis[0].NetConnect(ctx, addrs); err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
 | 
						|
	p, err = apis[0].NetPeers(ctx)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	if len(p) != 1 {
 | 
						|
		t.Error("Node 0 doesn't have 1 peer")
 | 
						|
	}
 | 
						|
 | 
						|
	p, err = apis[1].NetPeers(ctx)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	if len(p) != 1 {
 | 
						|
		t.Error("Node 0 doesn't have 1 peer")
 | 
						|
	}
 | 
						|
}
 |