Skip to content

Commit

Permalink
adding e2e tests for 09-localhost (#3119)
Browse files Browse the repository at this point in the history
* use temporary relayer tag for e2e testing localhost

* WIP commiting

* updating codec and handling txResp

* WIP scaffold happy path out

* adding some temporary todos

* adding msg response unmarshalling, and adding interchain accounts handshake test

* adding ica send packet testing, cleanup..etc

* adding separate test suite for localhost transfer tests (#3144)

* add separate test suite struct for ICA localhost

* fixing testsuite embedding

* review suggestions - events func and nits

* testcase naming

---------

Co-authored-by: Cian Hatton <cian@interchain.io>
  • Loading branch information
damiannolan and chatton committed Feb 15, 2023
1 parent 8e11eb1 commit 63111de
Show file tree
Hide file tree
Showing 7 changed files with 423 additions and 5 deletions.
4 changes: 2 additions & 2 deletions e2e/relayer/relayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ const (
Rly = "rly"
Hermes = "hermes"

cosmosRelayerRepository = "ghcr.io/cosmos/relayer"
cosmosRelayerUser = "100:1000" // docker run -it --rm --entrypoint echo ghcr.io/cosmos/relayer "$(id -u):$(id -g)"
cosmosRelayerRepository = "damiannolan/rly" //"ghcr.io/cosmos/relayer"
cosmosRelayerUser = "100:1000" // docker run -it --rm --entrypoint echo ghcr.io/cosmos/relayer "$(id -u):$(id -g)"
)

// Config holds configuration values for the relayer used in the tests.
Expand Down
2 changes: 1 addition & 1 deletion e2e/testconfig/testconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const (
defaultBinary = "simd"
// defaultRlyTag is the tag that will be used if no relayer tag is specified.
// all images are here https://github.com/cosmos/relayer/pkgs/container/relayer/versions
defaultRlyTag = "andrew-tendermint_v0.37" // "v2.2.0"
defaultRlyTag = "latest" // "andrew-tendermint_v0.37" // "v2.2.0"
// defaultChainTag is the tag that will be used for the chains if none is specified.
defaultChainTag = "main"
// defaultRelayerType is the default relayer that will be used if none is specified.
Expand Down
197 changes: 197 additions & 0 deletions e2e/tests/interchain_accounts/localhost_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
package interchain_accounts

import (
"context"
"testing"
"time"

sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/gogoproto/proto"
controllertypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/controller/types"
icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types"
clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
connectiontypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types"
channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
ibctesting "github.com/cosmos/ibc-go/v7/testing"
"github.com/stretchr/testify/suite"

"github.com/cosmos/ibc-go/e2e/testsuite"
"github.com/cosmos/ibc-go/e2e/testvalues"
"github.com/strangelove-ventures/interchaintest/v7"
"github.com/strangelove-ventures/interchaintest/v7/ibc"
test "github.com/strangelove-ventures/interchaintest/v7/testutil"
)

func TestInterchainAccountsLocalhostTestSuite(t *testing.T) {
suite.Run(t, new(LocalhostInterchainAccountsTestSuite))
}

type LocalhostInterchainAccountsTestSuite struct {
testsuite.E2ETestSuite
}

func (s *LocalhostInterchainAccountsTestSuite) TestInterchainAccounts_Localhost() {
t := s.T()
ctx := context.TODO()

_, _ = s.SetupChainsRelayerAndChannel(ctx)
chainA, _ := s.GetChains()

chainADenom := chainA.Config().Denom

rlyWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount)
userAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount)
userBWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount)

var (
msgChanOpenInitRes channeltypes.MsgChannelOpenInitResponse
msgChanOpenTryRes channeltypes.MsgChannelOpenTryResponse
ack []byte
packet channeltypes.Packet
)

s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA), "failed to wait for blocks")

version := icatypes.NewDefaultMetadataString(connectiontypes.LocalhostID, connectiontypes.LocalhostID)
controllerPortID, err := icatypes.NewControllerPortID(userAWallet.FormattedAddress())
s.Require().NoError(err)

t.Run("channel open init localhost - broadcast MsgRegisterInterchainAccount", func(t *testing.T) {
msgRegisterAccount := controllertypes.NewMsgRegisterInterchainAccount(connectiontypes.LocalhostID, userAWallet.FormattedAddress(), version)

txResp, err := s.BroadcastMessages(ctx, chainA, userAWallet, msgRegisterAccount)
s.Require().NoError(err)
s.AssertValidTxResponse(txResp)

s.Require().NoError(testsuite.UnmarshalMsgResponses(txResp, &msgChanOpenInitRes))
})

