Skip to content

Commit 4054555

Browse files
committed
loadtest: add sendV2 loadtest
This commit adds a refactored version of the send test, which uses less assertions and rpc calls. This is meant to speed things up compared to the old test, plus offer some more coverage by utilizing normal assets and balances greater than 1 (case for collectibles).
1 parent 01655a4 commit 4054555

File tree

2 files changed

+152
-0
lines changed

2 files changed

+152
-0
lines changed

itest/loadtest/load_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ var loadTestCases = []testCase{
4646
name: "send",
4747
fn: sendTest,
4848
},
49+
{
50+
name: "sendV2",
51+
fn: sendTestV2,
52+
},
4953
{
5054
name: "multisig",
5155
fn: multisigTest,

itest/loadtest/send_test.go

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
prand "math/rand"
7+
"math/rand/v2"
78
"testing"
89
"time"
910

@@ -52,6 +53,153 @@ func sendTest(t *testing.T, ctx context.Context, cfg *Config) {
5253
}
5354
}
5455

56+
// sendTestV2 checks that we are able to send assets between the two nodes. It
57+
// is a more performant and lightweight version of sendTest, as it uses less
58+
// assertions and RPC calls.
59+
func sendTestV2(t *testing.T, ctx context.Context, cfg *Config) {
60+
// Start by initializing all our client connections.
61+
alice, bob, bitcoinClient := initClients(t, ctx, cfg)
62+
63+
ctxb := context.Background()
64+
ctxt, cancel := context.WithTimeout(ctxb, cfg.TestTimeout)
65+
defer cancel()
66+
67+
// Alice is set to be the minter in mintV2, so we use Alice's universe.
68+
var (
69+
uniHost = fmt.Sprintf(
70+
"%s:%d", alice.cfg.Host, alice.cfg.Port,
71+
)
72+
)
73+
74+
// Let's make sure Bob is aware of all the assets that Alice may have
75+
// minted.
76+
itest.SyncUniverses(ctx, t, bob, alice, uniHost, cfg.TestTimeout)
77+
78+
// We now retrieve Alice and Bob's balances just once, and will re-use
79+
// them in future function calls. Any update to the balances will be
80+
// directly applied to these response objects, to skip future calls to
81+
// ListBalances.
82+
resAlice, err := alice.ListBalances(ctx, &taprpc.ListBalancesRequest{
83+
GroupBy: &taprpc.ListBalancesRequest_AssetId{
84+
AssetId: true,
85+
},
86+
})
87+
require.NoError(t, err)
88+
89+
resBob, err := bob.ListBalances(ctx, &taprpc.ListBalancesRequest{
90+
GroupBy: &taprpc.ListBalancesRequest_AssetId{
91+
AssetId: true,
92+
},
93+
})
94+
require.NoError(t, err)
95+
96+
for i := 1; i <= cfg.NumSends; i++ {
97+
var (
98+
sender, receiver *rpcClient
99+
senderAssets map[string]*taprpc.AssetBalance
100+
)
101+
102+
// Assets may be sent in both directions, so we make a random
103+
// draw to conclude who the sender is.
104+
draw := rand.IntN(2)
105+
106+
switch draw {
107+
case 0:
108+
sender = alice
109+
senderAssets = resAlice.AssetBalances
110+
receiver = bob
111+
112+
case 1:
113+
sender = bob
114+
senderAssets = resBob.AssetBalances
115+
receiver = alice
116+
}
117+
118+
sendAssetV2(
119+
t, ctxt, cfg.NumAssets, cfg.SendType, senderAssets,
120+
sender, receiver, bitcoinClient, cfg.TestTimeout,
121+
)
122+
}
123+
}
124+
125+
// sendAssetV2 sends a certain amount of assets of a specific type from a sender
126+
// to a receiver. It will scan the balance of the sender and find a suitable
127+
// asset to carry out the send, then will dispatch the send and assert its
128+
// completion.
129+
func sendAssetV2(t *testing.T, ctx context.Context, numAssets uint64,
130+
assetType taprpc.AssetType, assets map[string]*taprpc.AssetBalance,
131+
sender, receiver *rpcClient, bitcoinClient *rpcclient.Client,
132+
timeout time.Duration) {
133+
134+
// Look over the sender's balances to see if any asset balance qualifies
135+
// for this send.
136+
var (
137+
assetID []byte
138+
balance *taprpc.AssetBalance
139+
)
140+
for _, v := range assets {
141+
if v.Balance >= numAssets &&
142+
v.AssetGenesis.AssetType == assetType {
143+
144+
assetID = v.AssetGenesis.AssetId
145+
balance = v
146+
147+
break
148+
}
149+
}
150+
151+
// No balance satisfies the amount of this send, we can skip this round.
152+
if assetID == nil {
153+
t.Logf("%s could not send %v assets, no available balance",
154+
sender.cfg.Name, numAssets)
155+
156+
return
157+
}
158+
159+
t.Logf("%s sending %v assets to %s", sender.cfg.Name, numAssets,
160+
receiver.cfg.Name)
161+
162+
// Receiver creates the address to receive the assets.
163+
addr, err := receiver.NewAddr(ctx, &taprpc.NewAddrRequest{
164+
AssetId: assetID,
165+
Amt: numAssets,
166+
ProofCourierAddr: fmt.Sprintf(
167+
"%s://%s:%d", proof.UniverseRpcCourierType,
168+
sender.cfg.Host, sender.cfg.Port,
169+
),
170+
})
171+
require.NoError(t, err)
172+
173+
t.Logf("%s created address %v", receiver.cfg.Name, addr.String())
174+
175+
// Sender initiates the send.
176+
_, err = sender.SendAsset(ctx, &taprpc.SendAssetRequest{
177+
TapAddrs: []string{addr.Encoded},
178+
})
179+
require.NoError(t, err)
180+
t.Logf("%s sent assets to address %v", sender.cfg.Name, addr.String())
181+
182+
// We assert the receiver detects the spend.
183+
itest.AssertAddrEventCustomTimeout(
184+
t, receiver, addr, 1, statusDetected, timeout,
185+
)
186+
t.Logf("%s detected send", receiver.cfg.Name)
187+
188+
// Mine a block to confirm the transfer.
189+
itest.MineBlocks(t, bitcoinClient, 1, 0)
190+
t.Log("Mined 1 block")
191+
192+
// Assert that the transfer is now completed
193+
itest.AssertAddrEventCustomTimeout(
194+
t, receiver, addr, 1, statusCompleted, timeout,
195+
)
196+
t.Logf("%s completed send of %v assets", sender.cfg.Name, numAssets)
197+
198+
// If everything completed correctly, subtract the asset amount from the
199+
// sender's asset balance.
200+
balance.Balance -= numAssets
201+
}
202+
55203
// sendAsset sends the given number of assets of the given type from the given
56204
// node to the other node.
57205
func sendAssets(t *testing.T, ctx context.Context, numAssets uint64,

0 commit comments

Comments
 (0)