Skip to content

Commit

Permalink
tests for adding funds and wait for payment channel creation, some cl…
Browse files Browse the repository at this point in the history
…eanup
  • Loading branch information
shannonwells committed Apr 13, 2020
1 parent 841b485 commit 0c862db
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 49 deletions.
12 changes: 9 additions & 3 deletions retrievalmarket/impl/clientstates/client_fsm.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ var ClientEvents = fsm.Events{
fsm.Event(rm.ClientEventOpen).
From(rm.DealStatusNew).ToNoChange(),
fsm.Event(rm.ClientEventPaymentChannelErrored).
From(rm.DealStatusAccepted).To(rm.DealStatusFailed).
From(rm.DealStatusPaymentChannelCreating).To(rm.DealStatusFailed).
Action(func(deal *rm.ClientDealState, err error) error {
deal.Message = xerrors.Errorf("getting payment channel: %w", err).Error()
return nil
Expand All @@ -41,7 +41,7 @@ var ClientEvents = fsm.Events{
return nil
}),
fsm.Event(rm.ClientEventPaymentChannelAddingFunds).
From(rm.DealStatusPaymentChannelReady).To(rm.DealStatusPaymentChannelAddingFunds),
FromMany(rm.DealStatusOngoing, rm.DealStatusPaymentChannelReady).To(rm.DealStatusPaymentChannelAddingFunds),
fsm.Event(rm.ClientEventPaymentChannelReady).
FromMany(rm.DealStatusPaymentChannelCreating, rm.DealStatusPaymentChannelAddingFunds).
To(rm.DealStatusPaymentChannelReady).
Expand All @@ -53,11 +53,17 @@ var ClientEvents = fsm.Events{
return nil
}),
fsm.Event(rm.ClientEventAllocateLaneErrored).
From(rm.DealStatusAccepted).To(rm.DealStatusFailed).
From(rm.DealStatusPaymentChannelCreating).To(rm.DealStatusFailed).
Action(func(deal *rm.ClientDealState, err error) error {
deal.Message = xerrors.Errorf("allocating payment lane: %w", err).Error()
return nil
}),
fsm.Event(rm.ClientEventPaymentChannelAddFundsErrored).
From(rm.DealStatusPaymentChannelAddingFunds).To(rm.DealStatusFailed).
Action(func(deal *rm.ClientDealState, err error) error {
deal.Message = xerrors.Errorf("wait for add funds: %w", err).Error()
return nil
}),
fsm.Event(rm.ClientEventWriteDealProposalErrored).
FromAny().To(rm.DealStatusErrored).
Action(func(deal *rm.ClientDealState, err error) error {
Expand Down
9 changes: 3 additions & 6 deletions retrievalmarket/impl/clientstates/client_states.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type ClientDealEnvironment interface {
ConsumeBlock(context.Context, rm.DealID, rm.Block) (uint64, bool, error)
}

// SetupPaymentChannelStart sets up a payment channel for a deal
// SetupPaymentChannelStart initiates setting up a payment channel for a deal
func SetupPaymentChannelStart(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error {
tok, _, err := environment.Node().GetChainHead(ctx.Context())
if err != nil {
Expand All @@ -45,7 +45,6 @@ func WaitForPaymentChannelCreate(ctx fsm.Context, environment ClientDealEnvironm
if err != nil {
return ctx.Trigger(rm.ClientEventPaymentChannelErrored, err)
}
// if successful call allocate lane and trigger ClientEventPaymentChannelReady evt

lane, err := environment.Node().AllocateLane(paych)
if err != nil {
Expand All @@ -54,15 +53,13 @@ func WaitForPaymentChannelCreate(ctx fsm.Context, environment ClientDealEnvironm
return ctx.Trigger(rm.ClientEventPaymentChannelReady, paych, lane)
}

// WaitForPaymentChannelAddFunds waits for funds to be added to a payment channel, then
// WaitForPaymentChannelAddFunds waits for funds to be added to an existing payment channel, then
// signals that payment channel is ready again
func WaitForPaymentChannelAddFunds(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error {
// call wait for funds to be added func,
err := environment.Node().WaitForPaymentChannelAddFunds(*deal.WaitMsgCID)
if err != nil {
return ctx.Trigger(rm.ClientEventPaymentChannelErrored, err)
return ctx.Trigger(rm.ClientEventPaymentChannelAddFundsErrored, err)
}
// then trigger ClientEventPaymentChannelReady evt
return ctx.Trigger(rm.ClientEventPaymentChannelReady, deal.PaymentInfo.PayCh, deal.PaymentInfo.Lane)
}

Expand Down
117 changes: 105 additions & 12 deletions retrievalmarket/impl/clientstates/client_states_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/ipfs/go-cid"
mh "github.com/multiformats/go-multihash"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/filecoin-project/go-fil-markets/retrievalmarket"
Expand Down Expand Up @@ -106,18 +107,110 @@ func TestSetupPaymentChannel(t *testing.T) {
require.Equal(t, dealState.Status, retrievalmarket.DealStatusFailed)
})

// TODO: find the right place for this test
//t.Run("when allocate lane fails", func(t *testing.T) {
// dealState := makeDealState(retrievalmarket.ClientEventPaymentChannelAddingFunds)
// envParams := testnodes.TestRetrievalClientNodeParams{
// PayCh: expectedPayCh,
// Lane: expectedLane,
// LaneError: errors.New("Something went wrong"),
// }
// runSetupPaymentChannel(t, envParams, dealState)
// require.NotEmpty(t, dealState.Message)
// require.Equal(t, dealState.Status, retrievalmarket.DealStatusFailed)
//})
}

func TestWaitForPaymentChannelCreate(t *testing.T) {
ctx := context.Background()
ds := testnet.NewTestRetrievalDealStream(testnet.TestDealStreamParams{})
expectedPayCh := address.TestAddress2
expectedLane := uint64(10)
eventMachine, err := fsm.NewEventProcessor(retrievalmarket.ClientDealState{}, "Status", clientstates.ClientEvents)
require.NoError(t, err)
runWaitForPaychCreate := func(t *testing.T,
params testnodes.TestRetrievalClientNodeParams,
dealState *retrievalmarket.ClientDealState) {
node := testnodes.NewTestRetrievalClientNode(params)
environment := &fakeEnvironment{node, ds, 0, nil}
fsmCtx := fsmtest.NewTestContext(ctx, eventMachine)
err := clientstates.WaitForPaymentChannelCreate(fsmCtx, environment, *dealState)
require.NoError(t, err)
fsmCtx.ReplayEvents(t, dealState)
}
msgCID := testnet.GenerateCids(1)[0]

t.Run("it works", func(t *testing.T) {
dealState := makeDealState(retrievalmarket.DealStatusPaymentChannelCreating)
dealState.WaitMsgCID = &msgCID
params := testnodes.TestRetrievalClientNodeParams{
PayCh: expectedPayCh,
CreatePaychCID: msgCID,
Lane: expectedLane,
}
runWaitForPaychCreate(t, params, dealState)
require.Empty(t, dealState.Message)
assert.Equal(t, dealState.Status, retrievalmarket.DealStatusPaymentChannelReady)
assert.Equal(t, expectedLane, dealState.PaymentInfo.Lane)
})
t.Run("if Wait fails", func(t *testing.T) {
dealState := makeDealState(retrievalmarket.DealStatusPaymentChannelCreating)
dealState.WaitMsgCID = &msgCID
params := testnodes.TestRetrievalClientNodeParams{
PayCh: expectedPayCh,
CreatePaychCID: msgCID,
WaitForChCreateErr: errors.New("boom"),
}
runWaitForPaychCreate(t, params, dealState)
assert.Contains(t, dealState.Message, "boom")
assert.Equal(t, dealState.Status, retrievalmarket.DealStatusFailed)
})

t.Run("if AllocateLane fails", func(t *testing.T) {
dealState := makeDealState(retrievalmarket.DealStatusPaymentChannelCreating)
dealState.WaitMsgCID = &msgCID
params := testnodes.TestRetrievalClientNodeParams{
PayCh: expectedPayCh,
CreatePaychCID: msgCID,
LaneError: errors.New("boom"),
}
runWaitForPaychCreate(t, params, dealState)
assert.Contains(t, dealState.Message, "boom")
assert.Equal(t, dealState.Status, retrievalmarket.DealStatusFailed)
})
}

func TestWaitForPaymentChannelAddFunds(t *testing.T) {
ctx := context.Background()
ds := testnet.NewTestRetrievalDealStream(testnet.TestDealStreamParams{})
expectedPayCh := address.TestAddress2
eventMachine, err := fsm.NewEventProcessor(retrievalmarket.ClientDealState{}, "Status", clientstates.ClientEvents)
require.NoError(t, err)
runWaitForPaychAddFunds := func(t *testing.T,
params testnodes.TestRetrievalClientNodeParams,
dealState *retrievalmarket.ClientDealState) {
node := testnodes.NewTestRetrievalClientNode(params)
environment := &fakeEnvironment{node, ds, 0, nil}
fsmCtx := fsmtest.NewTestContext(ctx, eventMachine)
err := clientstates.WaitForPaymentChannelAddFunds(fsmCtx, environment, *dealState)
require.NoError(t, err)
fsmCtx.ReplayEvents(t, dealState)
}
msgCID := testnet.GenerateCids(1)[0]

t.Run("it works", func(t *testing.T) {
dealState := makeDealState(retrievalmarket.DealStatusPaymentChannelAddingFunds)
dealState.WaitMsgCID = &msgCID
params := testnodes.TestRetrievalClientNodeParams{
AddFundsOnly: true,
PayCh: expectedPayCh,
AddFundsCID: msgCID,
}
runWaitForPaychAddFunds(t, params, dealState)
require.Empty(t, dealState.Message)
assert.Equal(t, dealState.Status, retrievalmarket.DealStatusPaymentChannelReady)
})
t.Run("if Wait fails", func(t *testing.T) {
dealState := makeDealState(retrievalmarket.DealStatusPaymentChannelAddingFunds)
dealState.WaitMsgCID = &msgCID
params := testnodes.TestRetrievalClientNodeParams{
AddFundsOnly: true,
PayCh: expectedPayCh,
AddFundsCID: msgCID,
WaitForAddFundsErr: errors.New("boom"),
}
runWaitForPaychAddFunds(t, params, dealState)
assert.Contains(t, dealState.Message, "boom")
assert.Equal(t, dealState.Status, retrievalmarket.DealStatusFailed)
})
}

func TestProposeDeal(t *testing.T) {
Expand Down
54 changes: 32 additions & 22 deletions retrievalmarket/impl/testnodes/test_retrieval_client_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package testnodes

import (
"context"
"fmt"

"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/abi"
Expand All @@ -15,14 +16,14 @@ import (
// TestRetrievalClientNode is a node adapter for a retrieval client whose responses
// are stubbed
type TestRetrievalClientNode struct {
addFundsOnly bool // set this to true if the payment channel is expected to have been created already
payCh address.Address
payChErr error
createPaychMsgCID, addFundsMsgCID cid.Cid
lane uint64
laneError error
voucher *paych.SignedVoucher
voucherError error
addFundsOnly bool // set this to true to test adding funds to an existing payment channel
payCh address.Address
payChErr error
createPaychMsgCID, addFundsMsgCID cid.Cid
lane uint64
laneError error
voucher *paych.SignedVoucher
voucherError, waitCreateErr, waitAddErr error

allocateLaneRecorder func(address.Address)
createPaymentVoucherRecorder func(voucher *paych.SignedVoucher)
Expand All @@ -31,27 +32,30 @@ type TestRetrievalClientNode struct {

// TestRetrievalClientNodeParams are parameters for initializing a TestRetrievalClientNode
type TestRetrievalClientNodeParams struct {
PayCh address.Address
PayChErr error
CreatePaychCID, AddFundsCID cid.Cid
Lane uint64
LaneError error
Voucher *paych.SignedVoucher
VoucherError error
AllocateLaneRecorder func(address.Address)
PaymentVoucherRecorder func(voucher *paych.SignedVoucher)
PaymentChannelRecorder func(address.Address, address.Address, abi.TokenAmount)
AddFundsOnly bool
PayCh address.Address
PayChErr error
CreatePaychCID, AddFundsCID cid.Cid
Lane uint64
LaneError error
Voucher *paych.SignedVoucher
VoucherError error
AllocateLaneRecorder func(address.Address)
PaymentVoucherRecorder func(voucher *paych.SignedVoucher)
PaymentChannelRecorder func(address.Address, address.Address, abi.TokenAmount)
AddFundsOnly bool
WaitForAddFundsErr, WaitForChCreateErr error
}

var _ retrievalmarket.RetrievalClientNode = &TestRetrievalClientNode{}

// NewTestRetrievalClientNode instantiates a new TestRetrievalClientNode based ont he given params
// NewTestRetrievalClientNode initializes a new TestRetrievalClientNode based on the given params
func NewTestRetrievalClientNode(params TestRetrievalClientNodeParams) *TestRetrievalClientNode {
return &TestRetrievalClientNode{
addFundsOnly: params.AddFundsOnly,
payCh: params.PayCh,
payChErr: params.PayChErr,
waitCreateErr: params.WaitForChCreateErr,
waitAddErr: params.WaitForAddFundsErr,
lane: params.Lane,
laneError: params.LaneError,
voucher: params.Voucher,
Expand Down Expand Up @@ -96,9 +100,15 @@ func (trcn *TestRetrievalClientNode) GetChainHead(ctx context.Context) (shared.T
return shared.TipSetToken{}, 0, nil
}
func (trcn *TestRetrievalClientNode) WaitForPaymentChannelAddFunds(messageCID cid.Cid) error {
return nil
if messageCID != trcn.addFundsMsgCID {
return fmt.Errorf("expected messageCID: %s does not match actual: %s", trcn.addFundsMsgCID, messageCID)
}
return trcn.waitAddErr
}

func (trcn *TestRetrievalClientNode) WaitForPaymentChannelCreation(messageCID cid.Cid) (address.Address, error) {
return trcn.payCh, nil
if messageCID != trcn.createPaychMsgCID {
return address.Undef, fmt.Errorf("expected messageCID: %s does not match actual: %s", trcn.createPaychMsgCID, messageCID)
}
return trcn.payCh, trcn.waitCreateErr
}
10 changes: 4 additions & 6 deletions retrievalmarket/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,17 @@ const (
// successful and we are waiting for it to appear on chain
ClientEventPaymentChannelCreateInitiated

// ClientEventPaymentChannelCreated means a payment channel has been created
ClientEventPaymentChannelCreated

// ClientEventPaymentChannelReady means the newly created payment channel is ready for the
// deal to begin
ClientEventPaymentChannelReady

// ClientEventPaymentChannelAddingFunds means the request to add funds to a payment channel was
// successful and we are waiting for the funds to be sent
// sent and we are waiting for the funds to be added to the payment channel
ClientEventPaymentChannelAddingFunds

// ClientEventPaymentChannelFundsAdded means funds have been added to the payment channel
ClientEventPaymentChannelFundsAdded
// ClientEventPaymentChannelAddingFunds means that adding funds to the payment channel
// failed
ClientEventPaymentChannelAddFundsErrored

// ClientEventWriteDealProposalErrored means a network error writing a deal proposal
ClientEventWriteDealProposalErrored
Expand Down

0 comments on commit 0c862db

Please sign in to comment.