t.Run("channel open try localhost", func(t *testing.T) {
msgChanOpenTry := channeltypes.NewMsgChannelOpenTry(
icatypes.HostPortID, icatypes.Version,
channeltypes.ORDERED, []string{connectiontypes.LocalhostID},
controllerPortID, msgChanOpenInitRes.GetChannelId(),
version, nil, clienttypes.ZeroHeight(), rlyWallet.FormattedAddress(),
)

txResp, err := s.BroadcastMessages(ctx, chainA, rlyWallet, msgChanOpenTry)
s.Require().NoError(err)
s.AssertValidTxResponse(txResp)

s.Require().NoError(testsuite.UnmarshalMsgResponses(txResp, &msgChanOpenTryRes))
})

t.Run("channel open ack localhost", func(t *testing.T) {
msgChanOpenAck := channeltypes.NewMsgChannelOpenAck(
controllerPortID, msgChanOpenInitRes.GetChannelId(),
msgChanOpenTryRes.GetChannelId(), msgChanOpenTryRes.GetVersion(),
nil, clienttypes.ZeroHeight(), rlyWallet.FormattedAddress(),
)

txResp, err := s.BroadcastMessages(ctx, chainA, rlyWallet, msgChanOpenAck)
s.Require().NoError(err)
s.AssertValidTxResponse(txResp)
})

t.Run("channel open confirm localhost", func(t *testing.T) {
msgChanOpenConfirm := channeltypes.NewMsgChannelOpenConfirm(
icatypes.HostPortID, msgChanOpenTryRes.GetChannelId(),
nil, clienttypes.ZeroHeight(), rlyWallet.FormattedAddress(),
)

txResp, err := s.BroadcastMessages(ctx, chainA, rlyWallet, msgChanOpenConfirm)
s.Require().NoError(err)
s.AssertValidTxResponse(txResp)
})

t.Run("query localhost interchain accounts channel ends", func(t *testing.T) {
channelEndA, err := s.QueryChannel(ctx, chainA, controllerPortID, msgChanOpenInitRes.GetChannelId())
s.Require().NoError(err)
s.Require().NotNil(channelEndA)

channelEndB, err := s.QueryChannel(ctx, chainA, icatypes.HostPortID, msgChanOpenTryRes.GetChannelId())
s.Require().NoError(err)
s.Require().NotNil(channelEndB)

s.Require().Equal(channelEndA.GetConnectionHops(), channelEndB.GetConnectionHops())
})

t.Run("verify interchain account registration and deposit funds", func(t *testing.T) {
interchainAccAddress, err := s.QueryInterchainAccount(ctx, chainA, userAWallet.FormattedAddress(), connectiontypes.LocalhostID)
s.Require().NoError(err)
s.Require().NotZero(len(interchainAccAddress))

walletAmount := ibc.WalletAmount{
Address: interchainAccAddress,
Amount: testvalues.StartingTokenAmount,
Denom: chainADenom,
}

s.Require().NoError(chainA.SendFunds(ctx, interchaintest.FaucetAccountKeyName, walletAmount))
})

t.Run("send packet localhost interchain accounts", func(t *testing.T) {
interchainAccAddress, err := s.QueryInterchainAccount(ctx, chainA, userAWallet.FormattedAddress(), connectiontypes.LocalhostID)
s.Require().NoError(err)
s.Require().NotZero(len(interchainAccAddress))

msgSend := &banktypes.MsgSend{
FromAddress: interchainAccAddress,
ToAddress: userBWallet.FormattedAddress(),
Amount: sdk.NewCoins(testvalues.DefaultTransferAmount(chainADenom)),
}

cdc := testsuite.Codec()
bz, err := icatypes.SerializeCosmosTx(cdc, []proto.Message{msgSend})
s.Require().NoError(err)

packetData := icatypes.InterchainAccountPacketData{
Type: icatypes.EXECUTE_TX,
Data: bz,
Memo: "e2e",
}

msgSendTx := controllertypes.NewMsgSendTx(userAWallet.FormattedAddress(), connectiontypes.LocalhostID, uint64(time.Hour.Nanoseconds()), packetData)

txResp, err := s.BroadcastMessages(ctx, chainA, userAWallet, msgSendTx)
s.AssertValidTxResponse(txResp)
s.Require().NoError(err)

events := testsuite.ABCIToSDKEvents(txResp.Events)
packet, err = ibctesting.ParsePacketFromEvents(events)
s.Require().NoError(err)
s.Require().NotNil(packet)
})

