2019-06-29 09:19:06 +00:00
|
|
|
package test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2020-10-21 23:52:13 +00:00
|
|
|
"fmt"
|
|
|
|
"os"
|
2021-01-22 04:07:07 +00:00
|
|
|
"strings"
|
2019-06-29 09:19:06 +00:00
|
|
|
"testing"
|
2020-10-13 16:25:49 +00:00
|
|
|
"time"
|
2019-06-29 09:19:06 +00:00
|
|
|
|
2020-10-21 23:52:13 +00:00
|
|
|
logging "github.com/ipfs/go-log/v2"
|
2020-08-13 20:37:09 +00:00
|
|
|
"github.com/multiformats/go-multiaddr"
|
|
|
|
|
2020-06-01 19:11:37 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
2021-04-23 12:29:46 +00:00
|
|
|
"github.com/filecoin-project/go-address"
|
2020-10-08 10:21:15 +00:00
|
|
|
"github.com/filecoin-project/go-state-types/abi"
|
2020-10-13 16:25:49 +00:00
|
|
|
"github.com/filecoin-project/go-state-types/big"
|
2020-10-12 06:31:23 +00:00
|
|
|
"github.com/filecoin-project/go-state-types/network"
|
2021-04-23 12:29:46 +00:00
|
|
|
|
2021-04-05 19:34:03 +00:00
|
|
|
lapi "github.com/filecoin-project/lotus/api"
|
2021-04-27 06:13:49 +00:00
|
|
|
"github.com/filecoin-project/lotus/api/v1api"
|
2019-10-18 04:47:41 +00:00
|
|
|
"github.com/filecoin-project/lotus/build"
|
2021-04-23 12:29:46 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
2020-07-28 16:16:46 +00:00
|
|
|
"github.com/filecoin-project/lotus/miner"
|
2020-10-01 22:26:00 +00:00
|
|
|
"github.com/filecoin-project/lotus/node"
|
2019-06-29 09:19:06 +00:00
|
|
|
)
|
|
|
|
|
2020-10-21 23:52:13 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2021-04-23 12:29:46 +00:00
|
|
|
type StorageBuilder func(context.Context, *testing.T, abi.RegisteredSealProof, address.Address) TestStorageNode
|
|
|
|
|
2019-09-23 15:27:30 +00:00
|
|
|
type TestNode struct {
|
2021-04-05 17:56:53 +00:00
|
|
|
v1api.FullNode
|
2020-08-13 20:37:09 +00:00
|
|
|
// ListenAddr is the address on which an API server is listening, if an
|
|
|
|
// API server is created for this Node
|
|
|
|
ListenAddr multiaddr.Multiaddr
|
2021-04-23 12:29:46 +00:00
|
|
|
|
|
|
|
Stb StorageBuilder
|
2019-09-23 15:27:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type TestStorageNode struct {
|
2021-04-05 19:34:03 +00:00
|
|
|
lapi.StorageMiner
|
2020-08-13 20:37:09 +00:00
|
|
|
// ListenAddr is the address on which an API server is listening, if an
|
|
|
|
// API server is created for this Node
|
|
|
|
ListenAddr multiaddr.Multiaddr
|
2019-11-30 23:17:50 +00:00
|
|
|
|
2020-07-28 16:16:46 +00:00
|
|
|
MineOne func(context.Context, miner.MineReq) error
|
2021-01-22 03:48:34 +00:00
|
|
|
Stop func(context.Context) error
|
2019-09-23 15:27:30 +00:00
|
|
|
}
|
|
|
|
|
2020-04-23 17:50:52 +00:00
|
|
|
var PresealGenesis = -1
|
2020-06-01 18:11:55 +00:00
|
|
|
|
2020-06-01 12:49:48 +00:00
|
|
|
const GenesisPreseals = 2
|
2020-04-23 17:50:52 +00:00
|
|
|
|
2021-04-23 12:29:46 +00:00
|
|
|
const TestSpt = abi.RegisteredSealProof_StackedDrg2KiBV1_1
|
|
|
|
|
2020-10-08 09:24:31 +00:00
|
|
|
// Options for setting up a mock storage miner
|
2020-04-23 17:50:52 +00:00
|
|
|
type StorageMiner struct {
|
|
|
|
Full int
|
2021-01-08 15:28:38 +00:00
|
|
|
Opts node.Option
|
2020-04-23 17:50:52 +00:00
|
|
|
Preseal int
|
|
|
|
}
|
|
|
|
|
2020-10-07 09:26:15 +00:00
|
|
|
type OptionGenerator func([]TestNode) node.Option
|
|
|
|
|
2020-10-08 09:24:31 +00:00
|
|
|
// Options for setting up a mock full node
|
|
|
|
type FullNodeOpts struct {
|
|
|
|
Lite bool // run node in "lite" mode
|
|
|
|
Opts OptionGenerator // generate dependency injection options
|
|
|
|
}
|
|
|
|
|
2019-07-02 13:05:43 +00:00
|
|
|
// APIBuilder is a function which is invoked in test suite to provide
|
|
|
|
// test nodes and networks
|
2019-09-23 15:27:30 +00:00
|
|
|
//
|
2020-10-08 09:24:31 +00:00
|
|
|
// fullOpts array defines options for each full node
|
2019-09-23 15:27:30 +00:00
|
|
|
// storage array defines storage nodes, numbers in the array specify full node
|
|
|
|
// index the storage node 'belongs' to
|
2020-10-08 10:21:15 +00:00
|
|
|
type APIBuilder func(t *testing.T, full []FullNodeOpts, storage []StorageMiner) ([]TestNode, []TestStorageNode)
|
2019-06-29 09:19:06 +00:00
|
|
|
type testSuite struct {
|
2019-07-09 16:27:07 +00:00
|
|
|
makeNodes APIBuilder
|
2019-06-29 09:19:06 +00:00
|
|
|
}
|
|
|
|
|
2019-07-02 13:05:43 +00:00
|
|
|
// TestApis is the entry point to API test suite
|
2019-07-02 12:40:25 +00:00
|
|
|
func TestApis(t *testing.T, b APIBuilder) {
|
2019-06-29 09:19:06 +00:00
|
|
|
ts := testSuite{
|
2019-07-09 16:27:07 +00:00
|
|
|
makeNodes: b,
|
2019-06-29 09:19:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
t.Run("version", ts.testVersion)
|
2019-07-09 17:03:36 +00:00
|
|
|
t.Run("id", ts.testID)
|
|
|
|
t.Run("testConnectTwo", ts.testConnectTwo)
|
2019-09-23 15:27:30 +00:00
|
|
|
t.Run("testMining", ts.testMining)
|
2020-04-30 22:24:58 +00:00
|
|
|
t.Run("testMiningReal", ts.testMiningReal)
|
2020-10-13 16:25:49 +00:00
|
|
|
t.Run("testSearchMsg", ts.testSearchMsg)
|
2021-04-23 12:29:46 +00:00
|
|
|
t.Run("testNonGenesisMiner", ts.testNonGenesisMiner)
|
2019-06-29 09:19:06 +00:00
|
|
|
}
|
|
|
|
|
2020-10-08 09:24:31 +00:00
|
|
|
func DefaultFullOpts(nFull int) []FullNodeOpts {
|
|
|
|
full := make([]FullNodeOpts, nFull)
|
2020-10-07 09:26:15 +00:00
|
|
|
for i := range full {
|
2020-10-08 09:24:31 +00:00
|
|
|
full[i] = FullNodeOpts{
|
|
|
|
Opts: func(nodes []TestNode) node.Option {
|
|
|
|
return node.Options()
|
|
|
|
},
|
2020-10-07 09:26:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return full
|
|
|
|
}
|
|
|
|
|
2020-08-13 20:37:09 +00:00
|
|
|
var OneMiner = []StorageMiner{{Full: 0, Preseal: PresealGenesis}}
|
2020-10-07 09:26:15 +00:00
|
|
|
var OneFull = DefaultFullOpts(1)
|
|
|
|
var TwoFull = DefaultFullOpts(2)
|
2020-04-23 17:50:52 +00:00
|
|
|
|
2021-04-26 14:48:20 +00:00
|
|
|
var FullNodeWithLatestActorsAt = func(upgradeHeight abi.ChainEpoch) FullNodeOpts {
|
2021-04-23 12:29:46 +00:00
|
|
|
if upgradeHeight == -1 {
|
2021-05-06 05:44:11 +00:00
|
|
|
// Attention: Update this when introducing new actor versions or your tests will be sad
|
|
|
|
upgradeHeight = 4
|
2021-04-23 12:29:46 +00:00
|
|
|
}
|
|
|
|
|
2020-10-08 10:21:15 +00:00
|
|
|
return FullNodeOpts{
|
|
|
|
Opts: func(nodes []TestNode) node.Option {
|
|
|
|
return node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
|
2021-01-21 18:00:35 +00:00
|
|
|
// prepare for upgrade.
|
|
|
|
Network: network.Version9,
|
|
|
|
Height: 1,
|
|
|
|
Migration: stmgr.UpgradeActorsV2,
|
|
|
|
}, {
|
|
|
|
Network: network.Version10,
|
2021-04-23 12:29:46 +00:00
|
|
|
Height: 2,
|
2021-01-21 18:00:35 +00:00
|
|
|
Migration: stmgr.UpgradeActorsV3,
|
2021-04-23 12:29:46 +00:00
|
|
|
}, {
|
|
|
|
Network: network.Version12,
|
2021-05-06 05:44:11 +00:00
|
|
|
Height: 3,
|
2021-04-23 12:29:46 +00:00
|
|
|
Migration: stmgr.UpgradeActorsV4,
|
2021-05-06 05:44:11 +00:00
|
|
|
}, {
|
|
|
|
Network: network.Version13,
|
|
|
|
Height: upgradeHeight,
|
|
|
|
Migration: stmgr.UpgradeActorsV5,
|
2020-10-08 10:21:15 +00:00
|
|
|
}})
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-12 22:43:27 +00:00
|
|
|
var FullNodeWithSDRAt = func(calico, persian abi.ChainEpoch) FullNodeOpts {
|
2020-11-06 18:01:09 +00:00
|
|
|
return FullNodeOpts{
|
|
|
|
Opts: func(nodes []TestNode) node.Option {
|
|
|
|
return node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
|
|
|
|
Network: network.Version6,
|
|
|
|
Height: 1,
|
|
|
|
Migration: stmgr.UpgradeActorsV2,
|
|
|
|
}, {
|
|
|
|
Network: network.Version7,
|
2020-11-12 22:43:27 +00:00
|
|
|
Height: calico,
|
2020-11-06 18:01:09 +00:00
|
|
|
Migration: stmgr.UpgradeCalico,
|
2020-11-12 22:43:27 +00:00
|
|
|
}, {
|
|
|
|
Network: network.Version8,
|
|
|
|
Height: persian,
|
2020-11-06 18:01:09 +00:00
|
|
|
}})
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-25 19:27:32 +00:00
|
|
|
var FullNodeWithV4ActorsAt = func(upgradeHeight abi.ChainEpoch) FullNodeOpts {
|
|
|
|
if upgradeHeight == -1 {
|
|
|
|
upgradeHeight = 3
|
|
|
|
}
|
|
|
|
|
|
|
|
return FullNodeOpts{
|
|
|
|
Opts: func(nodes []TestNode) node.Option {
|
|
|
|
return node.Override(new(stmgr.UpgradeSchedule), stmgr.UpgradeSchedule{{
|
|
|
|
// prepare for upgrade.
|
|
|
|
Network: network.Version9,
|
|
|
|
Height: 1,
|
|
|
|
Migration: stmgr.UpgradeActorsV2,
|
|
|
|
}, {
|
|
|
|
Network: network.Version10,
|
|
|
|
Height: 2,
|
|
|
|
Migration: stmgr.UpgradeActorsV3,
|
|
|
|
}, {
|
|
|
|
Network: network.Version12,
|
|
|
|
Height: upgradeHeight,
|
|
|
|
Migration: stmgr.UpgradeActorsV4,
|
|
|
|
}})
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-21 23:52:13 +00:00
|
|
|
var MineNext = miner.MineReq{
|
|
|
|
InjectNulls: 0,
|
|
|
|
Done: func(bool, abi.ChainEpoch, error) {},
|
|
|
|
}
|
|
|
|
|
2019-06-29 09:19:06 +00:00
|
|
|
func (ts *testSuite) testVersion(t *testing.T) {
|
2021-04-05 19:34:03 +00:00
|
|
|
lapi.RunningNodeType = lapi.NodeFull
|
2021-04-23 12:29:46 +00:00
|
|
|
t.Cleanup(func() {
|
2021-04-27 06:13:49 +00:00
|
|
|
lapi.RunningNodeType = lapi.NodeUnknown
|
2021-04-23 12:29:46 +00:00
|
|
|
})
|
2020-09-08 18:54:37 +00:00
|
|
|
|
2019-06-29 09:19:06 +00:00
|
|
|
ctx := context.Background()
|
2020-10-07 09:26:15 +00:00
|
|
|
apis, _ := ts.makeNodes(t, OneFull, OneMiner)
|
2021-03-05 21:01:20 +00:00
|
|
|
napi := apis[0]
|
2019-06-29 09:19:06 +00:00
|
|
|
|
2021-03-05 21:01:20 +00:00
|
|
|
v, err := napi.Version(ctx)
|
2019-06-29 09:19:06 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2021-01-22 04:07:07 +00:00
|
|
|
versions := strings.Split(v.Version, "+")
|
|
|
|
if len(versions) <= 0 {
|
|
|
|
t.Fatal("empty version")
|
|
|
|
}
|
|
|
|
require.Equal(t, versions[0], build.BuildVersion)
|
2020-10-13 16:25:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
2021-04-05 19:34:03 +00:00
|
|
|
res, err := api.StateWaitMsg(ctx, sm.Cid(), 1, lapi.LookbackNoLimit, true)
|
2020-10-13 16:25:49 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if res.Receipt.ExitCode != 0 {
|
|
|
|
t.Fatal("did not successfully send message")
|
|
|
|
}
|
|
|
|
|
2021-04-05 19:34:03 +00:00
|
|
|
searchRes, err := api.StateSearchMsg(ctx, types.EmptyTSK, sm.Cid(), lapi.LookbackNoLimit, true)
|
2020-10-13 16:25:49 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2019-06-29 09:19:06 +00:00
|
|
|
}
|
2019-07-09 17:03:36 +00:00
|
|
|
|
|
|
|
func (ts *testSuite) testID(t *testing.T) {
|
|
|
|
ctx := context.Background()
|
2020-10-07 09:26:15 +00:00
|
|
|
apis, _ := ts.makeNodes(t, OneFull, OneMiner)
|
2019-09-23 15:27:30 +00:00
|
|
|
api := apis[0]
|
2019-07-09 17:03:36 +00:00
|
|
|
|
|
|
|
id, err := api.ID(ctx)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2019-07-18 15:52:48 +00:00
|
|
|
assert.Regexp(t, "^12", id.Pretty())
|
2019-07-09 17:03:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (ts *testSuite) testConnectTwo(t *testing.T) {
|
|
|
|
ctx := context.Background()
|
2020-10-07 09:26:15 +00:00
|
|
|
apis, _ := ts.makeNodes(t, TwoFull, OneMiner)
|
2019-07-09 17:03:36 +00:00
|
|
|
|
|
|
|
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")
|
|
|
|
}
|
|
|
|
}
|