Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

e2e: add client recovery proposal test #2130

Merged
merged 13 commits into from
Aug 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/e2e-fork.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
- name: Run e2e Test
env:
# see images here https://github.com/cosmos/relayer/pkgs/container/relayer/versions
RLY_TAG: "v2.0.0-rc2"
RLY_TAG: "v2.0.0"
colin-axner marked this conversation as resolved.
Show resolved Hide resolved
run: |
cd e2e
make e2e-test entrypoint=${{ matrix.entrypoint }} test=${{ matrix.test }}
2 changes: 1 addition & 1 deletion .github/workflows/e2e-manual-icad.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ on:
relayer-tag:
description: 'The tag to use for the relayer'
required: true
default: "v2.0.0-rc2"
default: "v2.0.0"
type: string


Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/e2e-manual-simd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ on:
relayer-tag:
description: 'The tag to use for the relayer'
required: true
default: "v2.0.0-rc2"
default: "v2.0.0"
type: string


Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/e2e-test-workflow-call.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ on:
relayer-tag:
description: 'The tag to use for the relayer'
required: true
default: "v2.0.0-rc2"
default: "v2.0.0"
type: string
build-and-push-docker-image:
description: "Flag to specify if the docker image should be built and pushed beforehand"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
chain-image: ghcr.io/cosmos/ibc-go-simd
chain-a-tag: "${{ needs.determine-image-tag.outputs.simd-tag }}"
chain-b-tag: "${{ needs.determine-image-tag.outputs.simd-tag }}"
relayer-tag: "v2.0.0-rc2"
relayer-tag: "v2.0.0"
chain-binary: "simd"
# on regular PRs we won't run interchain account tests.
test-exclusions: "TestInterchainAccountsTestSuite,TestIncentivizedInterchainAccountsTestSuite"
2 changes: 1 addition & 1 deletion e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export CHAIN_BINARY="simd"
# export CHAIN_B_TAG="main"
# export CHAIN_BINARY="icad"

