This repository has been archived by the owner on Apr 23, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sdk/agent: add a first happy path test (#255)
Add a first happy path test that exercises two agents that are connected to each other and successfully open, pay, and close. The agent code was ported over from the console example. The console example was really written to be throw away code, but the agent code within it was well formed enough to be something to build on. It's important we add tests early for the agent before we build too much more into it. This is a first step to closing #225.
- Loading branch information
1 parent
d9efee9
commit 6521706
Showing
3 changed files
with
190 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
package agent | ||
|
||
import ( | ||
"bytes" | ||
"io" | ||
"testing" | ||
"time" | ||
|
||
"github.com/stellar/experimental-payment-channels/sdk/state" | ||
"github.com/stellar/go/keypair" | ||
"github.com/stellar/go/network" | ||
"github.com/stellar/go/txnbuild" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
type sequenceNumberCollector func(accountID *keypair.FromAddress) (int64, error) | ||
|
||
func (f sequenceNumberCollector) GetSequenceNumber(accountID *keypair.FromAddress) (int64, error) { | ||
return f(accountID) | ||
} | ||
|
||
type balanceCollectorFunc func(accountID *keypair.FromAddress, asset state.Asset) (int64, error) | ||
|
||
func (f balanceCollectorFunc) GetBalance(accountID *keypair.FromAddress, asset state.Asset) (int64, error) { | ||
return f(accountID, asset) | ||
} | ||
|
||
type submitterFunc func(tx *txnbuild.Transaction) error | ||
|
||
func (f submitterFunc) SubmitTx(tx *txnbuild.Transaction) error { | ||
return f(tx) | ||
} | ||
|
||
func TestAgent_openPaymentClose(t *testing.T) { | ||
localEscrow := keypair.MustRandom() | ||
localSigner := keypair.MustRandom() | ||
remoteEscrow := keypair.MustRandom() | ||
remoteSigner := keypair.MustRandom() | ||
|
||
// Setup the local agent. | ||
localVars := struct { | ||
submittedTx *txnbuild.Transaction | ||
}{} | ||
localAgent := &Agent{ | ||
ObservationPeriodTime: 20 * time.Second, | ||
ObservationPeriodLedgerGap: 1, | ||
MaxOpenExpiry: 5 * time.Minute, | ||
NetworkPassphrase: network.TestNetworkPassphrase, | ||
SequenceNumberCollector: sequenceNumberCollector(func(accountID *keypair.FromAddress) (int64, error) { | ||
return 1, nil | ||
}), | ||
BalanceCollector: balanceCollectorFunc(func(accountID *keypair.FromAddress, asset state.Asset) (int64, error) { | ||
return 100_0000000, nil | ||
}), | ||
Submitter: submitterFunc(func(tx *txnbuild.Transaction) error { | ||
localVars.submittedTx = tx | ||
return nil | ||
}), | ||
EscrowAccountKey: localEscrow.FromAddress(), | ||
EscrowAccountSigner: localSigner, | ||
LogWriter: io.Discard, | ||
} | ||
|
||
// Setup the remote agent. | ||
remoteVars := struct { | ||
submittedTx *txnbuild.Transaction | ||
}{} | ||
remoteAgent := &Agent{ | ||
ObservationPeriodTime: 20 * time.Second, | ||
ObservationPeriodLedgerGap: 1, | ||
MaxOpenExpiry: 5 * time.Minute, | ||
NetworkPassphrase: network.TestNetworkPassphrase, | ||
SequenceNumberCollector: sequenceNumberCollector(func(accountID *keypair.FromAddress) (int64, error) { | ||
return 1, nil | ||
}), | ||
BalanceCollector: balanceCollectorFunc(func(accountID *keypair.FromAddress, asset state.Asset) (int64, error) { | ||
return 100_0000000, nil | ||
}), | ||
Submitter: submitterFunc(func(tx *txnbuild.Transaction) error { | ||
remoteVars.submittedTx = tx | ||
return nil | ||
}), | ||
EscrowAccountKey: remoteEscrow.FromAddress(), | ||
EscrowAccountSigner: remoteSigner, | ||
LogWriter: io.Discard, | ||
} | ||
|
||
// Connect the two agents. | ||
type ReadWriter struct { | ||
io.Reader | ||
io.Writer | ||
} | ||
localMsgs := bytes.Buffer{} | ||
remoteMsgs := bytes.Buffer{} | ||
localAgent.conn = ReadWriter{ | ||
Reader: &remoteMsgs, | ||
Writer: &localMsgs, | ||
} | ||
remoteAgent.conn = ReadWriter{ | ||
Reader: &localMsgs, | ||
Writer: &remoteMsgs, | ||
} | ||
err := localAgent.hello() | ||
require.NoError(t, err) | ||
err = remoteAgent.receive() | ||
require.NoError(t, err) | ||
err = remoteAgent.hello() | ||
require.NoError(t, err) | ||
err = localAgent.receive() | ||
require.NoError(t, err) | ||
|
||
// Open the channel. | ||
err = localAgent.Open() | ||
require.NoError(t, err) | ||
err = remoteAgent.receive() | ||
require.NoError(t, err) | ||
err = localAgent.receive() | ||
require.NoError(t, err) | ||
|
||
// Expect the open tx to have been submitted. | ||
openTx, err := localAgent.channel.OpenTx() | ||
require.NoError(t, err) | ||
assert.Equal(t, openTx, localVars.submittedTx) | ||
localVars.submittedTx = nil | ||
|
||
// Make a payment. | ||
err = localAgent.Payment("50.0") | ||
require.NoError(t, err) | ||
err = remoteAgent.receive() | ||
require.NoError(t, err) | ||
err = localAgent.receive() | ||
require.NoError(t, err) | ||
|
||
// Make another payment. | ||
err = remoteAgent.Payment("20.0") | ||
require.NoError(t, err) | ||
err = localAgent.receive() | ||
require.NoError(t, err) | ||
err = remoteAgent.receive() | ||
require.NoError(t, err) | ||
|
||
// Expect no txs to have been submitted for payments. | ||
assert.Nil(t, localVars.submittedTx) | ||
assert.Nil(t, remoteVars.submittedTx) | ||
|
||
// Declare the close, and start negotiating for an early close. | ||
err = localAgent.DeclareClose() | ||
require.NoError(t, err) | ||
|
||
// Expect the declaration tx to have been submitted. | ||
localDeclTx, _, err := localAgent.channel.CloseTxs() | ||
require.NoError(t, err) | ||
assert.Equal(t, localDeclTx, localVars.submittedTx) | ||
|
||
// Receive the declaration at the remote and complete negotiation. | ||
err = remoteAgent.receive() | ||
require.NoError(t, err) | ||
err = localAgent.receive() | ||
require.NoError(t, err) | ||
|
||
// Expect the close tx to have been submitted. | ||
_, localCloseTx, err := localAgent.channel.CloseTxs() | ||
require.NoError(t, err) | ||
_, remoteCloseTx, err := remoteAgent.channel.CloseTxs() | ||
require.NoError(t, err) | ||
assert.Equal(t, localCloseTx, remoteCloseTx) | ||
assert.Equal(t, localCloseTx, localVars.submittedTx) | ||
assert.Equal(t, remoteCloseTx, remoteVars.submittedTx) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters