2021-06-18 18:45:29 +00:00
|
|
|
package kit
|
2021-06-14 10:07:50 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"math/rand"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"regexp"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2022-06-14 15:00:51 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
lcli "github.com/urfave/cli/v2"
|
|
|
|
|
2021-06-14 10:07:50 +00:00
|
|
|
"github.com/filecoin-project/lotus/api"
|
|
|
|
"github.com/filecoin-project/lotus/build"
|
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
2023-11-13 23:59:34 +00:00
|
|
|
"github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
2021-06-14 10:07:50 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// RunClientTest exercises some of the Client CLI commands
|
2021-06-18 18:23:32 +00:00
|
|
|
func RunClientTest(t *testing.T, cmds []*lcli.Command, clientNode *TestFullNode) {
|
2021-06-14 10:07:50 +00:00
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
// Create mock CLI
|
2021-08-12 18:01:24 +00:00
|
|
|
mockCLI := NewMockCLI(ctx, t, cmds, api.NodeFull)
|
2021-06-14 10:07:50 +00:00
|
|
|
clientCLI := mockCLI.Client(clientNode.ListenAddr)
|
|
|
|
|
|
|
|
// 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>
|
|
|
|
out := clientCLI.RunCmd("client", "query-ask", minerAddr.String())
|
|
|
|
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>
|
2021-06-14 10:07:50 +00:00
|
|
|
res, _, _, err := CreateImportFile(ctx, clientNode, 1, 0)
|
|
|
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
startEpoch := fmt.Sprintf("--start-epoch=%d", 2<<12)
|
|
|
|
dataCid := res.Root
|
|
|
|
price := "1000000attofil"
|
|
|
|
duration := fmt.Sprintf("%d", build.MinDealDuration)
|
|
|
|
out = clientCLI.RunCmd("client", "deal", startEpoch, dataCid.String(), minerAddr.String(), price, duration)
|
|
|
|
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 = CreateImportFile(ctx, clientNode, 2, 0)
|
|
|
|
require.NoError(t, err)
|
|
|
|
dataCid2 := res.Root
|
|
|
|
duration = fmt.Sprintf("%d", build.MinDealDuration/builtin.EpochsInDay)
|
|
|
|
cmd := []string{"client", "deal"}
|
|
|
|
interactiveCmds := []string{
|
|
|
|
dataCid2.String(),
|
|
|
|
duration,
|
|
|
|
minerAddr.String(),
|
|
|
|
"no",
|
|
|
|
"yes",
|
|
|
|
}
|
|
|
|
out = clientCLI.RunInteractiveCmd(cmd, interactiveCmds)
|
|
|
|
fmt.Println("client deal:\n", out)
|
|
|
|
|
|
|
|
// Wait for provider to start sealing deal
|
|
|
|
dealStatus := ""
|
|
|
|
for {
|
|
|
|
// client list-deals
|
2023-05-03 20:49:23 +00:00
|
|
|
out = clientCLI.RunCmd("client", "list-deals", "--show-failed")
|
2021-06-14 10:07:50 +00:00
|
|
|
fmt.Println("list-deals:\n", out)
|
|
|
|
|
|
|
|
lines := strings.Split(out, "\n")
|
|
|
|
require.GreaterOrEqual(t, len(lines), 2)
|
|
|
|
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)
|
|
|
|
|
|
|
|
st := CategorizeDealState(dealStatus)
|
|
|
|
require.NotEqual(t, TestDealStateFailed, st)
|
|
|
|
if st == TestDealStateComplete {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
}
|
|
|
|
|
2021-12-17 17:01:12 +00:00
|
|
|
// client retrieval-ask --size=1 <miner addr> <data CID>
|
|
|
|
out = clientCLI.RunCmd("client", "retrieval-ask", "--size=1", minerAddr.String(), dataCid.String())
|
2021-12-17 14:50:51 +00:00
|
|
|
require.Regexp(t, regexp.MustCompile("Ask:"), out)
|
|
|
|
fmt.Println("retrieval ask:\n", out)
|
|
|
|
|
2021-06-14 10:07:50 +00:00
|
|
|
// Retrieve the first file from the Miner
|
|
|
|
// client retrieve <cid> <file path>
|
2023-03-29 19:24:07 +00:00
|
|
|
tmpdir, err := os.MkdirTemp(os.TempDir(), "test-cli-client")
|
2021-06-14 10:07:50 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
path := filepath.Join(tmpdir, "outfile.dat")
|
2021-11-18 08:07:12 +00:00
|
|
|
|
2022-03-02 11:04:50 +00:00
|
|
|
// Wait for client retrieve to succeed.
|
2021-11-18 08:07:12 +00:00
|
|
|
for {
|
|
|
|
out = clientCLI.RunCmd("client", "retrieve", dataCid.String(), path)
|
|
|
|
fmt.Println("retrieve:\n", out)
|
|
|
|
if strings.Contains(out, "Success") {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2021-06-14 10:07:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func CreateImportFile(ctx context.Context, client api.FullNode, rseed int, size int) (res *api.ImportRes, path string, data []byte, err error) {
|
|
|
|
data, path, err = createRandomFile(rseed, size)
|
|
|
|
if err != nil {
|
|
|
|
return nil, "", nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
res, err = client.ClientImport(ctx, api.FileRef{Path: path})
|
|
|
|
if err != nil {
|
|
|
|
return nil, "", nil, err
|
|
|
|
}
|
|
|
|
return res, path, data, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func createRandomFile(rseed, size int) ([]byte, string, error) {
|
|
|
|
if size == 0 {
|
|
|
|
size = 1600
|
|
|
|
}
|
|
|
|
data := make([]byte, size)
|
|
|
|
rand.New(rand.NewSource(int64(rseed))).Read(data)
|
|
|
|
|
2023-03-29 19:24:07 +00:00
|
|
|
dir, err := os.MkdirTemp(os.TempDir(), "test-make-deal-")
|
2021-06-14 10:07:50 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
path := filepath.Join(dir, "sourcefile.dat")
|
2023-03-29 19:24:07 +00:00
|
|
|
err = os.WriteFile(path, data, 0644)
|
2021-06-14 10:07:50 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
return data, path, nil
|
|
|
|
}
|