Skip to content

Commit 6d14ed1

Browse files
committed
e2e: Increase logging detail to improve traceability
1 parent 7faba53 commit 6d14ed1

File tree

9 files changed

+219
-148
lines changed

9 files changed

+219
-148
lines changed

tests/e2e/banff/suites.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ var _ = ginkgo.Describe("[Banff]", func() {
2929
),
3030
func() {
3131
keychain := e2e.Env.NewKeychain(1)
32-
wallet := e2e.Env.NewWallet(keychain)
32+
wallet := e2e.Env.NewWallet(keychain, e2e.Env.GetRandomNodeURI())
3333

3434
// Get the P-chain and the X-chain wallets
3535
pWallet := wallet.P()

tests/e2e/c/interchain_workflow.go

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ var _ = e2e.DescribeCChain("[Interchain Workflow]", func() {
3232
)
3333

3434
ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() {
35+
// Select a random node URI to use for both the eth client and
36+
// the wallet to avoid having to verify that all nodes are at
37+
// the same height before initializing the wallet.
38+
nodeURI := e2e.Env.GetRandomNodeURI()
39+
3540
ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to")
3641
senderKey := e2e.Env.AllocateFundedKey()
3742
senderEthAddress := evm.GetEthAddress(senderKey)
@@ -40,11 +45,7 @@ var _ = e2e.DescribeCChain("[Interchain Workflow]", func() {
4045
require.NoError(err)
4146
recipientEthAddress := evm.GetEthAddress(recipientKey)
4247

43-
// Select a random node URI to use for both the eth client and
44-
// the wallet to avoid having to verify that all nodes are at
45-
// the same height before initializing the wallet.
46-
nodeURI := e2e.Env.GetRandomNodeURI()
47-
ethClient := e2e.Env.NewEthClientForURI(nodeURI)
48+
ethClient := e2e.Env.NewEthClient(nodeURI)
4849

4950
ginkgo.By("sending funds from one address to another on the C-Chain", func() {
5051
// Create transaction
@@ -68,7 +69,7 @@ var _ = e2e.DescribeCChain("[Interchain Workflow]", func() {
6869
signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA())
6970
require.NoError(err)
7071

71-
require.NoError(ethClient.SendTransaction(e2e.DefaultContext(), signedTx))
72+
_ = e2e.SendEthTransaction(ethClient, signedTx)
7273

7374
ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds")
7475
e2e.Eventually(func() bool {
@@ -83,7 +84,7 @@ var _ = e2e.DescribeCChain("[Interchain Workflow]", func() {
8384
// matches on-chain state.
8485
ginkgo.By("initializing a keychain and associated wallet")
8586
keychain := secp256k1fx.NewKeychain(senderKey, recipientKey)
86-
baseWallet := e2e.Env.NewWalletForURI(keychain, nodeURI)
87+
baseWallet := e2e.Env.NewWallet(keychain, nodeURI)
8788
xWallet := baseWallet.X()
8889
cWallet := baseWallet.C()
8990
pWallet := baseWallet.P()
@@ -111,21 +112,23 @@ var _ = e2e.DescribeCChain("[Interchain Workflow]", func() {
111112
}
112113

113114
ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() {
114-
_, err := cWallet.IssueExportTx(
115-
xWallet.BlockchainID(),
116-
exportOutputs,
117-
e2e.WithDefaultContext(),
115+
e2e.LogTxAndCheck(
116+
cWallet.IssueExportTx(
117+
xWallet.BlockchainID(),
118+
exportOutputs,
119+
e2e.WithDefaultContext(),
120+
),
118121
)
119-
require.NoError(err)
120122
})
121123

122124
ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() {
123-
_, err := xWallet.IssueImportTx(
124-
cWallet.BlockchainID(),
125-
&recipientOwner,
126-
e2e.WithDefaultContext(),
125+
e2e.LogTxAndCheck(
126+
xWallet.IssueImportTx(
127+
cWallet.BlockchainID(),
128+
&recipientOwner,
129+
e2e.WithDefaultContext(),
130+
),
127131
)
128-
require.NoError(err)
129132
})
130133

131134
ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() {
@@ -137,21 +140,23 @@ var _ = e2e.DescribeCChain("[Interchain Workflow]", func() {
137140
})
138141

139142
ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() {
140-
_, err := cWallet.IssueExportTx(
141-
constants.PlatformChainID,
142-
exportOutputs,
143-
e2e.WithDefaultContext(),
143+
e2e.LogTxAndCheck(
144+
cWallet.IssueExportTx(
145+
constants.PlatformChainID,
146+
exportOutputs,
147+
e2e.WithDefaultContext(),
148+
),
144149
)
145-
require.NoError(err)
146150
})
147151

148152
ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() {
149-
_, err = pWallet.IssueImportTx(
150-
cWallet.BlockchainID(),
151-
&recipientOwner,
152-
e2e.WithDefaultContext(),
153+
e2e.LogTxAndCheck(
154+
pWallet.IssueImportTx(
155+
cWallet.BlockchainID(),
156+
&recipientOwner,
157+
e2e.WithDefaultContext(),
158+
),
153159
)
154-
require.NoError(err)
155160
})
156161

157162
ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() {

tests/e2e/e2e.go

Lines changed: 66 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package e2e
77
import (
88
"context"
99
"encoding/json"
10+
"errors"
1011
"fmt"
1112
"math/rand"
1213
"strings"
@@ -16,8 +17,13 @@ import (
1617

1718
"github.com/stretchr/testify/require"
1819

20+
"github.com/ava-labs/coreth/core/types"
1921
"github.com/ava-labs/coreth/ethclient"
22+
"github.com/ava-labs/coreth/interfaces"
2023

24+
"golang.org/x/exp/maps"
25+
26+
"github.com/ava-labs/avalanchego/ids"
2127
"github.com/ava-labs/avalanchego/tests"
2228
"github.com/ava-labs/avalanchego/tests/fixture"
2329
"github.com/ava-labs/avalanchego/tests/fixture/testnet"
@@ -58,7 +64,7 @@ type TestEnvironment struct {
5864
// The directory where the test network configuration is stored
5965
NetworkDir string
6066
// URIs used to access the API endpoints of nodes of the network
61-
URIs []string
67+
URIs map[ids.NodeID]string
6268
// The URI used to access the http server that allocates test data
6369
TestDataServerURI string
6470

@@ -78,7 +84,11 @@ func InitTestEnvironment(envBytes []byte) {
7884
// nodes.
7985
func (te *TestEnvironment) GetRandomNodeURI() string {
8086
r := rand.New(rand.NewSource(time.Now().Unix())) //#nosec G404
81-
return te.URIs[r.Intn(len(te.URIs))]
87+
nodeIDs := maps.Keys(te.URIs)
88+
nodeID := nodeIDs[r.Intn(len(nodeIDs))]
89+
uri := te.URIs[nodeID]
90+
tests.Outf("{{blue}} targeting node %s with URI: %s{{/}}\n", nodeID, uri)
91+
return uri
8292
}
8393

8494
// Retrieve the network to target for testing.
@@ -92,6 +102,7 @@ func (te *TestEnvironment) GetNetwork() testnet.Network {
92102
func (te *TestEnvironment) AllocateFundedKeys(count int) []*secp256k1.PrivateKey {
93103
keys, err := fixture.AllocateFundedKeys(te.TestDataServerURI, count)
94104
te.require.NoError(err)
105+
tests.Outf("{{blue}} allocated funded key(s): %+v{{/}}\n", keys)
95106
return keys
96107
}
97108

@@ -102,19 +113,14 @@ func (te *TestEnvironment) AllocateFundedKey() *secp256k1.PrivateKey {
102113

103114
// Create a new keychain with the specified number of test keys.
104115
func (te *TestEnvironment) NewKeychain(count int) *secp256k1fx.Keychain {
105-
tests.Outf("{{blue}} initializing keychain with %d keys {{/}}\n", count)
106116
keys := te.AllocateFundedKeys(count)
117+
tests.Outf("{{blue}} initializing keychain with %d key(s) {{/}}\n", count)
107118
return secp256k1fx.NewKeychain(keys...)
108119
}
109120

110-
// Create a new wallet for the provided keychain against a random node URI.
111-
func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain) primary.Wallet {
112-
return te.NewWalletForURI(keychain, te.GetRandomNodeURI())
113-
}
114-
115121
// Create a new wallet for the provided keychain against the specified node URI.
116-
func (te *TestEnvironment) NewWalletForURI(keychain *secp256k1fx.Keychain, uri string) primary.Wallet {
117-
tests.Outf("{{blue}} initializing a new wallet {{/}}\n")
122+
func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, uri string) primary.Wallet {
123+
tests.Outf("{{blue}} initializing a new wallet for URI: %s {{/}}\n", uri)
118124
wallet, err := primary.MakeWallet(DefaultContext(), &primary.WalletConfig{
119125
URI: uri,
120126
AVAXKeychain: keychain,
@@ -124,13 +130,9 @@ func (te *TestEnvironment) NewWalletForURI(keychain *secp256k1fx.Keychain, uri s
124130
return wallet
125131
}
126132

127-
// Create a new eth client targeting a random node.
128-
func (te *TestEnvironment) NewEthClient() ethclient.Client {
129-
return te.NewEthClientForURI(te.GetRandomNodeURI())
130-
}
131-
132133
// Create a new eth client targeting the specified node URI.
133-
func (te *TestEnvironment) NewEthClientForURI(nodeURI string) ethclient.Client {
134+
func (te *TestEnvironment) NewEthClient(nodeURI string) ethclient.Client {
135+
tests.Outf("{{blue}} initializing a new eth client for URI: %s {{/}}\n", nodeURI)
134136
nodeAddress := strings.Split(nodeURI, "//")[1]
135137
uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress)
136138
client, err := ethclient.Dial(uri)
@@ -198,3 +200,51 @@ func WaitForHealthy(node testnet.Node) {
198200
defer cancel()
199201
require.NoError(ginkgo.GinkgoT(), testnet.WaitForHealthy(ctx, node))
200202
}
203+
204+
// Interface to allow logging any type of transaction that has an ID method.
205+
type LoggableTx interface {
206+
ID() ids.ID
207+
}
208+
209+
// Ensures transaction id is logged if the transaction is non-nil. Should be
210+
// called before checking for an error to ensure traceability in the event
211+
// of a transaction being submitted but failing to be accepted.
212+
func LogTx(tx LoggableTx) {
213+
if tx != nil {
214+
tests.Outf(" tx id: %s\n", tx.ID())
215+
}
216+
}
217+
218+
// Ensures transaction id is logged if the transaction is non-nil and check
219+
// if an error occurred.
220+
func LogTxAndCheck(tx LoggableTx, err error) {
221+
LogTx(tx)
222+
require.NoError(ginkgo.GinkgoT(), err)
223+
}
224+
225+
// Sends an eth transaction, waits for the transaction receipt to be issued
226+
// and checks that the receipt indicates success.
227+
func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt {
228+
require := require.New(ginkgo.GinkgoT())
229+
230+
txID := signedTx.Hash()
231+
tests.Outf(" eth tx id: %s\n", txID)
232+
233+
require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx))
234+
235+
// Wait for the receipt
236+
var receipt *types.Receipt
237+
Eventually(func() bool {
238+
var err error
239+
receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID)
240+
if errors.Is(err, interfaces.NotFound) {
241+
return false // Transaction is still pending
242+
}
243+
require.NoError(err)
244+
return true
245+
}, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout")
246+
247+
// Retrieve the contract address
248+
require.Equal(receipt.Status, types.ReceiptStatusSuccessful)
249+
return receipt
250+
}

0 commit comments

Comments
 (0)