2020-10-20 15:08:25 +00:00
|
|
|
package test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"regexp"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2020-10-27 10:07:54 +00:00
|
|
|
"golang.org/x/xerrors"
|
|
|
|
|
2020-10-20 15:08:25 +00:00
|
|
|
"github.com/filecoin-project/lotus/api/test"
|
|
|
|
"github.com/filecoin-project/lotus/build"
|
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
|
|
|
"github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
lcli "github.com/urfave/cli/v2"
|
|
|
|
)
|
|
|
|
|
|
|
|
// RunClientTest exercises some of the client CLI commands
|
|
|
|
func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode test.TestNode) {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
// Create mock CLI
|
2020-10-27 10:07:54 +00:00
|
|
|
mockCLI := NewMockCLI(ctx, t, cmds)
|
2020-10-26 11:01:33 +00:00
|
|
|
clientCLI := mockCLI.Client(clientNode.ListenAddr)
|
2020-10-20 15:08:25 +00:00
|
|
|
|
|
|
|
// Get the miner address
|
|
|
|
addrs, err := clientNode.StateListMiners(ctx, types.EmptyTSK)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, addrs, 1)
|
|
|
|
|
|
|
|
minerAddr := addrs[0]
|
|
|
|
fmt.Println("Miner:", minerAddr)
|
|
|
|
|
|
|
|
// client query-ask <miner addr>
|
2020-10-26 13:26:46 +00:00
|
|
|
out := clientCLI.RunCmd("client", "query-ask", minerAddr.String())
|
2020-10-20 15:08:25 +00:00
|
|
|
require.Regexp(t, regexp.MustCompile("Ask:"), out)
|
|
|
|
|
|
|
|
// Create a deal (non-interactive)
|
2020-12-01 14:31:05 +00:00
|
|
|
// client deal --start-epoch=<start epoch> <cid> <miner addr> 1000000attofil <duration>
|
2020-10-20 15:08:25 +00:00
|
|
|
res, _, err := test.CreateClientFile(ctx, clientNode, 1)
|
|
|
|
require.NoError(t, err)
|
2020-12-01 14:31:05 +00:00
|
|
|
startEpoch := fmt.Sprintf("--start-epoch=%d", 2<<12)
|
2020-10-20 15:08:25 +00:00
|
|
|
dataCid := res.Root
|
|
|
|
price := "1000000attofil"
|
|
|
|
duration := fmt.Sprintf("%d", build.MinDealDuration)
|
2020-12-01 14:31:05 +00:00
|
|
|
out = clientCLI.RunCmd("client", "deal", startEpoch, dataCid.String(), minerAddr.String(), price, duration)
|
2020-10-20 15:08:25 +00:00
|
|
|
fmt.Println("client deal", out)
|
|
|
|
|
|
|
|
// Create a deal (interactive)
|
|
|
|
// client deal
|
|
|
|
// <cid>
|
|
|
|
// <duration> (in days)
|
|
|
|
// <miner addr>
|
|
|
|
// "no" (verified client)
|
|
|
|
// "yes" (confirm deal)
|
|
|
|
res, _, err = test.CreateClientFile(ctx, clientNode, 2)
|
|
|
|
require.NoError(t, err)
|
|
|
|
dataCid2 := res.Root
|
|
|
|
duration = fmt.Sprintf("%d", build.MinDealDuration/builtin.EpochsInDay)
|
2020-10-26 13:26:46 +00:00
|
|
|
cmd := []string{"client", "deal"}
|
2020-10-20 15:08:25 +00:00
|
|
|
interactiveCmds := []string{
|
|
|
|
dataCid2.String(),
|
|
|
|
duration,
|
|
|
|
minerAddr.String(),
|
2021-02-16 11:32:45 +00:00
|
|
|
"no",
|
2020-10-20 15:08:25 +00:00
|
|
|
"yes",
|
|
|
|
}
|
2020-10-26 11:01:33 +00:00
|
|
|
out = clientCLI.RunInteractiveCmd(cmd, interactiveCmds)
|
2020-10-20 15:08:25 +00:00
|
|
|
fmt.Println("client deal:\n", out)
|
|
|
|
|
|
|
|
// Wait for provider to start sealing deal
|
|
|
|
dealStatus := ""
|
2020-10-27 10:07:54 +00:00
|
|
|
for {
|
2020-10-20 15:08:25 +00:00
|
|
|
// client list-deals
|
2020-10-26 13:26:46 +00:00
|
|
|
out = clientCLI.RunCmd("client", "list-deals")
|
2020-10-20 15:08:25 +00:00
|
|
|
fmt.Println("list-deals:\n", out)
|
|
|
|
|
|
|
|
lines := strings.Split(out, "\n")
|
2020-12-01 10:48:14 +00:00
|
|
|
require.GreaterOrEqual(t, len(lines), 2)
|
2020-10-20 15:08:25 +00:00
|
|
|
re := regexp.MustCompile(`\s+`)
|
|
|
|
parts := re.Split(lines[1], -1)
|
|
|
|
if len(parts) < 4 {
|
|
|
|
require.Fail(t, "bad list-deals output format")
|
|
|
|
}
|
|
|
|
dealStatus = parts[3]
|
|
|
|
fmt.Println(" Deal status:", dealStatus)
|
2020-10-27 10:07:54 +00:00
|
|
|
if dealComplete(t, dealStatus) {
|
|
|
|
break
|
|
|
|
}
|
2020-10-20 15:08:25 +00:00
|
|
|
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Retrieve the first file from the miner
|
|
|
|
// client retrieve <cid> <file path>
|
|
|
|
tmpdir, err := ioutil.TempDir(os.TempDir(), "test-cli-client")
|
|
|
|
require.NoError(t, err)
|
|
|
|
path := filepath.Join(tmpdir, "outfile.dat")
|
2020-10-26 13:26:46 +00:00
|
|
|
out = clientCLI.RunCmd("client", "retrieve", dataCid.String(), path)
|
2020-10-20 15:08:25 +00:00
|
|
|
fmt.Println("retrieve:\n", out)
|
|
|
|
require.Regexp(t, regexp.MustCompile("Success"), out)
|
|
|
|
}
|
2020-10-27 10:07:54 +00:00
|
|
|
|
|
|
|
func dealComplete(t *testing.T, dealStatus string) bool {
|
|
|
|
switch dealStatus {
|
|
|
|
case "StorageDealFailing", "StorageDealError":
|
|
|
|
t.Fatal(xerrors.Errorf("Storage deal failed with status: " + dealStatus))
|
2020-11-20 16:30:17 +00:00
|
|
|
case "StorageDealStaged", "StorageDealAwaitingPreCommit", "StorageDealSealing", "StorageDealActive", "StorageDealExpired", "StorageDealSlashed":
|
2020-10-27 10:07:54 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|