From 50afbc30aea2cd8e6a4d790819f4420e72aa54e7 Mon Sep 17 00:00:00 2001 From: Gjermund Garaba Date: Mon, 23 Sep 2024 20:37:23 +0200 Subject: [PATCH] setup unit test for vote extension testing --- core/Makefile | 5 +- core/go.mod | 6 +- core/go.sum | 4 + core/scripts/mockgen.sh | 4 + core/voteextension/expected_keepers.go | 11 +++ core/voteextension/module.go | 6 +- .../testutil/expected_keepers_mocks.go | 50 +++++++++++ core/voteextension/testutil/mock_server.go | 47 ++++++++++ core/voteextension/voteextension_test.go | 85 +++++++++++++++++-- justfile | 11 +++ 10 files changed, 216 insertions(+), 13 deletions(-) create mode 100755 core/scripts/mockgen.sh create mode 100644 core/voteextension/expected_keepers.go create mode 100644 core/voteextension/testutil/expected_keepers_mocks.go create mode 100644 core/voteextension/testutil/mock_server.go diff --git a/core/Makefile b/core/Makefile index e3aec1a..f773acb 100644 --- a/core/Makefile +++ b/core/Makefile @@ -40,7 +40,8 @@ proto-all: proto-format proto-lint proto-gen proto-gen: @echo "Generating Protobuf files" - $(protoImage) ls -la#@go mod tidy + @$(protoImage) sh ./scripts/protocgen.sh + @go mod tidy proto-format: @$(protoImage) find ./ -name "*.proto" -exec clang-format -i {} \; @@ -48,4 +49,4 @@ proto-format: proto-lint: @$(protoImage) buf lint --error-format=json -.PHONY: * \ No newline at end of file +.PHONY: * diff --git a/core/go.mod b/core/go.mod index afd2ce0..c516a29 100644 --- a/core/go.mod +++ b/core/go.mod @@ -143,7 +143,6 @@ require ( go.opencensus.io v0.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.25.0 // indirect - golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect golang.org/x/net v0.27.0 // indirect golang.org/x/sys v0.22.0 // indirect golang.org/x/term v0.22.0 // indirect @@ -158,3 +157,8 @@ require ( pgregory.net/rapid v1.1.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) + +require ( + github.com/golang/mock v1.6.0 + golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 +) diff --git a/core/go.sum b/core/go.sum index a21eddd..7ec4f8e 100644 --- a/core/go.sum +++ b/core/go.sum @@ -744,6 +744,7 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= @@ -811,6 +812,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -855,6 +857,7 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -948,6 +951,7 @@ golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/core/scripts/mockgen.sh b/core/scripts/mockgen.sh new file mode 100755 index 0000000..a63dfc4 --- /dev/null +++ b/core/scripts/mockgen.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +mockgen_cmd="mockgen" +$mockgen_cmd -source=voteextension/expected_keepers.go -package testutil -destination voteextension/testutil/expected_keepers_mocks.go diff --git a/core/voteextension/expected_keepers.go b/core/voteextension/expected_keepers.go new file mode 100644 index 0000000..d6e2dd2 --- /dev/null +++ b/core/voteextension/expected_keepers.go @@ -0,0 +1,11 @@ +package voteextension + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/ibc-go/v9/modules/core/exported" +) + +type ClientKeeper interface { + UpdateClient(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) error +} diff --git a/core/voteextension/module.go b/core/voteextension/module.go index c1e3550..78acdcb 100644 --- a/core/voteextension/module.go +++ b/core/voteextension/module.go @@ -15,8 +15,6 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" "github.com/cometbft/cometbft/libs/json" - - clientkeeper "github.com/cosmos/ibc-go/v9/modules/core/02-client/keeper" ) const ModuleName = "attestationvoteextension" @@ -52,7 +50,7 @@ type AppModule struct { // TODO: Should we just move this stuff into a keeper, or is it fine here? sidecarAddress string - clientKeeper *clientkeeper.Keeper + clientKeeper ClientKeeper cdc codec.Codec // Create lazily @@ -60,7 +58,7 @@ type AppModule struct { } // NewAppModule creates a new attestation vote extension AppModule -func NewAppModule(clientKeeper *clientkeeper.Keeper, cdc codec.Codec) AppModule { +func NewAppModule(clientKeeper ClientKeeper, cdc codec.Codec) AppModule { sidecarAddress := os.Getenv(SidecarAddressEnv) return AppModule{ diff --git a/core/voteextension/testutil/expected_keepers_mocks.go b/core/voteextension/testutil/expected_keepers_mocks.go new file mode 100644 index 0000000..e01e3a8 --- /dev/null +++ b/core/voteextension/testutil/expected_keepers_mocks.go @@ -0,0 +1,50 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: voteextension/expected_keepers.go + +// Package testutil is a generated GoMock package. +package testutil + +import ( + reflect "reflect" + + types "github.com/cosmos/cosmos-sdk/types" + exported "github.com/cosmos/ibc-go/v9/modules/core/exported" + gomock "github.com/golang/mock/gomock" +) + +// MockClientKeeper is a mock of ClientKeeper interface. +type MockClientKeeper struct { + ctrl *gomock.Controller + recorder *MockClientKeeperMockRecorder +} + +// MockClientKeeperMockRecorder is the mock recorder for MockClientKeeper. +type MockClientKeeperMockRecorder struct { + mock *MockClientKeeper +} + +// NewMockClientKeeper creates a new mock instance. +func NewMockClientKeeper(ctrl *gomock.Controller) *MockClientKeeper { + mock := &MockClientKeeper{ctrl: ctrl} + mock.recorder = &MockClientKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockClientKeeper) EXPECT() *MockClientKeeperMockRecorder { + return m.recorder +} + +// UpdateClient mocks base method. +func (m *MockClientKeeper) UpdateClient(ctx types.Context, clientID string, clientMsg exported.ClientMessage) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateClient", ctx, clientID, clientMsg) + ret0, _ := ret[0].(error) + return ret0 +} + +// UpdateClient indicates an expected call of UpdateClient. +func (mr *MockClientKeeperMockRecorder) UpdateClient(ctx, clientID, clientMsg interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateClient", reflect.TypeOf((*MockClientKeeper)(nil).UpdateClient), ctx, clientID, clientMsg) +} diff --git a/core/voteextension/testutil/mock_server.go b/core/voteextension/testutil/mock_server.go new file mode 100644 index 0000000..773dae7 --- /dev/null +++ b/core/voteextension/testutil/mock_server.go @@ -0,0 +1,47 @@ +package testutil + +import ( + "context" + "fmt" + "net" + + "google.golang.org/grpc" + + "github.com/cosmos/interchain-attestation/core/types" +) + +type Server struct { + types.UnimplementedSidecarServer + grpcServer *grpc.Server + + Response *types.GetAttestationsResponse +} + +var _ types.SidecarServer = &Server{} + +func NewServer() *Server { + return &Server{} +} + +func (s *Server) Serve(listenAddr string) error { + lis, err := net.Listen("tcp", listenAddr) + if err != nil { + return fmt.Errorf("failed to start server: %w", err) + } + + s.grpcServer = grpc.NewServer() + types.RegisterSidecarServer(s.grpcServer, s) + if err := s.grpcServer.Serve(lis); err != nil { + return err + } + + return nil +} + +func (s *Server) Stop() { + s.grpcServer.GracefulStop() +} + +func (s *Server) GetAttestations(_ context.Context, _ *types.GetAttestationsRequest) (*types.GetAttestationsResponse, error) { + return s.Response, nil +} diff --git a/core/voteextension/voteextension_test.go b/core/voteextension/voteextension_test.go index b756a57..65d3f63 100644 --- a/core/voteextension/voteextension_test.go +++ b/core/voteextension/voteextension_test.go @@ -1,19 +1,92 @@ package voteextension_test import ( + fmt "fmt" + "os" + "sync" "testing" + "time" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + "golang.org/x/exp/rand" + + storetypes "cosmossdk.io/store/types" + + sdktestutil "github.com/cosmos/cosmos-sdk/testutil" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + + abci "github.com/cometbft/cometbft/abci/types" + + clienttypes "github.com/cosmos/ibc-go/v9/modules/core/02-client/types" + + "github.com/cosmos/interchain-attestation/core/types" + "github.com/cosmos/interchain-attestation/core/voteextension" + "github.com/cosmos/interchain-attestation/core/voteextension/testutil" ) func TestExtendVote(t *testing.T) { - /*testKey := storetypes.NewKVStoreKey("upgrade") - ctx := testutil.DefaultContext(testKey, storetypes.NewTransientStoreKey("transient_test")) + testKey := storetypes.NewKVStoreKey("upgrade") + ctx := sdktestutil.DefaultContext(testKey, storetypes.NewTransientStoreKey("transient_test")) + + randomPort := rand.Intn(65535-49152) + 49152 + addr := fmt.Sprintf("localhost:%d", randomPort) - err := os.Setenv(attestationabci.SidecarAddressEnv, "") + mockServer := testutil.NewServer() + wg := sync.WaitGroup{} + wg.Add(1) + go func() { + err := mockServer.Serve(addr) + require.NoError(t, err) + wg.Done() + }() + time.Sleep(1 * time.Second) + + err := os.Setenv(voteextension.SidecarAddressEnv, addr) require.NoError(t, err) - appModule := attestationabci.NewAppModule() + ctrl := gomock.NewController(t) + clientKeeper := testutil.NewMockClientKeeper(ctrl) + + encodingCfg := moduletestutil.MakeTestEncodingConfig() + appModule := voteextension.NewAppModule(clientKeeper, encodingCfg.Codec) + + mockServer.Response = &types.GetAttestationsResponse{ + Attestations: []types.Attestation{ + { + AttestatorId: []byte("mock-attestor-id"), + AttestedData: types.IBCData{ + ChainId: "mock-chain-id", + ClientId: "mock-client-id", + ClientToUpdate: "mock-client-to-update", + Height: clienttypes.NewHeight(1, 1), + Timestamp: time.Now(), + PacketCommitments: [][]byte{ + []byte("pckt1"), + []byte("pckt2"), + }, + }, + Signature: []byte("sig"), + }, + }, + } responseExtendVote, err := appModule.ExtendVote(ctx, &abci.RequestExtendVote{}) require.NoError(t, err) - _ = responseExtendVote*/ - // TODO: Create a mock sidecar server and set the address to the environment variable and test with that + require.NotEmpty(t, responseExtendVote.VoteExtension) + + var voteExt voteextension.VoteExtension + err = encodingCfg.Codec.Unmarshal(responseExtendVote.VoteExtension, &voteExt) + require.NoError(t, err) + require.Len(t, voteExt.Attestations, 1) + require.Equal(t, mockServer.Response.Attestations[0].AttestatorId, voteExt.Attestations[0].AttestatorId) + require.Equal(t, mockServer.Response.Attestations[0].Signature, voteExt.Attestations[0].Signature) + require.Equal(t, mockServer.Response.Attestations[0].AttestedData.ChainId, voteExt.Attestations[0].AttestedData.ChainId) + require.Equal(t, mockServer.Response.Attestations[0].AttestedData.ClientId, voteExt.Attestations[0].AttestedData.ClientId) + require.Equal(t, mockServer.Response.Attestations[0].AttestedData.ClientToUpdate, voteExt.Attestations[0].AttestedData.ClientToUpdate) + require.Equal(t, mockServer.Response.Attestations[0].AttestedData.Height, voteExt.Attestations[0].AttestedData.Height) + require.Equal(t, mockServer.Response.Attestations[0].AttestedData.Timestamp.UnixNano(), voteExt.Attestations[0].AttestedData.Timestamp.UnixNano()) + + require.Len(t, voteExt.Attestations[0].AttestedData.PacketCommitments, 2) + require.Equal(t, mockServer.Response.Attestations[0].AttestedData.PacketCommitments[0], voteExt.Attestations[0].AttestedData.PacketCommitments[0]) + require.Equal(t, mockServer.Response.Attestations[0].AttestedData.PacketCommitments[1], voteExt.Attestations[0].AttestedData.PacketCommitments[1]) } diff --git a/justfile b/justfile index 6846b26..352589f 100644 --- a/justfile +++ b/justfile @@ -1,3 +1,5 @@ +full-check: proto-gen tidy lint build test-unit build-docker-images test-e2e + build: @echo "Building all the components" cd core && make build @@ -16,6 +18,15 @@ lint: cd testing/rollupsimapp && golangci-lint run cd testing/interchaintest && golangci-lint run +lint-fix: + @echo "Running golangci-lint in all packages" + cd core && golangci-lint run --fix + cd configmodule && golangci-lint run --fix + cd sidecar && golangci-lint run --fix + cd testing/simapp && golangci-lint run --fix + cd testing/rollupsimapp && golangci-lint run --fix + cd testing/interchaintest && golangci-lint run --fix + tidy: @echo "Running go mod tidy in all packages" cd core && go mod tidy