t.Run("recv packet localhost interchain accounts", func(t *testing.T) {
msgRecvPacket := channeltypes.NewMsgRecvPacket(packet, nil, clienttypes.ZeroHeight(), rlyWallet.FormattedAddress())

txResp, err := s.BroadcastMessages(ctx, chainA, rlyWallet, msgRecvPacket)
s.Require().NoError(err)
s.AssertValidTxResponse(txResp)

events := testsuite.ABCIToSDKEvents(txResp.Events)
ack, err = ibctesting.ParseAckFromEvents(events)
s.Require().NoError(err)
s.Require().NotNil(ack)
})

t.Run("acknowledge packet localhost interchain accounts", func(t *testing.T) {
msgAcknowledgement := channeltypes.NewMsgAcknowledgement(packet, ack, nil, clienttypes.ZeroHeight(), rlyWallet.FormattedAddress())

txResp, err := s.BroadcastMessages(ctx, chainA, rlyWallet, msgAcknowledgement)
s.Require().NoError(err)
s.AssertValidTxResponse(txResp)
})

t.Run("verify tokens transferred", func(t *testing.T) {
s.AssertPacketRelayed(ctx, chainA, controllerPortID, msgChanOpenInitRes.GetChannelId(), 1)

balance, err := chainA.GetBalance(ctx, userBWallet.FormattedAddress(), chainADenom)
s.Require().NoError(err)

expected := testvalues.IBCTransferAmount + testvalues.StartingTokenAmount
s.Require().Equal(expected, balance)
})
}
169 changes: 169 additions & 0 deletions e2e/tests/transfer/localhost_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
package transfer

import (
"context"
"testing"

"github.com/stretchr/testify/suite"

transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
connectiontypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types"
channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
ibctesting "github.com/cosmos/ibc-go/v7/testing"
test "github.com/strangelove-ventures/interchaintest/v7/testutil"

"github.com/cosmos/ibc-go/e2e/testsuite"
"github.com/cosmos/ibc-go/e2e/testvalues"
)

func TestTransferLocalhostTestSuite(t *testing.T) {
suite.Run(t, new(LocalhostTransferTestSuite))
}

type LocalhostTransferTestSuite struct {
testsuite.E2ETestSuite
}

// TestMsgTransfer_Localhost creates two wallets on a single chain and performs MsgTransfers back and forth
// to ensure ibc functions as expected on localhost. This test is largely the same as TestMsgTransfer_Succeeds_Nonincentivized
// except that chain B is replaced with an additional wallet on chainA.
func (s *LocalhostTransferTestSuite) TestMsgTransfer_Localhost() {
t := s.T()
ctx := context.TODO()

_, _ = s.SetupChainsRelayerAndChannel(ctx, transferChannelOptions())
chainA, _ := s.GetChains()

chainADenom := chainA.Config().Denom

rlyWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount)
userAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount)
userBWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount)

var (
msgChanOpenInitRes channeltypes.MsgChannelOpenInitResponse
msgChanOpenTryRes channeltypes.MsgChannelOpenTryResponse
ack []byte
packet channeltypes.Packet
)

s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA), "failed to wait for blocks")

t.Run("channel open init localhost", func(t *testing.T) {
msgChanOpenInit := channeltypes.NewMsgChannelOpenInit(
transfertypes.PortID, transfertypes.Version,
channeltypes.UNORDERED, []string{connectiontypes.LocalhostID},
transfertypes.PortID, rlyWallet.FormattedAddress(),
)

s.Require().NoError(msgChanOpenInit.ValidateBasic())

txResp, err := s.BroadcastMessages(ctx, chainA, rlyWallet, msgChanOpenInit)
s.Require().NoError(err)
s.AssertValidTxResponse(txResp)

s.Require().NoError(testsuite.UnmarshalMsgResponses(txResp, &msgChanOpenInitRes))
})

t.Run("channel open try localhost", func(t *testing.T) {
msgChanOpenTry := channeltypes.NewMsgChannelOpenTry(
transfertypes.PortID, transfertypes.Version,
channeltypes.UNORDERED, []string{connectiontypes.LocalhostID},
transfertypes.PortID, msgChanOpenInitRes.GetChannelId(),
transfertypes.Version, nil, clienttypes.ZeroHeight(), rlyWallet.FormattedAddress(),
)

txResp, err := s.BroadcastMessages(ctx, chainA, rlyWallet, msgChanOpenTry)
s.Require().NoError(err)
s.AssertValidTxResponse(txResp)

s.Require().NoError(testsuite.UnmarshalMsgResponses(txResp, &msgChanOpenTryRes))
})