export RLY_TAG="v2.0.0-rc2"
export RLY_TAG="v2.0.0"
make e2e-test entrypoint=TestInterchainAccountsTestSuite test=TestMsgSubmitTx_SuccessfulTransfer
```

Expand Down
2 changes: 1 addition & 1 deletion e2e/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/cosmos/ibc-go/v5 v5.0.0-beta1
github.com/cosmos/interchain-accounts v0.3.1-0.20220816085955-393d8444c111
github.com/docker/docker v20.10.17+incompatible
github.com/strangelove-ventures/ibctest v0.0.0-20220824150312-9d02bdb119b0
github.com/strangelove-ventures/ibctest v0.0.0-20220824180329-f73a9f936fce
github.com/stretchr/testify v1.8.0
github.com/tendermint/tendermint v0.34.20
go.uber.org/zap v1.21.0
Expand Down
4 changes: 2 additions & 2 deletions e2e/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1255,8 +1255,8 @@ github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZL
github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I=
github.com/strangelove-ventures/go-subkey v1.0.7 h1:cOP/Lajg3uxV/tvspu0m6+0Cu+DJgygkEAbx/s+f35I=
github.com/strangelove-ventures/go-subkey v1.0.7/go.mod h1:E34izOIEm+sZ1YmYawYRquqBQWeZBjVB4pF7bMuhc1c=
github.com/strangelove-ventures/ibctest v0.0.0-20220824150312-9d02bdb119b0 h1:IBb9ktwUfrLcBLCAZz2Yf9qMz98U/1Nc1HpQFhA92qQ=
github.com/strangelove-ventures/ibctest v0.0.0-20220824150312-9d02bdb119b0/go.mod h1:fwqMUdv+pE55HipI/b+7+8xbjrqePGYTEHoZOtWvTqQ=
github.com/strangelove-ventures/ibctest v0.0.0-20220824180329-f73a9f936fce h1:CwbsETcaS9sRbcRdiwfxlZTn3hrpEYW2vAvMTPJDa4M=
github.com/strangelove-ventures/ibctest v0.0.0-20220824180329-f73a9f936fce/go.mod h1:fwqMUdv+pE55HipI/b+7+8xbjrqePGYTEHoZOtWvTqQ=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
Expand Down
121 changes: 121 additions & 0 deletions e2e/tests/core/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package e2e

import (
"context"
"fmt"
"strings"
"testing"
"time"

"github.com/strangelove-ventures/ibctest/ibc"
"github.com/strangelove-ventures/ibctest/test"
"github.com/stretchr/testify/suite"

"github.com/cosmos/ibc-go/e2e/testsuite"
"github.com/cosmos/ibc-go/e2e/testvalues"
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
ibcexported "github.com/cosmos/ibc-go/v5/modules/core/exported"
ibctesting "github.com/cosmos/ibc-go/v5/testing"
)

func TestClientTestSuite(t *testing.T) {
suite.Run(t, new(ClientTestSuite))
}

type ClientTestSuite struct {
testsuite.E2ETestSuite
}

// Status queries the current status of the client
func (s *ClientTestSuite) Status(ctx context.Context, chain ibc.Chain, clientID string) (string, error) {
queryClient := s.GetChainGRCPClients(chain).ClientQueryClient
res, err := queryClient.ClientStatus(ctx, &clienttypes.QueryClientStatusRequest{
ClientId: clientID,
})
if err != nil {
return "", err
}

return res.Status, nil
}

func (s *ClientTestSuite) TestClientUpdateProposal_Succeeds() {
t := s.T()
ctx := context.TODO()

var (
pathName string
relayer ibc.Relayer
subjectClientID string
substituteClientID string
badTrustingPeriod = time.Duration(time.Second)
)

t.Run("create substitute client with correct trusting period", func(t *testing.T) {
relayer, _ = s.SetupChainsRelayerAndChannel(ctx)

// TODO: update when client identifier created is accessible
// currently assumes first client is 07-tendermint-0
substituteClientID = clienttypes.FormatClientIdentifier(ibcexported.Tendermint, 0)

// TODO: replace with better handling of path names
pathName = fmt.Sprintf("%s-path-%d", s.T().Name(), 0)
pathName = strings.ReplaceAll(pathName, "/", "-")
Comment on lines +57 to +63
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are a bit hacky, but I think it is better to just do this for now and figure out a better solution later. I think adding the endpoint type should solve the issue in both cases

})

chainA, chainB := s.GetChains()
chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount)

t.Run("create subject client with bad trusting period", func(t *testing.T) {
createClientOptions := ibc.CreateClientOptions{
TrustingPeriod: badTrustingPeriod.String(),
}

s.SetupClients(ctx, relayer, createClientOptions)

// TODO: update when client identifier created is accessible
// currently assumes second client is 07-tendermint-1
subjectClientID = clienttypes.FormatClientIdentifier(ibcexported.Tendermint, 1)
})

time.Sleep(badTrustingPeriod)

t.Run("update substitute client", func(t *testing.T) {
s.UpdateClients(ctx, relayer, pathName)
})

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

t.Run("check status of each client", func(t *testing.T) {
t.Run("substitute should be active", func(t *testing.T) {
status, err := s.Status(ctx, chainA, substituteClientID)
s.Require().NoError(err)
s.Require().Equal(ibcexported.Active.String(), status)
})

t.Run("subject should be expired", func(t *testing.T) {
status, err := s.Status(ctx, chainA, subjectClientID)
s.Require().NoError(err)
s.Require().Equal(ibcexported.Expired.String(), status)
})
})

t.Run("pass client update proposal", func(t *testing.T) {
proposal := clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subjectClientID, substituteClientID)
s.ExecuteGovProposal(ctx, chainA, chainAWallet, proposal)
})

t.Run("check status of each client", func(t *testing.T) {
t.Run("substitute should be active", func(t *testing.T) {
status, err := s.Status(ctx, chainA, substituteClientID)
s.Require().NoError(err)
s.Require().Equal(ibcexported.Active.String(), status)
})

t.Run("subject should be active", func(t *testing.T) {
status, err := s.Status(ctx, chainA, subjectClientID)
s.Require().NoError(err)
s.Require().Equal(ibcexported.Active.String(), status)
})
})
}
39 changes: 37 additions & 2 deletions e2e/testsuite/testsuite.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ type E2ETestSuite struct {
DockerClient *dockerclient.Client
network string
startRelayerFn func(relayer ibc.Relayer)

// pathNameIndex is the latest index to be used for generating paths
pathNameIndex uint64
}

// GRPCClients holds a reference to any GRPC clients that are needed by the tests.
Expand Down Expand Up @@ -111,8 +114,7 @@ func (s *E2ETestSuite) SetupChainsRelayerAndChannel(ctx context.Context, channel

r := newCosmosRelayer(s.T(), testconfig.FromEnv(), s.logger, s.DockerClient, s.network)

pathName := fmt.Sprintf("%s-path", s.T().Name())
pathName = strings.ReplaceAll(pathName, "/", "-")
pathName := s.generatePathName()

ic := ibctest.NewInterchain().
AddChain(chainA).
Expand Down Expand Up @@ -160,6 +162,39 @@ func (s *E2ETestSuite) SetupChainsRelayerAndChannel(ctx context.Context, channel
return r, chainAChannels[len(chainAChannels)-1]
}

// generatePathName generates the path name using the test suites name
func (s *E2ETestSuite) generatePathName() string {
pathName := fmt.Sprintf("%s-path-%d", s.T().Name(), s.pathNameIndex)
s.pathNameIndex++
return strings.ReplaceAll(pathName, "/", "-")
Comment on lines +166 to +169
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for every endpoint (client/connection/channel) stack we need a new path name, so I added an index kept by the E2ETestSuite

}

// generatePath generates the path name using the test suites name
func (s *E2ETestSuite) generatePath(ctx context.Context, relayer ibc.Relayer) string {
chainA, chainB := s.GetChains()
chainAID := chainA.Config().ChainID
chainBID := chainB.Config().ChainID

pathName := s.generatePathName()
err := relayer.GeneratePath(ctx, s.GetRelayerExecReporter(), chainAID, chainBID, pathName)
s.Require().NoError(err)

return pathName
}

// SetupClients creates clients on chainA and chainB using the provided create client options
func (s *E2ETestSuite) SetupClients(ctx context.Context, relayer ibc.Relayer, opts ibc.CreateClientOptions) {
pathName := s.generatePath(ctx, relayer)
err := relayer.CreateClients(ctx, s.GetRelayerExecReporter(), pathName, opts)
s.Require().NoError(err)
}

// UpdateClients updates clients on chainA and chainB
func (s *E2ETestSuite) UpdateClients(ctx context.Context, relayer ibc.Relayer, pathName string) {
err := relayer.UpdateClients(ctx, s.GetRelayerExecReporter(), pathName)
s.Require().NoError(err)
}

// GetChains returns two chains that can be used in a test. The pair returned
// is unique to the current test being run. Note: this function does not create containers.
func (s *E2ETestSuite) GetChains(chainOpts ...testconfig.ChainOptionConfiguration) (*cosmos.CosmosChain, *cosmos.CosmosChain) {
Expand Down