Merge remote-tracking branch 'origin/master' into feat/async-restartable-workers
This commit is contained in:
+106
-4
@@ -84,6 +84,7 @@ var clientCmd = &cli.Command{
|
||||
WithCategory("data", clientImportCmd),
|
||||
WithCategory("data", clientDropCmd),
|
||||
WithCategory("data", clientLocalCmd),
|
||||
WithCategory("data", clientStat),
|
||||
WithCategory("retrieval", clientFindCmd),
|
||||
WithCategory("retrieval", clientRetrieveCmd),
|
||||
WithCategory("util", clientCommPCmd),
|
||||
@@ -91,6 +92,7 @@ var clientCmd = &cli.Command{
|
||||
WithCategory("util", clientInfoCmd),
|
||||
WithCategory("util", clientListTransfers),
|
||||
WithCategory("util", clientRestartTransfer),
|
||||
WithCategory("util", clientCancelTransfer),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1638,6 +1640,39 @@ var clientInfoCmd = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
var clientStat = &cli.Command{
|
||||
Name: "stat",
|
||||
Usage: "Print information about a locally stored file (piece size, etc)",
|
||||
ArgsUsage: "<cid>",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
if !cctx.Args().Present() || cctx.NArg() != 1 {
|
||||
return fmt.Errorf("must specify cid of data")
|
||||
}
|
||||
|
||||
dataCid, err := cid.Parse(cctx.Args().First())
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing data cid: %w", err)
|
||||
}
|
||||
|
||||
ds, err := api.ClientDealSize(ctx, dataCid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Piece Size : %v\n", ds.PieceSize)
|
||||
fmt.Printf("Payload Size: %v\n", ds.PayloadSize)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var clientRestartTransfer = &cli.Command{
|
||||
Name: "restart-transfer",
|
||||
Usage: "Force restart a stalled data transfer",
|
||||
@@ -1698,6 +1733,66 @@ var clientRestartTransfer = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
var clientCancelTransfer = &cli.Command{
|
||||
Name: "cancel-transfer",
|
||||
Usage: "Force cancel a data transfer",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "peerid",
|
||||
Usage: "narrow to transfer with specific peer",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "initiator",
|
||||
Usage: "specify only transfers where peer is/is not initiator",
|
||||
Value: true,
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if !cctx.Args().Present() {
|
||||
return cli.ShowCommandHelp(cctx, cctx.Command.Name)
|
||||
}
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
transferUint, err := strconv.ParseUint(cctx.Args().First(), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error reading transfer ID: %w", err)
|
||||
}
|
||||
transferID := datatransfer.TransferID(transferUint)
|
||||
initiator := cctx.Bool("initiator")
|
||||
var other peer.ID
|
||||
if pidstr := cctx.String("peerid"); pidstr != "" {
|
||||
p, err := peer.Decode(pidstr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
other = p
|
||||
} else {
|
||||
channels, err := api.ClientListDataTransfers(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
found := false
|
||||
for _, channel := range channels {
|
||||
if channel.IsInitiator == initiator && channel.TransferID == transferID {
|
||||
other = channel.OtherPeer
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return errors.New("unable to find matching data transfer")
|
||||
}
|
||||
}
|
||||
|
||||
return api.ClientCancelDataTransfer(ctx, transferID, other, initiator)
|
||||
},
|
||||
}
|
||||
|
||||
var clientListTransfers = &cli.Command{
|
||||
Name: "list-transfers",
|
||||
Usage: "List ongoing data transfers for deals",
|
||||
@@ -1715,6 +1810,10 @@ var clientListTransfers = &cli.Command{
|
||||
Name: "watch",
|
||||
Usage: "watch deal updates in real-time, rather than a one time list",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "show-failed",
|
||||
Usage: "show failed/cancelled transfers",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
@@ -1732,7 +1831,7 @@ var clientListTransfers = &cli.Command{
|
||||
completed := cctx.Bool("completed")
|
||||
color := cctx.Bool("color")
|
||||
watch := cctx.Bool("watch")
|
||||
|
||||
showFailed := cctx.Bool("show-failed")
|
||||
if watch {
|
||||
channelUpdates, err := api.ClientDataTransferUpdates(ctx)
|
||||
if err != nil {
|
||||
@@ -1744,7 +1843,7 @@ var clientListTransfers = &cli.Command{
|
||||
|
||||
tm.MoveCursor(1, 1)
|
||||
|
||||
OutputDataTransferChannels(tm.Screen, channels, completed, color)
|
||||
OutputDataTransferChannels(tm.Screen, channels, completed, color, showFailed)
|
||||
|
||||
tm.Flush()
|
||||
|
||||
@@ -1769,13 +1868,13 @@ var clientListTransfers = &cli.Command{
|
||||
}
|
||||
}
|
||||
}
|
||||
OutputDataTransferChannels(os.Stdout, channels, completed, color)
|
||||
OutputDataTransferChannels(os.Stdout, channels, completed, color, showFailed)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// OutputDataTransferChannels generates table output for a list of channels
|
||||
func OutputDataTransferChannels(out io.Writer, channels []lapi.DataTransferChannel, completed bool, color bool) {
|
||||
func OutputDataTransferChannels(out io.Writer, channels []lapi.DataTransferChannel, completed bool, color bool, showFailed bool) {
|
||||
sort.Slice(channels, func(i, j int) bool {
|
||||
return channels[i].TransferID < channels[j].TransferID
|
||||
})
|
||||
@@ -1785,6 +1884,9 @@ func OutputDataTransferChannels(out io.Writer, channels []lapi.DataTransferChann
|
||||
if !completed && channel.Status == datatransfer.Completed {
|
||||
continue
|
||||
}
|
||||
if !showFailed && (channel.Status == datatransfer.Failed || channel.Status == datatransfer.Cancelled) {
|
||||
continue
|
||||
}
|
||||
if channel.IsSender {
|
||||
sendingChannels = append(sendingChannels, channel)
|
||||
} else {
|
||||
|
||||
+35
-18
@@ -264,8 +264,19 @@ var msigInspectCmd = &cli.Command{
|
||||
}
|
||||
fmt.Fprintf(cctx.App.Writer, "Threshold: %d / %d\n", threshold, len(signers))
|
||||
fmt.Fprintln(cctx.App.Writer, "Signers:")
|
||||
|
||||
signerTable := tabwriter.NewWriter(cctx.App.Writer, 8, 4, 2, ' ', 0)
|
||||
fmt.Fprintf(signerTable, "ID\tAddress\n")
|
||||
for _, s := range signers {
|
||||
fmt.Fprintf(cctx.App.Writer, "\t%s\n", s)
|
||||
signerActor, err := api.StateAccountKey(ctx, s, types.EmptyTSK)
|
||||
if err != nil {
|
||||
fmt.Fprintf(signerTable, "%s\t%s\n", s, "N/A")
|
||||
} else {
|
||||
fmt.Fprintf(signerTable, "%s\t%s\n", s, signerActor)
|
||||
}
|
||||
}
|
||||
if err := signerTable.Flush(); err != nil {
|
||||
return xerrors.Errorf("flushing output: %+v", err)
|
||||
}
|
||||
|
||||
pending := make(map[int64]multisig.Transaction)
|
||||
@@ -296,27 +307,33 @@ var msigInspectCmd = &cli.Command{
|
||||
target += " (self)"
|
||||
}
|
||||
targAct, err := api.StateGetActor(ctx, tx.To, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to resolve 'To' address of multisig transaction %d: %w", txid, err)
|
||||
}
|
||||
method := stmgr.MethodsMap[targAct.Code][tx.Method]
|
||||
|
||||
paramStr := fmt.Sprintf("%x", tx.Params)
|
||||
if decParams && tx.Method != 0 {
|
||||
ptyp := reflect.New(method.Params.Elem()).Interface().(cbg.CBORUnmarshaler)
|
||||
if err := ptyp.UnmarshalCBOR(bytes.NewReader(tx.Params)); err != nil {
|
||||
return xerrors.Errorf("failed to decode parameters of transaction %d: %w", txid, err)
|
||||
|
||||
if err != nil {
|
||||
if tx.Method == 0 {
|
||||
fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%s(%d)\t%s\n", txid, "pending", len(tx.Approved), target, types.FIL(tx.Value), "Send", tx.Method, paramStr)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%s(%d)\t%s\n", txid, "pending", len(tx.Approved), target, types.FIL(tx.Value), "new account, unknown method", tx.Method, paramStr)
|
||||
}
|
||||
} else {
|
||||
method := stmgr.MethodsMap[targAct.Code][tx.Method]
|
||||
|
||||
if decParams && tx.Method != 0 {
|
||||
ptyp := reflect.New(method.Params.Elem()).Interface().(cbg.CBORUnmarshaler)
|
||||
if err := ptyp.UnmarshalCBOR(bytes.NewReader(tx.Params)); err != nil {
|
||||
return xerrors.Errorf("failed to decode parameters of transaction %d: %w", txid, err)
|
||||
}
|
||||
|
||||
b, err := json.Marshal(ptyp)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("could not json marshal parameter type: %w", err)
|
||||
}
|
||||
|
||||
paramStr = string(b)
|
||||
}
|
||||
|
||||
b, err := json.Marshal(ptyp)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("could not json marshal parameter type: %w", err)
|
||||
}
|
||||
|
||||
paramStr = string(b)
|
||||
fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%s(%d)\t%s\n", txid, "pending", len(tx.Approved), target, types.FIL(tx.Value), method.Name, tx.Method, paramStr)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "%d\t%s\t%d\t%s\t%s\t%s(%d)\t%s\n", txid, "pending", len(tx.Approved), target, types.FIL(tx.Value), method.Name, tx.Method, paramStr)
|
||||
}
|
||||
if err := w.Flush(); err != nil {
|
||||
return xerrors.Errorf("flushing output: %+v", err)
|
||||
|
||||
+77
-211
@@ -1,9 +1,7 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
@@ -12,24 +10,21 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/urfave/cli/v2"
|
||||
clitest "github.com/filecoin-project/lotus/cli/test"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/lotus/api/apibstore"
|
||||
"github.com/filecoin-project/lotus/api/test"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/events"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
builder "github.com/filecoin-project/lotus/node/test"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -42,24 +37,24 @@ func init() {
|
||||
// commands
|
||||
func TestPaymentChannels(t *testing.T) {
|
||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
clitest.QuietMiningLogs()
|
||||
|
||||
blocktime := 5 * time.Millisecond
|
||||
ctx := context.Background()
|
||||
nodes, addrs := startTwoNodesOneMiner(ctx, t, blocktime)
|
||||
nodes, addrs := clitest.StartTwoNodesOneMiner(ctx, t, blocktime)
|
||||
paymentCreator := nodes[0]
|
||||
paymentReceiver := nodes[1]
|
||||
creatorAddr := addrs[0]
|
||||
receiverAddr := addrs[1]
|
||||
|
||||
// Create mock CLI
|
||||
mockCLI := newMockCLI(t)
|
||||
creatorCLI := mockCLI.client(paymentCreator.ListenAddr)
|
||||
receiverCLI := mockCLI.client(paymentReceiver.ListenAddr)
|
||||
mockCLI := clitest.NewMockCLI(t, Commands)
|
||||
creatorCLI := mockCLI.Client(paymentCreator.ListenAddr)
|
||||
receiverCLI := mockCLI.Client(paymentReceiver.ListenAddr)
|
||||
|
||||
// creator: paych add-funds <creator> <receiver> <amount>
|
||||
channelAmt := "100000"
|
||||
cmd := []string{creatorAddr.String(), receiverAddr.String(), channelAmt}
|
||||
chstr := creatorCLI.runCmd(paychAddFundsCmd, cmd)
|
||||
chstr := creatorCLI.RunCmd("paych", "add-funds", creatorAddr.String(), receiverAddr.String(), channelAmt)
|
||||
|
||||
chAddr, err := address.NewFromString(chstr)
|
||||
require.NoError(t, err)
|
||||
@@ -67,16 +62,13 @@ func TestPaymentChannels(t *testing.T) {
|
||||
// creator: paych voucher create <channel> <amount>
|
||||
voucherAmt := 100
|
||||
vamt := strconv.Itoa(voucherAmt)
|
||||
cmd = []string{chAddr.String(), vamt}
|
||||
voucher := creatorCLI.runCmd(paychVoucherCreateCmd, cmd)
|
||||
voucher := creatorCLI.RunCmd("paych", "voucher", "create", chAddr.String(), vamt)
|
||||
|
||||
// receiver: paych voucher add <channel> <voucher>
|
||||
cmd = []string{chAddr.String(), voucher}
|
||||
receiverCLI.runCmd(paychVoucherAddCmd, cmd)
|
||||
receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher)
|
||||
|
||||
// creator: paych settle <channel>
|
||||
cmd = []string{chAddr.String()}
|
||||
creatorCLI.runCmd(paychSettleCmd, cmd)
|
||||
creatorCLI.RunCmd("paych", "settle", chAddr.String())
|
||||
|
||||
// Wait for the chain to reach the settle height
|
||||
chState := getPaychState(ctx, t, paymentReceiver, chAddr)
|
||||
@@ -85,8 +77,7 @@ func TestPaymentChannels(t *testing.T) {
|
||||
waitForHeight(ctx, t, paymentReceiver, sa)
|
||||
|
||||
// receiver: paych collect <channel>
|
||||
cmd = []string{chAddr.String()}
|
||||
receiverCLI.runCmd(paychCloseCmd, cmd)
|
||||
receiverCLI.RunCmd("paych", "collect", chAddr.String())
|
||||
}
|
||||
|
||||
type voucherSpec struct {
|
||||
@@ -98,20 +89,21 @@ type voucherSpec struct {
|
||||
// TestPaymentChannelStatus tests the payment channel status CLI command
|
||||
func TestPaymentChannelStatus(t *testing.T) {
|
||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
clitest.QuietMiningLogs()
|
||||
|
||||
blocktime := 5 * time.Millisecond
|
||||
ctx := context.Background()
|
||||
nodes, addrs := startTwoNodesOneMiner(ctx, t, blocktime)
|
||||
nodes, addrs := clitest.StartTwoNodesOneMiner(ctx, t, blocktime)
|
||||
paymentCreator := nodes[0]
|
||||
creatorAddr := addrs[0]
|
||||
receiverAddr := addrs[1]
|
||||
|
||||
// Create mock CLI
|
||||
mockCLI := newMockCLI(t)
|
||||
creatorCLI := mockCLI.client(paymentCreator.ListenAddr)
|
||||
mockCLI := clitest.NewMockCLI(t, Commands)
|
||||
creatorCLI := mockCLI.Client(paymentCreator.ListenAddr)
|
||||
|
||||
cmd := []string{creatorAddr.String(), receiverAddr.String()}
|
||||
out := creatorCLI.runCmd(paychStatusByFromToCmd, cmd)
|
||||
// creator: paych status-by-from-to <creator> <receiver>
|
||||
out := creatorCLI.RunCmd("paych", "status-by-from-to", creatorAddr.String(), receiverAddr.String())
|
||||
fmt.Println(out)
|
||||
noChannelState := "Channel does not exist"
|
||||
require.Regexp(t, regexp.MustCompile(noChannelState), out)
|
||||
@@ -120,14 +112,17 @@ func TestPaymentChannelStatus(t *testing.T) {
|
||||
create := make(chan string)
|
||||
go func() {
|
||||
// creator: paych add-funds <creator> <receiver> <amount>
|
||||
cmd := []string{creatorAddr.String(), receiverAddr.String(), fmt.Sprintf("%d", channelAmt)}
|
||||
create <- creatorCLI.runCmd(paychAddFundsCmd, cmd)
|
||||
create <- creatorCLI.RunCmd(
|
||||
"paych",
|
||||
"add-funds",
|
||||
creatorAddr.String(),
|
||||
receiverAddr.String(),
|
||||
fmt.Sprintf("%d", channelAmt))
|
||||
}()
|
||||
|
||||
// Wait for the output to stop being "Channel does not exist"
|
||||
for regexp.MustCompile(noChannelState).MatchString(out) {
|
||||
cmd := []string{creatorAddr.String(), receiverAddr.String()}
|
||||
out = creatorCLI.runCmd(paychStatusByFromToCmd, cmd)
|
||||
out = creatorCLI.RunCmd("paych", "status-by-from-to", creatorAddr.String(), receiverAddr.String())
|
||||
}
|
||||
fmt.Println(out)
|
||||
|
||||
@@ -147,8 +142,7 @@ func TestPaymentChannelStatus(t *testing.T) {
|
||||
// Wait for create channel to complete
|
||||
chstr := <-create
|
||||
|
||||
cmd = []string{chstr}
|
||||
out = creatorCLI.runCmd(paychStatusCmd, cmd)
|
||||
out = creatorCLI.RunCmd("paych", "status", chstr)
|
||||
fmt.Println(out)
|
||||
// Output should have the channel address
|
||||
require.Regexp(t, regexp.MustCompile("Channel.*"+chstr), out)
|
||||
@@ -160,11 +154,9 @@ func TestPaymentChannelStatus(t *testing.T) {
|
||||
|
||||
// creator: paych voucher create <channel> <amount>
|
||||
voucherAmt := uint64(10)
|
||||
cmd = []string{chAddr.String(), fmt.Sprintf("%d", voucherAmt)}
|
||||
creatorCLI.runCmd(paychVoucherCreateCmd, cmd)
|
||||
creatorCLI.RunCmd("paych", "voucher", "create", chAddr.String(), fmt.Sprintf("%d", voucherAmt))
|
||||
|
||||
cmd = []string{chstr}
|
||||
out = creatorCLI.runCmd(paychStatusCmd, cmd)
|
||||
out = creatorCLI.RunCmd("paych", "status", chstr)
|
||||
fmt.Println(out)
|
||||
voucherAmtAtto := types.BigMul(types.NewInt(voucherAmt), types.NewInt(build.FilecoinPrecision))
|
||||
voucherAmtStr := fmt.Sprintf("%d", voucherAmtAtto)
|
||||
@@ -176,24 +168,24 @@ func TestPaymentChannelStatus(t *testing.T) {
|
||||
// channel voucher commands
|
||||
func TestPaymentChannelVouchers(t *testing.T) {
|
||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
clitest.QuietMiningLogs()
|
||||
|
||||
blocktime := 5 * time.Millisecond
|
||||
ctx := context.Background()
|
||||
nodes, addrs := startTwoNodesOneMiner(ctx, t, blocktime)
|
||||
nodes, addrs := clitest.StartTwoNodesOneMiner(ctx, t, blocktime)
|
||||
paymentCreator := nodes[0]
|
||||
paymentReceiver := nodes[1]
|
||||
creatorAddr := addrs[0]
|
||||
receiverAddr := addrs[1]
|
||||
|
||||
// Create mock CLI
|
||||
mockCLI := newMockCLI(t)
|
||||
creatorCLI := mockCLI.client(paymentCreator.ListenAddr)
|
||||
receiverCLI := mockCLI.client(paymentReceiver.ListenAddr)
|
||||
mockCLI := clitest.NewMockCLI(t, Commands)
|
||||
creatorCLI := mockCLI.Client(paymentCreator.ListenAddr)
|
||||
receiverCLI := mockCLI.Client(paymentReceiver.ListenAddr)
|
||||
|
||||
// creator: paych add-funds <creator> <receiver> <amount>
|
||||
channelAmt := "100000"
|
||||
cmd := []string{creatorAddr.String(), receiverAddr.String(), channelAmt}
|
||||
chstr := creatorCLI.runCmd(paychAddFundsCmd, cmd)
|
||||
chstr := creatorCLI.RunCmd("paych", "add-funds", creatorAddr.String(), receiverAddr.String(), channelAmt)
|
||||
|
||||
chAddr, err := address.NewFromString(chstr)
|
||||
require.NoError(t, err)
|
||||
@@ -203,39 +195,33 @@ func TestPaymentChannelVouchers(t *testing.T) {
|
||||
// creator: paych voucher create <channel> <amount>
|
||||
// Note: implied --lane=0
|
||||
voucherAmt1 := 100
|
||||
cmd = []string{chAddr.String(), strconv.Itoa(voucherAmt1)}
|
||||
voucher1 := creatorCLI.runCmd(paychVoucherCreateCmd, cmd)
|
||||
voucher1 := creatorCLI.RunCmd("paych", "voucher", "create", chAddr.String(), strconv.Itoa(voucherAmt1))
|
||||
vouchers = append(vouchers, voucherSpec{serialized: voucher1, lane: 0, amt: voucherAmt1})
|
||||
|
||||
// creator: paych voucher create <channel> <amount> --lane=5
|
||||
lane5 := "--lane=5"
|
||||
voucherAmt2 := 50
|
||||
cmd = []string{lane5, chAddr.String(), strconv.Itoa(voucherAmt2)}
|
||||
voucher2 := creatorCLI.runCmd(paychVoucherCreateCmd, cmd)
|
||||
voucher2 := creatorCLI.RunCmd("paych", "voucher", "create", lane5, chAddr.String(), strconv.Itoa(voucherAmt2))
|
||||
vouchers = append(vouchers, voucherSpec{serialized: voucher2, lane: 5, amt: voucherAmt2})
|
||||
|
||||
// creator: paych voucher create <channel> <amount> --lane=5
|
||||
voucherAmt3 := 70
|
||||
cmd = []string{lane5, chAddr.String(), strconv.Itoa(voucherAmt3)}
|
||||
voucher3 := creatorCLI.runCmd(paychVoucherCreateCmd, cmd)
|
||||
voucher3 := creatorCLI.RunCmd("paych", "voucher", "create", lane5, chAddr.String(), strconv.Itoa(voucherAmt3))
|
||||
vouchers = append(vouchers, voucherSpec{serialized: voucher3, lane: 5, amt: voucherAmt3})
|
||||
|
||||
// creator: paych voucher create <channel> <amount> --lane=5
|
||||
voucherAmt4 := 80
|
||||
cmd = []string{lane5, chAddr.String(), strconv.Itoa(voucherAmt4)}
|
||||
voucher4 := creatorCLI.runCmd(paychVoucherCreateCmd, cmd)
|
||||
voucher4 := creatorCLI.RunCmd("paych", "voucher", "create", lane5, chAddr.String(), strconv.Itoa(voucherAmt4))
|
||||
vouchers = append(vouchers, voucherSpec{serialized: voucher4, lane: 5, amt: voucherAmt4})
|
||||
|
||||
// creator: paych voucher list <channel> --export
|
||||
cmd = []string{"--export", chAddr.String()}
|
||||
list := creatorCLI.runCmd(paychVoucherListCmd, cmd)
|
||||
list := creatorCLI.RunCmd("paych", "voucher", "list", "--export", chAddr.String())
|
||||
|
||||
// Check that voucher list output is correct on creator
|
||||
checkVoucherOutput(t, list, vouchers)
|
||||
|
||||
// creator: paych voucher best-spendable <channel>
|
||||
cmd = []string{"--export", chAddr.String()}
|
||||
bestSpendable := creatorCLI.runCmd(paychVoucherBestSpendableCmd, cmd)
|
||||
bestSpendable := creatorCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String())
|
||||
|
||||
// Check that best spendable output is correct on creator
|
||||
bestVouchers := []voucherSpec{
|
||||
@@ -245,31 +231,25 @@ func TestPaymentChannelVouchers(t *testing.T) {
|
||||
checkVoucherOutput(t, bestSpendable, bestVouchers)
|
||||
|
||||
// receiver: paych voucher add <voucher>
|
||||
cmd = []string{chAddr.String(), voucher1}
|
||||
receiverCLI.runCmd(paychVoucherAddCmd, cmd)
|
||||
receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher1)
|
||||
|
||||
// receiver: paych voucher add <voucher>
|
||||
cmd = []string{chAddr.String(), voucher2}
|
||||
receiverCLI.runCmd(paychVoucherAddCmd, cmd)
|
||||
receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher2)
|
||||
|
||||
// receiver: paych voucher add <voucher>
|
||||
cmd = []string{chAddr.String(), voucher3}
|
||||
receiverCLI.runCmd(paychVoucherAddCmd, cmd)
|
||||
receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher3)
|
||||
|
||||
// receiver: paych voucher add <voucher>
|
||||
cmd = []string{chAddr.String(), voucher4}
|
||||
receiverCLI.runCmd(paychVoucherAddCmd, cmd)
|
||||
receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher4)
|
||||
|
||||
// receiver: paych voucher list <channel> --export
|
||||
cmd = []string{"--export", chAddr.String()}
|
||||
list = receiverCLI.runCmd(paychVoucherListCmd, cmd)
|
||||
list = receiverCLI.RunCmd("paych", "voucher", "list", "--export", chAddr.String())
|
||||
|
||||
// Check that voucher list output is correct on receiver
|
||||
checkVoucherOutput(t, list, vouchers)
|
||||
|
||||
// receiver: paych voucher best-spendable <channel>
|
||||
cmd = []string{"--export", chAddr.String()}
|
||||
bestSpendable = receiverCLI.runCmd(paychVoucherBestSpendableCmd, cmd)
|
||||
bestSpendable = receiverCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String())
|
||||
|
||||
// Check that best spendable output is correct on receiver
|
||||
bestVouchers = []voucherSpec{
|
||||
@@ -279,12 +259,10 @@ func TestPaymentChannelVouchers(t *testing.T) {
|
||||
checkVoucherOutput(t, bestSpendable, bestVouchers)
|
||||
|
||||
// receiver: paych voucher submit <channel> <voucher>
|
||||
cmd = []string{chAddr.String(), voucher1}
|
||||
receiverCLI.runCmd(paychVoucherSubmitCmd, cmd)
|
||||
receiverCLI.RunCmd("paych", "voucher", "submit", chAddr.String(), voucher1)
|
||||
|
||||
// receiver: paych voucher best-spendable <channel>
|
||||
cmd = []string{"--export", chAddr.String()}
|
||||
bestSpendable = receiverCLI.runCmd(paychVoucherBestSpendableCmd, cmd)
|
||||
bestSpendable = receiverCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String())
|
||||
|
||||
// Check that best spendable output no longer includes submitted voucher
|
||||
bestVouchers = []voucherSpec{
|
||||
@@ -295,12 +273,10 @@ func TestPaymentChannelVouchers(t *testing.T) {
|
||||
// There are three vouchers in lane 5: 50, 70, 80
|
||||
// Submit the voucher for 50. Best spendable should still be 80.
|
||||
// receiver: paych voucher submit <channel> <voucher>
|
||||
cmd = []string{chAddr.String(), voucher2}
|
||||
receiverCLI.runCmd(paychVoucherSubmitCmd, cmd)
|
||||
receiverCLI.RunCmd("paych", "voucher", "submit", chAddr.String(), voucher2)
|
||||
|
||||
// receiver: paych voucher best-spendable <channel>
|
||||
cmd = []string{"--export", chAddr.String()}
|
||||
bestSpendable = receiverCLI.runCmd(paychVoucherBestSpendableCmd, cmd)
|
||||
bestSpendable = receiverCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String())
|
||||
|
||||
// Check that best spendable output still includes the voucher for 80
|
||||
bestVouchers = []voucherSpec{
|
||||
@@ -310,12 +286,10 @@ func TestPaymentChannelVouchers(t *testing.T) {
|
||||
|
||||
// Submit the voucher for 80
|
||||
// receiver: paych voucher submit <channel> <voucher>
|
||||
cmd = []string{chAddr.String(), voucher4}
|
||||
receiverCLI.runCmd(paychVoucherSubmitCmd, cmd)
|
||||
receiverCLI.RunCmd("paych", "voucher", "submit", chAddr.String(), voucher4)
|
||||
|
||||
// receiver: paych voucher best-spendable <channel>
|
||||
cmd = []string{"--export", chAddr.String()}
|
||||
bestSpendable = receiverCLI.runCmd(paychVoucherBestSpendableCmd, cmd)
|
||||
bestSpendable = receiverCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String())
|
||||
|
||||
// Check that best spendable output no longer includes submitted voucher
|
||||
bestVouchers = []voucherSpec{}
|
||||
@@ -326,22 +300,27 @@ func TestPaymentChannelVouchers(t *testing.T) {
|
||||
// is greater than what's left in the channel, voucher create fails
|
||||
func TestPaymentChannelVoucherCreateShortfall(t *testing.T) {
|
||||
_ = os.Setenv("BELLMAN_NO_GPU", "1")
|
||||
clitest.QuietMiningLogs()
|
||||
|
||||
blocktime := 5 * time.Millisecond
|
||||
ctx := context.Background()
|
||||
nodes, addrs := startTwoNodesOneMiner(ctx, t, blocktime)
|
||||
nodes, addrs := clitest.StartTwoNodesOneMiner(ctx, t, blocktime)
|
||||
paymentCreator := nodes[0]
|
||||
creatorAddr := addrs[0]
|
||||
receiverAddr := addrs[1]
|
||||
|
||||
// Create mock CLI
|
||||
mockCLI := newMockCLI(t)
|
||||
creatorCLI := mockCLI.client(paymentCreator.ListenAddr)
|
||||
mockCLI := clitest.NewMockCLI(t, Commands)
|
||||
creatorCLI := mockCLI.Client(paymentCreator.ListenAddr)
|
||||
|
||||
// creator: paych add-funds <creator> <receiver> <amount>
|
||||
channelAmt := 100
|
||||
cmd := []string{creatorAddr.String(), receiverAddr.String(), fmt.Sprintf("%d", channelAmt)}
|
||||
chstr := creatorCLI.runCmd(paychAddFundsCmd, cmd)
|
||||
chstr := creatorCLI.RunCmd(
|
||||
"paych",
|
||||
"add-funds",
|
||||
creatorAddr.String(),
|
||||
receiverAddr.String(),
|
||||
fmt.Sprintf("%d", channelAmt))
|
||||
|
||||
chAddr, err := address.NewFromString(chstr)
|
||||
require.NoError(t, err)
|
||||
@@ -349,15 +328,25 @@ func TestPaymentChannelVoucherCreateShortfall(t *testing.T) {
|
||||
// creator: paych voucher create <channel> <amount> --lane=1
|
||||
voucherAmt1 := 60
|
||||
lane1 := "--lane=1"
|
||||
cmd = []string{lane1, chAddr.String(), strconv.Itoa(voucherAmt1)}
|
||||
voucher1 := creatorCLI.runCmd(paychVoucherCreateCmd, cmd)
|
||||
voucher1 := creatorCLI.RunCmd(
|
||||
"paych",
|
||||
"voucher",
|
||||
"create",
|
||||
lane1,
|
||||
chAddr.String(),
|
||||
strconv.Itoa(voucherAmt1))
|
||||
fmt.Println(voucher1)
|
||||
|
||||
// creator: paych voucher create <channel> <amount> --lane=2
|
||||
lane2 := "--lane=2"
|
||||
voucherAmt2 := 70
|
||||
cmd = []string{lane2, chAddr.String(), strconv.Itoa(voucherAmt2)}
|
||||
_, err = creatorCLI.runCmdRaw(paychVoucherCreateCmd, cmd)
|
||||
_, err = creatorCLI.RunCmdRaw(
|
||||
"paych",
|
||||
"voucher",
|
||||
"create",
|
||||
lane2,
|
||||
chAddr.String(),
|
||||
strconv.Itoa(voucherAmt2))
|
||||
|
||||
// Should fail because channel doesn't have required amount
|
||||
require.Error(t, err)
|
||||
@@ -388,129 +377,6 @@ func checkVoucherOutput(t *testing.T, list string, vouchers []voucherSpec) {
|
||||
}
|
||||
}
|
||||
|
||||
func startTwoNodesOneMiner(ctx context.Context, t *testing.T, blocktime time.Duration) ([]test.TestNode, []address.Address) {
|
||||
n, sn := builder.RPCMockSbBuilder(t, test.TwoFull, test.OneMiner)
|
||||
|
||||
paymentCreator := n[0]
|
||||
paymentReceiver := n[1]
|
||||
miner := sn[0]
|
||||
|
||||
// Get everyone connected
|
||||
addrs, err := paymentCreator.NetAddrsListen(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := paymentReceiver.NetConnect(ctx, addrs); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := miner.NetConnect(ctx, addrs); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Start mining blocks
|
||||
bm := test.NewBlockMiner(ctx, t, miner, blocktime)
|
||||
bm.MineBlocks()
|
||||
|
||||
// Send some funds to register the receiver
|
||||
receiverAddr, err := paymentReceiver.WalletNew(ctx, types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
test.SendFunds(ctx, t, paymentCreator, receiverAddr, abi.NewTokenAmount(1e18))
|
||||
|
||||
// Get the creator's address
|
||||
creatorAddr, err := paymentCreator.WalletDefaultAddress(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Create mock CLI
|
||||
return n, []address.Address{creatorAddr, receiverAddr}
|
||||
}
|
||||
|
||||
type mockCLI struct {
|
||||
t *testing.T
|
||||
cctx *cli.Context
|
||||
out *bytes.Buffer
|
||||
}
|
||||
|
||||
// TODO: refactor to use the methods in cli/test/mockcli.go
|
||||
func newMockCLI(t *testing.T) *mockCLI {
|
||||
// Create a CLI App with an --api-url flag so that we can specify which node
|
||||
// the command should be executed against
|
||||
app := cli.NewApp()
|
||||
app.Flags = []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "api-url",
|
||||
Hidden: true,
|
||||
},
|
||||
}
|
||||
var out bytes.Buffer
|
||||
app.Writer = &out
|
||||
app.Setup()
|
||||
|
||||
cctx := cli.NewContext(app, &flag.FlagSet{}, nil)
|
||||
return &mockCLI{t: t, cctx: cctx, out: &out}
|
||||
}
|
||||
|
||||
func (c *mockCLI) client(addr multiaddr.Multiaddr) *mockCLIClient {
|
||||
return &mockCLIClient{t: c.t, addr: addr, cctx: c.cctx, out: c.out}
|
||||
}
|
||||
|
||||
// mockCLIClient runs commands against a particular node
|
||||
type mockCLIClient struct {
|
||||
t *testing.T
|
||||
addr multiaddr.Multiaddr
|
||||
cctx *cli.Context
|
||||
out *bytes.Buffer
|
||||
}
|
||||
|
||||
func (c *mockCLIClient) runCmd(cmd *cli.Command, input []string) string {
|
||||
out, err := c.runCmdRaw(cmd, input)
|
||||
require.NoError(c.t, err)
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (c *mockCLIClient) runCmdRaw(cmd *cli.Command, input []string) (string, error) {
|
||||
// prepend --api-url=<node api listener address>
|
||||
apiFlag := "--api-url=" + c.addr.String()
|
||||
input = append([]string{apiFlag}, input...)
|
||||
|
||||
fs := c.flagSet(cmd)
|
||||
err := fs.Parse(input)
|
||||
require.NoError(c.t, err)
|
||||
|
||||
err = cmd.Action(cli.NewContext(c.cctx.App, fs, c.cctx))
|
||||
|
||||
// Get the output
|
||||
str := strings.TrimSpace(c.out.String())
|
||||
c.out.Reset()
|
||||
return str, err
|
||||
}
|
||||
|
||||
func (c *mockCLIClient) flagSet(cmd *cli.Command) *flag.FlagSet {
|
||||
// Apply app level flags (so we can process --api-url flag)
|
||||
fs := &flag.FlagSet{}
|
||||
for _, f := range c.cctx.App.Flags {
|
||||
err := f.Apply(fs)
|
||||
if err != nil {
|
||||
c.t.Fatal(err)
|
||||
}
|
||||
}
|
||||
// Apply command level flags
|
||||
for _, f := range cmd.Flags {
|
||||
err := f.Apply(fs)
|
||||
if err != nil {
|
||||
c.t.Fatal(err)
|
||||
}
|
||||
}
|
||||
return fs
|
||||
}
|
||||
|
||||
// waitForHeight waits for the node to reach the given chain epoch
|
||||
func waitForHeight(ctx context.Context, t *testing.T, node test.TestNode, height abi.ChainEpoch) {
|
||||
atHeight := make(chan struct{})
|
||||
|
||||
+8
-20
@@ -25,8 +25,8 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode)
|
||||
defer cancel()
|
||||
|
||||
// Create mock CLI
|
||||
mockCLI := newMockCLI(t, cmds)
|
||||
clientCLI := mockCLI.client(clientNode.ListenAddr)
|
||||
mockCLI := NewMockCLI(t, cmds)
|
||||
clientCLI := mockCLI.Client(clientNode.ListenAddr)
|
||||
|
||||
// Get the miner address
|
||||
addrs, err := clientNode.StateListMiners(ctx, types.EmptyTSK)
|
||||
@@ -37,10 +37,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode)
|
||||
fmt.Println("Miner:", minerAddr)
|
||||
|
||||
// client query-ask <miner addr>
|
||||
cmd := []string{
|
||||
"client", "query-ask", minerAddr.String(),
|
||||
}
|
||||
out := clientCLI.runCmd(cmd)
|
||||
out := clientCLI.RunCmd("client", "query-ask", minerAddr.String())
|
||||
require.Regexp(t, regexp.MustCompile("Ask:"), out)
|
||||
|
||||
// Create a deal (non-interactive)
|
||||
@@ -50,10 +47,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode)
|
||||
dataCid := res.Root
|
||||
price := "1000000attofil"
|
||||
duration := fmt.Sprintf("%d", build.MinDealDuration)
|
||||
cmd = []string{
|
||||
"client", "deal", dataCid.String(), minerAddr.String(), price, duration,
|
||||
}
|
||||
out = clientCLI.runCmd(cmd)
|
||||
out = clientCLI.RunCmd("client", "deal", dataCid.String(), minerAddr.String(), price, duration)
|
||||
fmt.Println("client deal", out)
|
||||
|
||||
// Create a deal (interactive)
|
||||
@@ -67,9 +61,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode)
|
||||
require.NoError(t, err)
|
||||
dataCid2 := res.Root
|
||||
duration = fmt.Sprintf("%d", build.MinDealDuration/builtin.EpochsInDay)
|
||||
cmd = []string{
|
||||
"client", "deal",
|
||||
}
|
||||
cmd := []string{"client", "deal"}
|
||||
interactiveCmds := []string{
|
||||
dataCid2.String(),
|
||||
duration,
|
||||
@@ -77,15 +69,14 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode)
|
||||
"no",
|
||||
"yes",
|
||||
}
|
||||
out = clientCLI.runInteractiveCmd(cmd, interactiveCmds)
|
||||
out = clientCLI.RunInteractiveCmd(cmd, interactiveCmds)
|
||||
fmt.Println("client deal:\n", out)
|
||||
|
||||
// Wait for provider to start sealing deal
|
||||
dealStatus := ""
|
||||
for dealStatus != "StorageDealSealing" {
|
||||
// client list-deals
|
||||
cmd = []string{"client", "list-deals"}
|
||||
out = clientCLI.runCmd(cmd)
|
||||
out = clientCLI.RunCmd("client", "list-deals")
|
||||
fmt.Println("list-deals:\n", out)
|
||||
|
||||
lines := strings.Split(out, "\n")
|
||||
@@ -106,10 +97,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode)
|
||||
tmpdir, err := ioutil.TempDir(os.TempDir(), "test-cli-client")
|
||||
require.NoError(t, err)
|
||||
path := filepath.Join(tmpdir, "outfile.dat")
|
||||
cmd = []string{
|
||||
"client", "retrieve", dataCid.String(), path,
|
||||
}
|
||||
out = clientCLI.runCmd(cmd)
|
||||
out = clientCLI.RunCmd("client", "retrieve", dataCid.String(), path)
|
||||
fmt.Println("retrieve:\n", out)
|
||||
require.Regexp(t, regexp.MustCompile("Success"), out)
|
||||
}
|
||||
|
||||
+44
-38
@@ -11,14 +11,14 @@ import (
|
||||
lcli "github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type mockCLI struct {
|
||||
type MockCLI struct {
|
||||
t *testing.T
|
||||
cmds []*lcli.Command
|
||||
cctx *lcli.Context
|
||||
out *bytes.Buffer
|
||||
}
|
||||
|
||||
func newMockCLI(t *testing.T, cmds []*lcli.Command) *mockCLI {
|
||||
func NewMockCLI(t *testing.T, cmds []*lcli.Command) *MockCLI {
|
||||
// Create a CLI App with an --api-url flag so that we can specify which node
|
||||
// the command should be executed against
|
||||
app := &lcli.App{
|
||||
@@ -36,15 +36,15 @@ func newMockCLI(t *testing.T, cmds []*lcli.Command) *mockCLI {
|
||||
app.Setup()
|
||||
|
||||
cctx := lcli.NewContext(app, &flag.FlagSet{}, nil)
|
||||
return &mockCLI{t: t, cmds: cmds, cctx: cctx, out: &out}
|
||||
return &MockCLI{t: t, cmds: cmds, cctx: cctx, out: &out}
|
||||
}
|
||||
|
||||
func (c *mockCLI) client(addr multiaddr.Multiaddr) *mockCLIClient {
|
||||
return &mockCLIClient{t: c.t, cmds: c.cmds, addr: addr, cctx: c.cctx, out: c.out}
|
||||
func (c *MockCLI) Client(addr multiaddr.Multiaddr) *MockCLIClient {
|
||||
return &MockCLIClient{t: c.t, cmds: c.cmds, addr: addr, cctx: c.cctx, out: c.out}
|
||||
}
|
||||
|
||||
// mockCLIClient runs commands against a particular node
|
||||
type mockCLIClient struct {
|
||||
// MockCLIClient runs commands against a particular node
|
||||
type MockCLIClient struct {
|
||||
t *testing.T
|
||||
cmds []*lcli.Command
|
||||
addr multiaddr.Multiaddr
|
||||
@@ -52,42 +52,48 @@ type mockCLIClient struct {
|
||||
out *bytes.Buffer
|
||||
}
|
||||
|
||||
func (c *mockCLIClient) run(cmd []string, params []string, args []string) string {
|
||||
// Add parameter --api-url=<node api listener address>
|
||||
apiFlag := "--api-url=" + c.addr.String()
|
||||
params = append([]string{apiFlag}, params...)
|
||||
|
||||
err := c.cctx.App.Run(append(append(cmd, params...), args...))
|
||||
require.NoError(c.t, err)
|
||||
|
||||
// Get the output
|
||||
str := strings.TrimSpace(c.out.String())
|
||||
c.out.Reset()
|
||||
return str
|
||||
}
|
||||
|
||||
func (c *mockCLIClient) runCmd(input []string) string {
|
||||
cmd := c.cmdByNameSub(input[0], input[1])
|
||||
out, err := c.runCmdRaw(cmd, input[2:])
|
||||
func (c *MockCLIClient) RunCmd(input ...string) string {
|
||||
out, err := c.RunCmdRaw(input...)
|
||||
require.NoError(c.t, err)
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (c *mockCLIClient) cmdByNameSub(name string, sub string) *lcli.Command {
|
||||
for _, c := range c.cmds {
|
||||
if c.Name == name {
|
||||
for _, s := range c.Subcommands {
|
||||
if s.Name == sub {
|
||||
return s
|
||||
}
|
||||
}
|
||||
// Given an input, find the corresponding command or sub-command.
|
||||
// eg "paych add-funds"
|
||||
func (c *MockCLIClient) cmdByNameSub(input []string) (*lcli.Command, []string) {
|
||||
name := input[0]
|
||||
for _, cmd := range c.cmds {
|
||||
if cmd.Name == name {
|
||||
return c.findSubcommand(cmd, input[1:])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return nil, []string{}
|
||||
}
|
||||
|
||||
func (c *mockCLIClient) runCmdRaw(cmd *lcli.Command, input []string) (string, error) {
|
||||
func (c *MockCLIClient) findSubcommand(cmd *lcli.Command, input []string) (*lcli.Command, []string) {
|
||||
// If there are no sub-commands, return the current command
|
||||
if len(cmd.Subcommands) == 0 {
|
||||
return cmd, input
|
||||
}
|
||||
|
||||
// Check each sub-command for a match against the name
|
||||
subName := input[0]
|
||||
for _, subCmd := range cmd.Subcommands {
|
||||
if subCmd.Name == subName {
|
||||
// Found a match, recursively search for sub-commands
|
||||
return c.findSubcommand(subCmd, input[1:])
|
||||
}
|
||||
}
|
||||
return nil, []string{}
|
||||
}
|
||||
|
||||
func (c *MockCLIClient) RunCmdRaw(input ...string) (string, error) {
|
||||
cmd, input := c.cmdByNameSub(input)
|
||||
if cmd == nil {
|
||||
panic("Could not find command " + input[0] + " " + input[1])
|
||||
}
|
||||
|
||||
// prepend --api-url=<node api listener address>
|
||||
apiFlag := "--api-url=" + c.addr.String()
|
||||
input = append([]string{apiFlag}, input...)
|
||||
@@ -104,7 +110,7 @@ func (c *mockCLIClient) runCmdRaw(cmd *lcli.Command, input []string) (string, er
|
||||
return str, err
|
||||
}
|
||||
|
||||
func (c *mockCLIClient) flagSet(cmd *lcli.Command) *flag.FlagSet {
|
||||
func (c *MockCLIClient) flagSet(cmd *lcli.Command) *flag.FlagSet {
|
||||
// Apply app level flags (so we can process --api-url flag)
|
||||
fs := &flag.FlagSet{}
|
||||
for _, f := range c.cctx.App.Flags {
|
||||
@@ -123,11 +129,11 @@ func (c *mockCLIClient) flagSet(cmd *lcli.Command) *flag.FlagSet {
|
||||
return fs
|
||||
}
|
||||
|
||||
func (c *mockCLIClient) runInteractiveCmd(cmd []string, interactive []string) string {
|
||||
func (c *MockCLIClient) RunInteractiveCmd(cmd []string, interactive []string) string {
|
||||
c.toStdin(strings.Join(interactive, "\n") + "\n")
|
||||
return c.runCmd(cmd)
|
||||
return c.RunCmd(cmd...)
|
||||
}
|
||||
|
||||
func (c *mockCLIClient) toStdin(s string) {
|
||||
func (c *MockCLIClient) toStdin(s string) {
|
||||
c.cctx.App.Metadata["stdin"] = bytes.NewBufferString(s)
|
||||
}
|
||||
|
||||
+9
-13
@@ -18,8 +18,8 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod
|
||||
ctx := context.Background()
|
||||
|
||||
// Create mock CLI
|
||||
mockCLI := newMockCLI(t, cmds)
|
||||
clientCLI := mockCLI.client(clientNode.ListenAddr)
|
||||
mockCLI := NewMockCLI(t, cmds)
|
||||
clientCLI := mockCLI.Client(clientNode.ListenAddr)
|
||||
|
||||
// Create some wallets on the node to use for testing multisig
|
||||
var walletAddrs []address.Address
|
||||
@@ -39,7 +39,7 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod
|
||||
paramDuration := "--duration=50"
|
||||
paramRequired := fmt.Sprintf("--required=%d", threshold)
|
||||
paramValue := fmt.Sprintf("--value=%dattofil", amtAtto)
|
||||
cmd := []string{
|
||||
out := clientCLI.RunCmd(
|
||||
"msig", "create",
|
||||
paramRequired,
|
||||
paramDuration,
|
||||
@@ -47,8 +47,7 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod
|
||||
walletAddrs[0].String(),
|
||||
walletAddrs[1].String(),
|
||||
walletAddrs[2].String(),
|
||||
}
|
||||
out := clientCLI.runCmd(cmd)
|
||||
)
|
||||
fmt.Println(out)
|
||||
|
||||
// Extract msig robust address from output
|
||||
@@ -62,18 +61,16 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod
|
||||
// Propose to add a new address to the msig
|
||||
// msig add-propose --from=<addr> <msig> <addr>
|
||||
paramFrom := fmt.Sprintf("--from=%s", walletAddrs[0])
|
||||
cmd = []string{
|
||||
out = clientCLI.RunCmd(
|
||||
"msig", "add-propose",
|
||||
paramFrom,
|
||||
msigRobustAddr,
|
||||
walletAddrs[3].String(),
|
||||
}
|
||||
out = clientCLI.runCmd(cmd)
|
||||
)
|
||||
fmt.Println(out)
|
||||
|
||||
// msig inspect <msig>
|
||||
cmd = []string{"msig", "inspect", "--vesting", "--decode-params", msigRobustAddr}
|
||||
out = clientCLI.runCmd(cmd)
|
||||
out = clientCLI.RunCmd("msig", "inspect", "--vesting", "--decode-params", msigRobustAddr)
|
||||
fmt.Println(out)
|
||||
|
||||
// Expect correct balance
|
||||
@@ -87,7 +84,7 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod
|
||||
// msig add-approve --from=<addr> <msig> <addr> 0 <addr> false
|
||||
txnID := "0"
|
||||
paramFrom = fmt.Sprintf("--from=%s", walletAddrs[1])
|
||||
cmd = []string{
|
||||
out = clientCLI.RunCmd(
|
||||
"msig", "add-approve",
|
||||
paramFrom,
|
||||
msigRobustAddr,
|
||||
@@ -95,7 +92,6 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod
|
||||
txnID,
|
||||
walletAddrs[3].String(),
|
||||
"false",
|
||||
}
|
||||
out = clientCLI.runCmd(cmd)
|
||||
)
|
||||
fmt.Println(out)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/api/test"
|
||||
test2 "github.com/filecoin-project/lotus/node/test"
|
||||
@@ -39,3 +42,46 @@ func StartOneNodeOneMiner(ctx context.Context, t *testing.T, blocktime time.Dura
|
||||
// Create mock CLI
|
||||
return full, fullAddr
|
||||
}
|
||||
|
||||
func StartTwoNodesOneMiner(ctx context.Context, t *testing.T, blocktime time.Duration) ([]test.TestNode, []address.Address) {
|
||||
n, sn := test2.RPCMockSbBuilder(t, test.TwoFull, test.OneMiner)
|
||||
|
||||
fullNode1 := n[0]
|
||||
fullNode2 := n[1]
|
||||
miner := sn[0]
|
||||
|
||||
// Get everyone connected
|
||||
addrs, err := fullNode1.NetAddrsListen(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := fullNode2.NetConnect(ctx, addrs); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := miner.NetConnect(ctx, addrs); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Start mining blocks
|
||||
bm := test.NewBlockMiner(ctx, t, miner, blocktime)
|
||||
bm.MineBlocks()
|
||||
|
||||
// Send some funds to register the second node
|
||||
fullNodeAddr2, err := fullNode2.WalletNew(ctx, types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
test.SendFunds(ctx, t, fullNode1, fullNodeAddr2, abi.NewTokenAmount(1e18))
|
||||
|
||||
// Get the first node's address
|
||||
fullNodeAddr1, err := fullNode1.WalletDefaultAddress(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Create mock CLI
|
||||
return n, []address.Address{fullNodeAddr1, fullNodeAddr2}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user