t.Run("channel open ack localhost", func(t *testing.T) {
msgChanOpenAck := channeltypes.NewMsgChannelOpenAck(
transfertypes.PortID, msgChanOpenInitRes.GetChannelId(),
msgChanOpenTryRes.GetChannelId(), transfertypes.Version,
nil, clienttypes.ZeroHeight(), rlyWallet.FormattedAddress(),
)

txResp, err := s.BroadcastMessages(ctx, chainA, rlyWallet, msgChanOpenAck)
s.Require().NoError(err)
s.AssertValidTxResponse(txResp)
})

t.Run("channel open confirm localhost", func(t *testing.T) {
msgChanOpenConfirm := channeltypes.NewMsgChannelOpenConfirm(
transfertypes.PortID, msgChanOpenTryRes.GetChannelId(),
nil, clienttypes.ZeroHeight(), rlyWallet.FormattedAddress(),
)

txResp, err := s.BroadcastMessages(ctx, chainA, rlyWallet, msgChanOpenConfirm)
s.Require().NoError(err)
s.AssertValidTxResponse(txResp)
})

t.Run("query localhost transfer channel ends", func(t *testing.T) {
channelEndA, err := s.QueryChannel(ctx, chainA, transfertypes.PortID, msgChanOpenInitRes.GetChannelId())
s.Require().NoError(err)
s.Require().NotNil(channelEndA)

channelEndB, err := s.QueryChannel(ctx, chainA, transfertypes.PortID, msgChanOpenTryRes.GetChannelId())
s.Require().NoError(err)
s.Require().NotNil(channelEndB)

s.Require().Equal(channelEndA.GetConnectionHops(), channelEndB.GetConnectionHops())
})

t.Run("send packet localhost ibc transfer", func(t *testing.T) {
txResp, err := s.Transfer(ctx, chainA, userAWallet, transfertypes.PortID, msgChanOpenInitRes.GetChannelId(), testvalues.DefaultTransferAmount(chainADenom), userAWallet.FormattedAddress(), userBWallet.FormattedAddress(), clienttypes.NewHeight(1, 100), 0, "")
s.Require().NoError(err)
s.AssertValidTxResponse(txResp)

events := testsuite.ABCIToSDKEvents(txResp.Events)
packet, err = ibctesting.ParsePacketFromEvents(events)
s.Require().NoError(err)
s.Require().NotNil(packet)
})

t.Run("tokens are escrowed", func(t *testing.T) {
actualBalance, err := s.GetChainANativeBalance(ctx, userAWallet)
s.Require().NoError(err)

expected := testvalues.StartingTokenAmount - testvalues.IBCTransferAmount
s.Require().Equal(expected, actualBalance)
})

t.Run("recv packet localhost ibc transfer", func(t *testing.T) {
msgRecvPacket := channeltypes.NewMsgRecvPacket(packet, nil, clienttypes.ZeroHeight(), rlyWallet.FormattedAddress())

txResp, err := s.BroadcastMessages(ctx, chainA, rlyWallet, msgRecvPacket)
s.Require().NoError(err)
s.AssertValidTxResponse(txResp)

events := testsuite.ABCIToSDKEvents(txResp.Events)
ack, err = ibctesting.ParseAckFromEvents(events)
s.Require().NoError(err)
s.Require().NotNil(ack)
})

t.Run("acknowledge packet localhost ibc transfer", func(t *testing.T) {
msgAcknowledgement := channeltypes.NewMsgAcknowledgement(packet, ack, nil, clienttypes.ZeroHeight(), rlyWallet.FormattedAddress())

txResp, err := s.BroadcastMessages(ctx, chainA, rlyWallet, msgAcknowledgement)
s.Require().NoError(err)
s.AssertValidTxResponse(txResp)
})

t.Run("verify tokens transferred", func(t *testing.T) {
s.AssertPacketRelayed(ctx, chainA, transfertypes.PortID, msgChanOpenInitRes.GetChannelId(), 1)

ibcToken := testsuite.GetIBCToken(chainADenom, transfertypes.PortID, msgChanOpenTryRes.GetChannelId())
actualBalance, err := chainA.GetBalance(ctx, userBWallet.FormattedAddress(), ibcToken.IBCDenom())
s.Require().NoError(err)

expected := testvalues.IBCTransferAmount
s.Require().Equal(expected, actualBalance)
})
}
Loading

0 comments on commit 63111de

Please sign in to comment.