Skip to content

Commit 850af55

Browse files
colmaziaRogerKSI
andauthored
[Grogu] unit test (#189)
* add unit test for signaller * add test for querier, use remoteClient instead of http * Grogu unfinished test (#188) * mock test for submitter * finish submitter test setup * add test cases for submitter test * implement basic integration tests for signaller * change check submit price to include assigned time, fix test to use assigned time * change clientContext to clientCtx * remove dup func --------- Co-authored-by: Kitipong Sirirueangsakul <[email protected]>
1 parent 1410734 commit 850af55

File tree

18 files changed

+1929
-130
lines changed

18 files changed

+1929
-130
lines changed

cmd/grogu/cmd/utils.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ package cmd
33
import (
44
"fmt"
55

6+
rpcclient "github.com/cometbft/cometbft/rpc/client"
67
"github.com/cometbft/cometbft/rpc/client/http"
78
)
89

9-
func createClients(nodeURIs []string) ([]*http.HTTP, func(), error) {
10-
clients := make([]*http.HTTP, 0, len(nodeURIs))
10+
func createClients(nodeURIs []string) ([]rpcclient.RemoteClient, func(), error) {
11+
clients := make([]rpcclient.RemoteClient, 0, len(nodeURIs))
1112
for _, uri := range nodeURIs {
1213
httpClient, err := http.New(uri, "/websocket")
1314
if err != nil {

grogu/querier/auth.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package querier
33
import (
44
"sync/atomic"
55

6-
"github.com/cometbft/cometbft/rpc/client/http"
6+
rpcclient "github.com/cometbft/cometbft/rpc/client"
77
"github.com/cosmos/cosmos-sdk/client"
88
sdk "github.com/cosmos/cosmos-sdk/types"
99
auth "github.com/cosmos/cosmos-sdk/x/auth/types"
@@ -15,13 +15,13 @@ type AuthQuerier struct {
1515
}
1616

1717
func NewAuthQuerier(
18-
clientContext client.Context,
19-
clients []*http.HTTP,
18+
clientCtx client.Context,
19+
clients []rpcclient.RemoteClient,
2020
maxBlockHeight *atomic.Int64,
2121
) *AuthQuerier {
2222
queryClients := make([]auth.QueryClient, 0, len(clients))
2323
for _, cl := range clients {
24-
queryClients = append(queryClients, auth.NewQueryClient(clientContext.WithClient(cl)))
24+
queryClients = append(queryClients, auth.NewQueryClient(clientCtx.WithClient(cl)))
2525
}
2626

2727
return &AuthQuerier{

grogu/querier/feed.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package querier
33
import (
44
"sync/atomic"
55

6-
"github.com/cometbft/cometbft/rpc/client/http"
6+
rpcclient "github.com/cometbft/cometbft/rpc/client"
77
"github.com/cosmos/cosmos-sdk/client"
88
sdk "github.com/cosmos/cosmos-sdk/types"
99

@@ -15,10 +15,14 @@ type FeedQuerier struct {
1515
maxBlockHeight *atomic.Int64
1616
}
1717

18-
func NewFeedQuerier(clientContext client.Context, clients []*http.HTTP, maxBlockHeight *atomic.Int64) *FeedQuerier {
18+
func NewFeedQuerier(
19+
clientCtx client.Context,
20+
clients []rpcclient.RemoteClient,
21+
maxBlockHeight *atomic.Int64,
22+
) *FeedQuerier {
1923
queryClients := make([]feeds.QueryClient, 0, len(clients))
2024
for _, cl := range clients {
21-
queryClients = append(queryClients, feeds.NewQueryClient(clientContext.WithClient(cl)))
25+
queryClients = append(queryClients, feeds.NewQueryClient(clientCtx.WithClient(cl)))
2226
}
2327

2428
return &FeedQuerier{queryClients, maxBlockHeight}

grogu/querier/tx.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package querier
22

33
import (
4-
"github.com/cometbft/cometbft/rpc/client/http"
4+
rpcclient "github.com/cometbft/cometbft/rpc/client"
55
"github.com/cosmos/cosmos-sdk/client"
66
"github.com/cosmos/cosmos-sdk/types"
77
"github.com/cosmos/cosmos-sdk/x/auth/tx"
@@ -11,12 +11,12 @@ type TxQuerier struct {
1111
contexts []client.Context
1212
}
1313

14-
func NewTxQuerier(clientContext client.Context, clients []*http.HTTP) *TxQuerier {
15-
clientContexts := make([]client.Context, 0, len(clients))
14+
func NewTxQuerier(clientCtx client.Context, clients []rpcclient.RemoteClient) *TxQuerier {
15+
clientCtxs := make([]client.Context, 0, len(clients))
1616
for _, cl := range clients {
17-
clientContexts = append(clientContexts, clientContext.WithClient(cl))
17+
clientCtxs = append(clientCtxs, clientCtx.WithClient(cl))
1818
}
19-
return &TxQuerier{clientContexts}
19+
return &TxQuerier{clientCtxs}
2020
}
2121

2222
func (q *TxQuerier) QueryTx(hash string) (*types.TxResponse, error) {

grogu/querier/utils.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,11 @@ func getMaxBlockHeightResponse[I, O any](
9090
}
9191
}
9292

93-
if localMaxBlockHeight < maxBlockHeight.Load() {
94-
return nil, fmt.Errorf("block height is less than latest max block height")
95-
}
96-
9793
if resp != nil {
94+
if localMaxBlockHeight < maxBlockHeight.Load() {
95+
return nil, fmt.Errorf("block height is lower than latest max block height")
96+
}
97+
9898
maxBlockHeight.Store(localMaxBlockHeight)
9999
return resp, nil
100100
}

grogu/querier/utils_test.go

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package querier
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"sync/atomic"
7+
"testing"
8+
9+
sdk "github.com/cosmos/cosmos-sdk/types/grpc"
10+
"github.com/stretchr/testify/require"
11+
"google.golang.org/grpc"
12+
"google.golang.org/grpc/metadata"
13+
)
14+
15+
// Mock Request and Response types
16+
type MockRequest struct{}
17+
18+
type MockResponse struct {
19+
Value string
20+
}
21+
22+
// Mock gRPC function generator
23+
func generateMockFuncWithBlockHeight(blockHeight string) QueryFunction[MockRequest, MockResponse] {
24+
return func(ctx context.Context, in *MockRequest, opts ...grpc.CallOption) (*MockResponse, error) {
25+
var header *metadata.MD
26+
for _, opt := range opts {
27+
if hOpt, ok := opt.(grpc.HeaderCallOption); ok {
28+
header = hOpt.HeaderAddr
29+
*header = metadata.Pairs(sdk.GRPCBlockHeightHeader, blockHeight)
30+
}
31+
}
32+
return &MockResponse{Value: "mock response"}, nil
33+
}
34+
}
35+
36+
func mockFuncMissingHeader(ctx context.Context, in *MockRequest, opts ...grpc.CallOption) (*MockResponse, error) {
37+
return &MockResponse{Value: "mock response"}, nil
38+
}
39+
40+
func TestGetResponseWithBlockHeight(t *testing.T) {
41+
in := &MockRequest{}
42+
opts := []grpc.CallOption{}
43+
44+
resp, err := getResponseWithBlockHeight(generateMockFuncWithBlockHeight("15"), in, opts...)
45+
require.NoError(t, err)
46+
require.NotNil(t, resp)
47+
require.Equal(t, int64(15), resp.blockHeight)
48+
require.Equal(t, "mock response", resp.response.Value)
49+
}
50+
51+
func TestGetResponseWithBlockHeight_MissingHeader(t *testing.T) {
52+
in := &MockRequest{}
53+
opts := []grpc.CallOption{}
54+
55+
resp, err := getResponseWithBlockHeight(mockFuncMissingHeader, in, opts...)
56+
require.Error(t, err)
57+
require.Contains(t, err.Error(), "block height not found in header")
58+
require.Nil(t, resp)
59+
}
60+
61+
func TestGetResponseWithBlockHeight_InvalidHeader(t *testing.T) {
62+
in := &MockRequest{}
63+
opts := []grpc.CallOption{}
64+
65+
resp, err := getResponseWithBlockHeight(generateMockFuncWithBlockHeight("invalid"), in, opts...)
66+
require.Error(t, err)
67+
require.Contains(t, err.Error(), "failed to parse block height")
68+
require.Nil(t, resp)
69+
}
70+
71+
func TestGetMaxBlockHeightResponse(t *testing.T) {
72+
fs := []QueryFunction[MockRequest, MockResponse]{
73+
generateMockFuncWithBlockHeight("1"),
74+
generateMockFuncWithBlockHeight("12"),
75+
generateMockFuncWithBlockHeight("15"),
76+
}
77+
78+
in := &MockRequest{}
79+
maxBlockHeight := new(atomic.Int64)
80+
maxBlockHeight.Store(10)
81+
opts := []grpc.CallOption{}
82+
83+
resp, err := getMaxBlockHeightResponse(fs, in, maxBlockHeight, opts...)
84+
require.NoError(t, err)
85+
require.NotNil(t, resp)
86+
require.Equal(t, int64(15), maxBlockHeight.Load())
87+
require.Equal(t, "mock response", resp.Value)
88+
}
89+
90+
func TestGetMaxBlockHeightResponse_LowerThanCurrentMax(t *testing.T) {
91+
fs := []QueryFunction[MockRequest, MockResponse]{
92+
generateMockFuncWithBlockHeight("19"),
93+
}
94+
95+
in := &MockRequest{}
96+
maxBlockHeight := new(atomic.Int64)
97+
maxBlockHeight.Store(20)
98+
opts := []grpc.CallOption{}
99+
100+
resp, err := getMaxBlockHeightResponse(fs, in, maxBlockHeight, opts...)
101+
require.Error(t, err)
102+
require.Contains(t, err.Error(), "block height is lower than latest max block height")
103+
require.Nil(t, resp)
104+
}
105+
106+
func TestGetMaxBlockHeightResponse_AllFail(t *testing.T) {
107+
fs := []QueryFunction[MockRequest, MockResponse]{
108+
func(ctx context.Context, in *MockRequest, opts ...grpc.CallOption) (*MockResponse, error) {
109+
return nil, fmt.Errorf("failed")
110+
},
111+
func(ctx context.Context, in *MockRequest, opts ...grpc.CallOption) (*MockResponse, error) {
112+
return nil, fmt.Errorf("failed")
113+
},
114+
}
115+
116+
in := &MockRequest{}
117+
maxBlockHeight := new(atomic.Int64)
118+
maxBlockHeight.Store(10)
119+
opts := []grpc.CallOption{}
120+
121+
_, err := getMaxBlockHeightResponse(fs, in, maxBlockHeight, opts...)
122+
require.Error(t, err)
123+
}

grogu/signaller/expected_types.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package signaller
2+
3+
import (
4+
bothan "github.com/bandprotocol/bothan/bothan-api/client/go-client"
5+
sdk "github.com/cosmos/cosmos-sdk/types"
6+
7+
feeds "github.com/bandprotocol/chain/v2/x/feeds/types"
8+
)
9+
10+
type BothanClient interface {
11+
bothan.Client
12+
}
13+
14+
type FeedQuerier interface {
15+
QueryValidValidator(valAddress sdk.ValAddress) (*feeds.QueryValidValidatorResponse, error)
16+
QueryValidatorPrices(valAddress sdk.ValAddress) (*feeds.QueryValidatorPricesResponse, error)
17+
QueryParams() (*feeds.QueryParamsResponse, error)
18+
QueryCurrentFeeds() (*feeds.QueryCurrentFeedsResponse, error)
19+
}

0 commit comments

Comments
 (0)