Merge pull request #4598 from filecoin-project/refactor/paych-cli-test

refactor: share code between CLI tests
This commit is contained in:
Łukasz Magiera 2020-10-26 14:51:03 +01:00 committed by GitHub
commit 5a6195feb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 184 additions and 282 deletions

View File

@ -1,9 +1,7 @@
package cli package cli
import ( import (
"bytes"
"context" "context"
"flag"
"fmt" "fmt"
"os" "os"
"regexp" "regexp"
@ -12,24 +10,21 @@ import (
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/require" clitest "github.com/filecoin-project/lotus/cli/test"
"github.com/urfave/cli/v2"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "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/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin/paych" "github.com/filecoin-project/lotus/chain/actors/builtin/paych"
"github.com/filecoin-project/lotus/chain/actors/policy" "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/apibstore"
"github.com/filecoin-project/lotus/api/test" "github.com/filecoin-project/lotus/api/test"
"github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/events" "github.com/filecoin-project/lotus/chain/events"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
builder "github.com/filecoin-project/lotus/node/test"
) )
func init() { func init() {
@ -42,24 +37,24 @@ func init() {
// commands // commands
func TestPaymentChannels(t *testing.T) { func TestPaymentChannels(t *testing.T) {
_ = os.Setenv("BELLMAN_NO_GPU", "1") _ = os.Setenv("BELLMAN_NO_GPU", "1")
clitest.QuietMiningLogs()
blocktime := 5 * time.Millisecond blocktime := 5 * time.Millisecond
ctx := context.Background() ctx := context.Background()
nodes, addrs := startTwoNodesOneMiner(ctx, t, blocktime) nodes, addrs := clitest.StartTwoNodesOneMiner(ctx, t, blocktime)
paymentCreator := nodes[0] paymentCreator := nodes[0]
paymentReceiver := nodes[1] paymentReceiver := nodes[1]
creatorAddr := addrs[0] creatorAddr := addrs[0]
receiverAddr := addrs[1] receiverAddr := addrs[1]
// Create mock CLI // Create mock CLI
mockCLI := newMockCLI(t) mockCLI := clitest.NewMockCLI(t, Commands)
creatorCLI := mockCLI.client(paymentCreator.ListenAddr) creatorCLI := mockCLI.Client(paymentCreator.ListenAddr)
receiverCLI := mockCLI.client(paymentReceiver.ListenAddr) receiverCLI := mockCLI.Client(paymentReceiver.ListenAddr)
// creator: paych add-funds <creator> <receiver> <amount> // creator: paych add-funds <creator> <receiver> <amount>
channelAmt := "100000" channelAmt := "100000"
cmd := []string{creatorAddr.String(), receiverAddr.String(), channelAmt} chstr := creatorCLI.RunCmd("paych", "add-funds", creatorAddr.String(), receiverAddr.String(), channelAmt)
chstr := creatorCLI.runCmd(paychAddFundsCmd, cmd)
chAddr, err := address.NewFromString(chstr) chAddr, err := address.NewFromString(chstr)
require.NoError(t, err) require.NoError(t, err)
@ -67,16 +62,13 @@ func TestPaymentChannels(t *testing.T) {
// creator: paych voucher create <channel> <amount> // creator: paych voucher create <channel> <amount>
voucherAmt := 100 voucherAmt := 100
vamt := strconv.Itoa(voucherAmt) vamt := strconv.Itoa(voucherAmt)
cmd = []string{chAddr.String(), vamt} voucher := creatorCLI.RunCmd("paych", "voucher", "create", chAddr.String(), vamt)
voucher := creatorCLI.runCmd(paychVoucherCreateCmd, cmd)
// receiver: paych voucher add <channel> <voucher> // receiver: paych voucher add <channel> <voucher>
cmd = []string{chAddr.String(), voucher} receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher)
receiverCLI.runCmd(paychVoucherAddCmd, cmd)
// creator: paych settle <channel> // creator: paych settle <channel>
cmd = []string{chAddr.String()} creatorCLI.RunCmd("paych", "settle", chAddr.String())
creatorCLI.runCmd(paychSettleCmd, cmd)
// Wait for the chain to reach the settle height // Wait for the chain to reach the settle height
chState := getPaychState(ctx, t, paymentReceiver, chAddr) chState := getPaychState(ctx, t, paymentReceiver, chAddr)
@ -85,8 +77,7 @@ func TestPaymentChannels(t *testing.T) {
waitForHeight(ctx, t, paymentReceiver, sa) waitForHeight(ctx, t, paymentReceiver, sa)
// receiver: paych collect <channel> // receiver: paych collect <channel>
cmd = []string{chAddr.String()} receiverCLI.RunCmd("paych", "collect", chAddr.String())
receiverCLI.runCmd(paychCloseCmd, cmd)
} }
type voucherSpec struct { type voucherSpec struct {
@ -98,20 +89,21 @@ type voucherSpec struct {
// TestPaymentChannelStatus tests the payment channel status CLI command // TestPaymentChannelStatus tests the payment channel status CLI command
func TestPaymentChannelStatus(t *testing.T) { func TestPaymentChannelStatus(t *testing.T) {
_ = os.Setenv("BELLMAN_NO_GPU", "1") _ = os.Setenv("BELLMAN_NO_GPU", "1")
clitest.QuietMiningLogs()
blocktime := 5 * time.Millisecond blocktime := 5 * time.Millisecond
ctx := context.Background() ctx := context.Background()
nodes, addrs := startTwoNodesOneMiner(ctx, t, blocktime) nodes, addrs := clitest.StartTwoNodesOneMiner(ctx, t, blocktime)
paymentCreator := nodes[0] paymentCreator := nodes[0]
creatorAddr := addrs[0] creatorAddr := addrs[0]
receiverAddr := addrs[1] receiverAddr := addrs[1]
// Create mock CLI // Create mock CLI
mockCLI := newMockCLI(t) mockCLI := clitest.NewMockCLI(t, Commands)
creatorCLI := mockCLI.client(paymentCreator.ListenAddr) creatorCLI := mockCLI.Client(paymentCreator.ListenAddr)
cmd := []string{creatorAddr.String(), receiverAddr.String()} // creator: paych status-by-from-to <creator> <receiver>
out := creatorCLI.runCmd(paychStatusByFromToCmd, cmd) out := creatorCLI.RunCmd("paych", "status-by-from-to", creatorAddr.String(), receiverAddr.String())
fmt.Println(out) fmt.Println(out)
noChannelState := "Channel does not exist" noChannelState := "Channel does not exist"
require.Regexp(t, regexp.MustCompile(noChannelState), out) require.Regexp(t, regexp.MustCompile(noChannelState), out)
@ -120,14 +112,17 @@ func TestPaymentChannelStatus(t *testing.T) {
create := make(chan string) create := make(chan string)
go func() { go func() {
// creator: paych add-funds <creator> <receiver> <amount> // creator: paych add-funds <creator> <receiver> <amount>
cmd := []string{creatorAddr.String(), receiverAddr.String(), fmt.Sprintf("%d", channelAmt)} create <- creatorCLI.RunCmd(
create <- creatorCLI.runCmd(paychAddFundsCmd, cmd) "paych",
"add-funds",
creatorAddr.String(),
receiverAddr.String(),
fmt.Sprintf("%d", channelAmt))
}() }()
// Wait for the output to stop being "Channel does not exist" // Wait for the output to stop being "Channel does not exist"
for regexp.MustCompile(noChannelState).MatchString(out) { for regexp.MustCompile(noChannelState).MatchString(out) {
cmd := []string{creatorAddr.String(), receiverAddr.String()} out = creatorCLI.RunCmd("paych", "status-by-from-to", creatorAddr.String(), receiverAddr.String())
out = creatorCLI.runCmd(paychStatusByFromToCmd, cmd)
} }
fmt.Println(out) fmt.Println(out)
@ -147,8 +142,7 @@ func TestPaymentChannelStatus(t *testing.T) {
// Wait for create channel to complete // Wait for create channel to complete
chstr := <-create chstr := <-create
cmd = []string{chstr} out = creatorCLI.RunCmd("paych", "status", chstr)
out = creatorCLI.runCmd(paychStatusCmd, cmd)
fmt.Println(out) fmt.Println(out)
// Output should have the channel address // Output should have the channel address
require.Regexp(t, regexp.MustCompile("Channel.*"+chstr), out) require.Regexp(t, regexp.MustCompile("Channel.*"+chstr), out)
@ -160,11 +154,9 @@ func TestPaymentChannelStatus(t *testing.T) {
// creator: paych voucher create <channel> <amount> // creator: paych voucher create <channel> <amount>
voucherAmt := uint64(10) voucherAmt := uint64(10)
cmd = []string{chAddr.String(), fmt.Sprintf("%d", voucherAmt)} creatorCLI.RunCmd("paych", "voucher", "create", chAddr.String(), fmt.Sprintf("%d", voucherAmt))
creatorCLI.runCmd(paychVoucherCreateCmd, cmd)
cmd = []string{chstr} out = creatorCLI.RunCmd("paych", "status", chstr)
out = creatorCLI.runCmd(paychStatusCmd, cmd)
fmt.Println(out) fmt.Println(out)
voucherAmtAtto := types.BigMul(types.NewInt(voucherAmt), types.NewInt(build.FilecoinPrecision)) voucherAmtAtto := types.BigMul(types.NewInt(voucherAmt), types.NewInt(build.FilecoinPrecision))
voucherAmtStr := fmt.Sprintf("%d", voucherAmtAtto) voucherAmtStr := fmt.Sprintf("%d", voucherAmtAtto)
@ -176,24 +168,24 @@ func TestPaymentChannelStatus(t *testing.T) {
// channel voucher commands // channel voucher commands
func TestPaymentChannelVouchers(t *testing.T) { func TestPaymentChannelVouchers(t *testing.T) {
_ = os.Setenv("BELLMAN_NO_GPU", "1") _ = os.Setenv("BELLMAN_NO_GPU", "1")
clitest.QuietMiningLogs()
blocktime := 5 * time.Millisecond blocktime := 5 * time.Millisecond
ctx := context.Background() ctx := context.Background()
nodes, addrs := startTwoNodesOneMiner(ctx, t, blocktime) nodes, addrs := clitest.StartTwoNodesOneMiner(ctx, t, blocktime)
paymentCreator := nodes[0] paymentCreator := nodes[0]
paymentReceiver := nodes[1] paymentReceiver := nodes[1]
creatorAddr := addrs[0] creatorAddr := addrs[0]
receiverAddr := addrs[1] receiverAddr := addrs[1]
// Create mock CLI // Create mock CLI
mockCLI := newMockCLI(t) mockCLI := clitest.NewMockCLI(t, Commands)
creatorCLI := mockCLI.client(paymentCreator.ListenAddr) creatorCLI := mockCLI.Client(paymentCreator.ListenAddr)
receiverCLI := mockCLI.client(paymentReceiver.ListenAddr) receiverCLI := mockCLI.Client(paymentReceiver.ListenAddr)
// creator: paych add-funds <creator> <receiver> <amount> // creator: paych add-funds <creator> <receiver> <amount>
channelAmt := "100000" channelAmt := "100000"
cmd := []string{creatorAddr.String(), receiverAddr.String(), channelAmt} chstr := creatorCLI.RunCmd("paych", "add-funds", creatorAddr.String(), receiverAddr.String(), channelAmt)
chstr := creatorCLI.runCmd(paychAddFundsCmd, cmd)
chAddr, err := address.NewFromString(chstr) chAddr, err := address.NewFromString(chstr)
require.NoError(t, err) require.NoError(t, err)
@ -203,39 +195,33 @@ func TestPaymentChannelVouchers(t *testing.T) {
// creator: paych voucher create <channel> <amount> // creator: paych voucher create <channel> <amount>
// Note: implied --lane=0 // Note: implied --lane=0
voucherAmt1 := 100 voucherAmt1 := 100
cmd = []string{chAddr.String(), strconv.Itoa(voucherAmt1)} voucher1 := creatorCLI.RunCmd("paych", "voucher", "create", chAddr.String(), strconv.Itoa(voucherAmt1))
voucher1 := creatorCLI.runCmd(paychVoucherCreateCmd, cmd)
vouchers = append(vouchers, voucherSpec{serialized: voucher1, lane: 0, amt: voucherAmt1}) vouchers = append(vouchers, voucherSpec{serialized: voucher1, lane: 0, amt: voucherAmt1})
// creator: paych voucher create <channel> <amount> --lane=5 // creator: paych voucher create <channel> <amount> --lane=5
lane5 := "--lane=5" lane5 := "--lane=5"
voucherAmt2 := 50 voucherAmt2 := 50
cmd = []string{lane5, chAddr.String(), strconv.Itoa(voucherAmt2)} voucher2 := creatorCLI.RunCmd("paych", "voucher", "create", lane5, chAddr.String(), strconv.Itoa(voucherAmt2))
voucher2 := creatorCLI.runCmd(paychVoucherCreateCmd, cmd)
vouchers = append(vouchers, voucherSpec{serialized: voucher2, lane: 5, amt: voucherAmt2}) vouchers = append(vouchers, voucherSpec{serialized: voucher2, lane: 5, amt: voucherAmt2})
// creator: paych voucher create <channel> <amount> --lane=5 // creator: paych voucher create <channel> <amount> --lane=5
voucherAmt3 := 70 voucherAmt3 := 70
cmd = []string{lane5, chAddr.String(), strconv.Itoa(voucherAmt3)} voucher3 := creatorCLI.RunCmd("paych", "voucher", "create", lane5, chAddr.String(), strconv.Itoa(voucherAmt3))
voucher3 := creatorCLI.runCmd(paychVoucherCreateCmd, cmd)
vouchers = append(vouchers, voucherSpec{serialized: voucher3, lane: 5, amt: voucherAmt3}) vouchers = append(vouchers, voucherSpec{serialized: voucher3, lane: 5, amt: voucherAmt3})
// creator: paych voucher create <channel> <amount> --lane=5 // creator: paych voucher create <channel> <amount> --lane=5
voucherAmt4 := 80 voucherAmt4 := 80
cmd = []string{lane5, chAddr.String(), strconv.Itoa(voucherAmt4)} voucher4 := creatorCLI.RunCmd("paych", "voucher", "create", lane5, chAddr.String(), strconv.Itoa(voucherAmt4))
voucher4 := creatorCLI.runCmd(paychVoucherCreateCmd, cmd)
vouchers = append(vouchers, voucherSpec{serialized: voucher4, lane: 5, amt: voucherAmt4}) vouchers = append(vouchers, voucherSpec{serialized: voucher4, lane: 5, amt: voucherAmt4})
// creator: paych voucher list <channel> --export // creator: paych voucher list <channel> --export
cmd = []string{"--export", chAddr.String()} list := creatorCLI.RunCmd("paych", "voucher", "list", "--export", chAddr.String())
list := creatorCLI.runCmd(paychVoucherListCmd, cmd)
// Check that voucher list output is correct on creator // Check that voucher list output is correct on creator
checkVoucherOutput(t, list, vouchers) checkVoucherOutput(t, list, vouchers)
// creator: paych voucher best-spendable <channel> // creator: paych voucher best-spendable <channel>
cmd = []string{"--export", chAddr.String()} bestSpendable := creatorCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String())
bestSpendable := creatorCLI.runCmd(paychVoucherBestSpendableCmd, cmd)
// Check that best spendable output is correct on creator // Check that best spendable output is correct on creator
bestVouchers := []voucherSpec{ bestVouchers := []voucherSpec{
@ -245,31 +231,25 @@ func TestPaymentChannelVouchers(t *testing.T) {
checkVoucherOutput(t, bestSpendable, bestVouchers) checkVoucherOutput(t, bestSpendable, bestVouchers)
// receiver: paych voucher add <voucher> // receiver: paych voucher add <voucher>
cmd = []string{chAddr.String(), voucher1} receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher1)
receiverCLI.runCmd(paychVoucherAddCmd, cmd)
// receiver: paych voucher add <voucher> // receiver: paych voucher add <voucher>
cmd = []string{chAddr.String(), voucher2} receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher2)
receiverCLI.runCmd(paychVoucherAddCmd, cmd)
// receiver: paych voucher add <voucher> // receiver: paych voucher add <voucher>
cmd = []string{chAddr.String(), voucher3} receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher3)
receiverCLI.runCmd(paychVoucherAddCmd, cmd)
// receiver: paych voucher add <voucher> // receiver: paych voucher add <voucher>
cmd = []string{chAddr.String(), voucher4} receiverCLI.RunCmd("paych", "voucher", "add", chAddr.String(), voucher4)
receiverCLI.runCmd(paychVoucherAddCmd, cmd)
// receiver: paych voucher list <channel> --export // receiver: paych voucher list <channel> --export
cmd = []string{"--export", chAddr.String()} list = receiverCLI.RunCmd("paych", "voucher", "list", "--export", chAddr.String())
list = receiverCLI.runCmd(paychVoucherListCmd, cmd)
// Check that voucher list output is correct on receiver // Check that voucher list output is correct on receiver
checkVoucherOutput(t, list, vouchers) checkVoucherOutput(t, list, vouchers)
// receiver: paych voucher best-spendable <channel> // receiver: paych voucher best-spendable <channel>
cmd = []string{"--export", chAddr.String()} bestSpendable = receiverCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String())
bestSpendable = receiverCLI.runCmd(paychVoucherBestSpendableCmd, cmd)
// Check that best spendable output is correct on receiver // Check that best spendable output is correct on receiver
bestVouchers = []voucherSpec{ bestVouchers = []voucherSpec{
@ -279,12 +259,10 @@ func TestPaymentChannelVouchers(t *testing.T) {
checkVoucherOutput(t, bestSpendable, bestVouchers) checkVoucherOutput(t, bestSpendable, bestVouchers)
// receiver: paych voucher submit <channel> <voucher> // receiver: paych voucher submit <channel> <voucher>
cmd = []string{chAddr.String(), voucher1} receiverCLI.RunCmd("paych", "voucher", "submit", chAddr.String(), voucher1)
receiverCLI.runCmd(paychVoucherSubmitCmd, cmd)
// receiver: paych voucher best-spendable <channel> // receiver: paych voucher best-spendable <channel>
cmd = []string{"--export", chAddr.String()} bestSpendable = receiverCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String())
bestSpendable = receiverCLI.runCmd(paychVoucherBestSpendableCmd, cmd)
// Check that best spendable output no longer includes submitted voucher // Check that best spendable output no longer includes submitted voucher
bestVouchers = []voucherSpec{ bestVouchers = []voucherSpec{
@ -295,12 +273,10 @@ func TestPaymentChannelVouchers(t *testing.T) {
// There are three vouchers in lane 5: 50, 70, 80 // There are three vouchers in lane 5: 50, 70, 80
// Submit the voucher for 50. Best spendable should still be 80. // Submit the voucher for 50. Best spendable should still be 80.
// receiver: paych voucher submit <channel> <voucher> // receiver: paych voucher submit <channel> <voucher>
cmd = []string{chAddr.String(), voucher2} receiverCLI.RunCmd("paych", "voucher", "submit", chAddr.String(), voucher2)
receiverCLI.runCmd(paychVoucherSubmitCmd, cmd)
// receiver: paych voucher best-spendable <channel> // receiver: paych voucher best-spendable <channel>
cmd = []string{"--export", chAddr.String()} bestSpendable = receiverCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String())
bestSpendable = receiverCLI.runCmd(paychVoucherBestSpendableCmd, cmd)
// Check that best spendable output still includes the voucher for 80 // Check that best spendable output still includes the voucher for 80
bestVouchers = []voucherSpec{ bestVouchers = []voucherSpec{
@ -310,12 +286,10 @@ func TestPaymentChannelVouchers(t *testing.T) {
// Submit the voucher for 80 // Submit the voucher for 80
// receiver: paych voucher submit <channel> <voucher> // receiver: paych voucher submit <channel> <voucher>
cmd = []string{chAddr.String(), voucher4} receiverCLI.RunCmd("paych", "voucher", "submit", chAddr.String(), voucher4)
receiverCLI.runCmd(paychVoucherSubmitCmd, cmd)
// receiver: paych voucher best-spendable <channel> // receiver: paych voucher best-spendable <channel>
cmd = []string{"--export", chAddr.String()} bestSpendable = receiverCLI.RunCmd("paych", "voucher", "best-spendable", "--export", chAddr.String())
bestSpendable = receiverCLI.runCmd(paychVoucherBestSpendableCmd, cmd)
// Check that best spendable output no longer includes submitted voucher // Check that best spendable output no longer includes submitted voucher
bestVouchers = []voucherSpec{} bestVouchers = []voucherSpec{}
@ -326,22 +300,27 @@ func TestPaymentChannelVouchers(t *testing.T) {
// is greater than what's left in the channel, voucher create fails // is greater than what's left in the channel, voucher create fails
func TestPaymentChannelVoucherCreateShortfall(t *testing.T) { func TestPaymentChannelVoucherCreateShortfall(t *testing.T) {
_ = os.Setenv("BELLMAN_NO_GPU", "1") _ = os.Setenv("BELLMAN_NO_GPU", "1")
clitest.QuietMiningLogs()
blocktime := 5 * time.Millisecond blocktime := 5 * time.Millisecond
ctx := context.Background() ctx := context.Background()
nodes, addrs := startTwoNodesOneMiner(ctx, t, blocktime) nodes, addrs := clitest.StartTwoNodesOneMiner(ctx, t, blocktime)
paymentCreator := nodes[0] paymentCreator := nodes[0]
creatorAddr := addrs[0] creatorAddr := addrs[0]
receiverAddr := addrs[1] receiverAddr := addrs[1]
// Create mock CLI // Create mock CLI
mockCLI := newMockCLI(t) mockCLI := clitest.NewMockCLI(t, Commands)
creatorCLI := mockCLI.client(paymentCreator.ListenAddr) creatorCLI := mockCLI.Client(paymentCreator.ListenAddr)
// creator: paych add-funds <creator> <receiver> <amount> // creator: paych add-funds <creator> <receiver> <amount>
channelAmt := 100 channelAmt := 100
cmd := []string{creatorAddr.String(), receiverAddr.String(), fmt.Sprintf("%d", channelAmt)} chstr := creatorCLI.RunCmd(
chstr := creatorCLI.runCmd(paychAddFundsCmd, cmd) "paych",
"add-funds",
creatorAddr.String(),
receiverAddr.String(),
fmt.Sprintf("%d", channelAmt))
chAddr, err := address.NewFromString(chstr) chAddr, err := address.NewFromString(chstr)
require.NoError(t, err) require.NoError(t, err)
@ -349,15 +328,25 @@ func TestPaymentChannelVoucherCreateShortfall(t *testing.T) {
// creator: paych voucher create <channel> <amount> --lane=1 // creator: paych voucher create <channel> <amount> --lane=1
voucherAmt1 := 60 voucherAmt1 := 60
lane1 := "--lane=1" lane1 := "--lane=1"
cmd = []string{lane1, chAddr.String(), strconv.Itoa(voucherAmt1)} voucher1 := creatorCLI.RunCmd(
voucher1 := creatorCLI.runCmd(paychVoucherCreateCmd, cmd) "paych",
"voucher",
"create",
lane1,
chAddr.String(),
strconv.Itoa(voucherAmt1))
fmt.Println(voucher1) fmt.Println(voucher1)
// creator: paych voucher create <channel> <amount> --lane=2 // creator: paych voucher create <channel> <amount> --lane=2
lane2 := "--lane=2" lane2 := "--lane=2"
voucherAmt2 := 70 voucherAmt2 := 70
cmd = []string{lane2, chAddr.String(), strconv.Itoa(voucherAmt2)} _, err = creatorCLI.RunCmdRaw(
_, err = creatorCLI.runCmdRaw(paychVoucherCreateCmd, cmd) "paych",
"voucher",
"create",
lane2,
chAddr.String(),
strconv.Itoa(voucherAmt2))
// Should fail because channel doesn't have required amount // Should fail because channel doesn't have required amount
require.Error(t, err) 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 // 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) { func waitForHeight(ctx context.Context, t *testing.T, node test.TestNode, height abi.ChainEpoch) {
atHeight := make(chan struct{}) atHeight := make(chan struct{})

View File

@ -25,8 +25,8 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode)
defer cancel() defer cancel()
// Create mock CLI // Create mock CLI
mockCLI := newMockCLI(t, cmds) mockCLI := NewMockCLI(t, cmds)
clientCLI := mockCLI.client(clientNode.ListenAddr) clientCLI := mockCLI.Client(clientNode.ListenAddr)
// Get the miner address // Get the miner address
addrs, err := clientNode.StateListMiners(ctx, types.EmptyTSK) 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) fmt.Println("Miner:", minerAddr)
// client query-ask <miner addr> // client query-ask <miner addr>
cmd := []string{ out := clientCLI.RunCmd("client", "query-ask", minerAddr.String())
"client", "query-ask", minerAddr.String(),
}
out := clientCLI.runCmd(cmd)
require.Regexp(t, regexp.MustCompile("Ask:"), out) require.Regexp(t, regexp.MustCompile("Ask:"), out)
// Create a deal (non-interactive) // Create a deal (non-interactive)
@ -50,10 +47,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode)
dataCid := res.Root dataCid := res.Root
price := "1000000attofil" price := "1000000attofil"
duration := fmt.Sprintf("%d", build.MinDealDuration) duration := fmt.Sprintf("%d", build.MinDealDuration)
cmd = []string{ out = clientCLI.RunCmd("client", "deal", dataCid.String(), minerAddr.String(), price, duration)
"client", "deal", dataCid.String(), minerAddr.String(), price, duration,
}
out = clientCLI.runCmd(cmd)
fmt.Println("client deal", out) fmt.Println("client deal", out)
// Create a deal (interactive) // Create a deal (interactive)
@ -67,9 +61,7 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode)
require.NoError(t, err) require.NoError(t, err)
dataCid2 := res.Root dataCid2 := res.Root
duration = fmt.Sprintf("%d", build.MinDealDuration/builtin.EpochsInDay) duration = fmt.Sprintf("%d", build.MinDealDuration/builtin.EpochsInDay)
cmd = []string{ cmd := []string{"client", "deal"}
"client", "deal",
}
interactiveCmds := []string{ interactiveCmds := []string{
dataCid2.String(), dataCid2.String(),
duration, duration,
@ -77,15 +69,14 @@ func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode)
"no", "no",
"yes", "yes",
} }
out = clientCLI.runInteractiveCmd(cmd, interactiveCmds) out = clientCLI.RunInteractiveCmd(cmd, interactiveCmds)
fmt.Println("client deal:\n", out) fmt.Println("client deal:\n", out)
// Wait for provider to start sealing deal // Wait for provider to start sealing deal
dealStatus := "" dealStatus := ""
for dealStatus != "StorageDealSealing" { for dealStatus != "StorageDealSealing" {
// client list-deals // client list-deals
cmd = []string{"client", "list-deals"} out = clientCLI.RunCmd("client", "list-deals")
out = clientCLI.runCmd(cmd)
fmt.Println("list-deals:\n", out) fmt.Println("list-deals:\n", out)
lines := strings.Split(out, "\n") 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") tmpdir, err := ioutil.TempDir(os.TempDir(), "test-cli-client")
require.NoError(t, err) require.NoError(t, err)
path := filepath.Join(tmpdir, "outfile.dat") path := filepath.Join(tmpdir, "outfile.dat")
cmd = []string{ out = clientCLI.RunCmd("client", "retrieve", dataCid.String(), path)
"client", "retrieve", dataCid.String(), path,
}
out = clientCLI.runCmd(cmd)
fmt.Println("retrieve:\n", out) fmt.Println("retrieve:\n", out)
require.Regexp(t, regexp.MustCompile("Success"), out) require.Regexp(t, regexp.MustCompile("Success"), out)
} }

View File

@ -11,14 +11,14 @@ import (
lcli "github.com/urfave/cli/v2" lcli "github.com/urfave/cli/v2"
) )
type mockCLI struct { type MockCLI struct {
t *testing.T t *testing.T
cmds []*lcli.Command cmds []*lcli.Command
cctx *lcli.Context cctx *lcli.Context
out *bytes.Buffer 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 // Create a CLI App with an --api-url flag so that we can specify which node
// the command should be executed against // the command should be executed against
app := &lcli.App{ app := &lcli.App{
@ -36,15 +36,15 @@ func newMockCLI(t *testing.T, cmds []*lcli.Command) *mockCLI {
app.Setup() app.Setup()
cctx := lcli.NewContext(app, &flag.FlagSet{}, nil) 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 { func (c *MockCLI) Client(addr multiaddr.Multiaddr) *MockCLIClient {
return &mockCLIClient{t: c.t, cmds: c.cmds, addr: addr, cctx: c.cctx, out: c.out} return &MockCLIClient{t: c.t, cmds: c.cmds, addr: addr, cctx: c.cctx, out: c.out}
} }
// mockCLIClient runs commands against a particular node // MockCLIClient runs commands against a particular node
type mockCLIClient struct { type MockCLIClient struct {
t *testing.T t *testing.T
cmds []*lcli.Command cmds []*lcli.Command
addr multiaddr.Multiaddr addr multiaddr.Multiaddr
@ -52,42 +52,48 @@ type mockCLIClient struct {
out *bytes.Buffer out *bytes.Buffer
} }
func (c *mockCLIClient) run(cmd []string, params []string, args []string) string { func (c *MockCLIClient) RunCmd(input ...string) string {
// Add parameter --api-url=<node api listener address> out, err := c.RunCmdRaw(input...)
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:])
require.NoError(c.t, err) require.NoError(c.t, err)
return out return out
} }
func (c *mockCLIClient) cmdByNameSub(name string, sub string) *lcli.Command { // Given an input, find the corresponding command or sub-command.
for _, c := range c.cmds { // eg "paych add-funds"
if c.Name == name { func (c *MockCLIClient) cmdByNameSub(input []string) (*lcli.Command, []string) {
for _, s := range c.Subcommands { name := input[0]
if s.Name == sub { for _, cmd := range c.cmds {
return s 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> // prepend --api-url=<node api listener address>
apiFlag := "--api-url=" + c.addr.String() apiFlag := "--api-url=" + c.addr.String()
input = append([]string{apiFlag}, input...) input = append([]string{apiFlag}, input...)
@ -104,7 +110,7 @@ func (c *mockCLIClient) runCmdRaw(cmd *lcli.Command, input []string) (string, er
return str, err 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) // Apply app level flags (so we can process --api-url flag)
fs := &flag.FlagSet{} fs := &flag.FlagSet{}
for _, f := range c.cctx.App.Flags { for _, f := range c.cctx.App.Flags {
@ -123,11 +129,11 @@ func (c *mockCLIClient) flagSet(cmd *lcli.Command) *flag.FlagSet {
return fs 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") 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) c.cctx.App.Metadata["stdin"] = bytes.NewBufferString(s)
} }

View File

@ -18,8 +18,8 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod
ctx := context.Background() ctx := context.Background()
// Create mock CLI // Create mock CLI
mockCLI := newMockCLI(t, cmds) mockCLI := NewMockCLI(t, cmds)
clientCLI := mockCLI.client(clientNode.ListenAddr) clientCLI := mockCLI.Client(clientNode.ListenAddr)
// Create some wallets on the node to use for testing multisig // Create some wallets on the node to use for testing multisig
var walletAddrs []address.Address var walletAddrs []address.Address
@ -39,7 +39,7 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod
paramDuration := "--duration=50" paramDuration := "--duration=50"
paramRequired := fmt.Sprintf("--required=%d", threshold) paramRequired := fmt.Sprintf("--required=%d", threshold)
paramValue := fmt.Sprintf("--value=%dattofil", amtAtto) paramValue := fmt.Sprintf("--value=%dattofil", amtAtto)
cmd := []string{ out := clientCLI.RunCmd(
"msig", "create", "msig", "create",
paramRequired, paramRequired,
paramDuration, paramDuration,
@ -47,8 +47,7 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod
walletAddrs[0].String(), walletAddrs[0].String(),
walletAddrs[1].String(), walletAddrs[1].String(),
walletAddrs[2].String(), walletAddrs[2].String(),
} )
out := clientCLI.runCmd(cmd)
fmt.Println(out) fmt.Println(out)
// Extract msig robust address from output // 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 // Propose to add a new address to the msig
// msig add-propose --from=<addr> <msig> <addr> // msig add-propose --from=<addr> <msig> <addr>
paramFrom := fmt.Sprintf("--from=%s", walletAddrs[0]) paramFrom := fmt.Sprintf("--from=%s", walletAddrs[0])
cmd = []string{ out = clientCLI.RunCmd(
"msig", "add-propose", "msig", "add-propose",
paramFrom, paramFrom,
msigRobustAddr, msigRobustAddr,
walletAddrs[3].String(), walletAddrs[3].String(),
} )
out = clientCLI.runCmd(cmd)
fmt.Println(out) fmt.Println(out)
// msig inspect <msig> // msig inspect <msig>
cmd = []string{"msig", "inspect", "--vesting", "--decode-params", msigRobustAddr} out = clientCLI.RunCmd("msig", "inspect", "--vesting", "--decode-params", msigRobustAddr)
out = clientCLI.runCmd(cmd)
fmt.Println(out) fmt.Println(out)
// Expect correct balance // 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 // msig add-approve --from=<addr> <msig> <addr> 0 <addr> false
txnID := "0" txnID := "0"
paramFrom = fmt.Sprintf("--from=%s", walletAddrs[1]) paramFrom = fmt.Sprintf("--from=%s", walletAddrs[1])
cmd = []string{ out = clientCLI.RunCmd(
"msig", "add-approve", "msig", "add-approve",
paramFrom, paramFrom,
msigRobustAddr, msigRobustAddr,
@ -95,7 +92,6 @@ func RunMultisigTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNod
txnID, txnID,
walletAddrs[3].String(), walletAddrs[3].String(),
"false", "false",
} )
out = clientCLI.runCmd(cmd)
fmt.Println(out) fmt.Println(out)
} }

View File

@ -5,6 +5,9 @@ import (
"testing" "testing"
"time" "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/go-address"
"github.com/filecoin-project/lotus/api/test" "github.com/filecoin-project/lotus/api/test"
test2 "github.com/filecoin-project/lotus/node/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 // Create mock CLI
return full, fullAddr 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}
}