diff --git a/x/lightclient/keeper/grpc_query_block_header_test.go b/x/lightclient/keeper/grpc_query_block_header_test.go index e71da3a20f..8be62d2d75 100644 --- a/x/lightclient/keeper/grpc_query_block_header_test.go +++ b/x/lightclient/keeper/grpc_query_block_header_test.go @@ -4,8 +4,11 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/pkg/proofs" keepertest "github.com/zeta-chain/zetacore/testutil/keeper" + "github.com/zeta-chain/zetacore/testutil/nullify" "github.com/zeta-chain/zetacore/testutil/sample" "github.com/zeta-chain/zetacore/x/lightclient/types" ) @@ -30,6 +33,64 @@ func TestKeeper_BlockHeaderAll(t *testing.T) { require.NoError(t, err) require.Equal(t, bh, res.BlockHeaders[0]) }) + + t.Run("can run paginated queries", func(t *testing.T) { + k, ctx, _, _ := keepertest.LightclientKeeper(t) + wctx := sdk.WrapSDKContext(ctx) + nbItems := 5 + + items := make([]proofs.BlockHeader, nbItems) + for i := range items { + items[i] = sample.BlockHeader(sample.Hash().Bytes()) + k.SetBlockHeader(ctx, items[i]) + } + + request := func(next []byte, offset, limit uint64, total bool) *types.QueryAllBlockHeaderRequest { + return &types.QueryAllBlockHeaderRequest{ + Pagination: &query.PageRequest{ + Key: next, + Offset: offset, + Limit: limit, + CountTotal: total, + }, + } + } + t.Run("ByOffset", func(t *testing.T) { + step := 2 + for i := 0; i < nbItems; i += step { + resp, err := k.BlockHeaderAll(wctx, request(nil, uint64(i), uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.BlockHeaders), step) + require.Subset(t, + nullify.Fill(items), + nullify.Fill(resp.BlockHeaders), + ) + } + }) + t.Run("ByKey", func(t *testing.T) { + step := 2 + var next []byte + for i := 0; i < nbItems; i += step { + resp, err := k.BlockHeaderAll(wctx, request(next, 0, uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.BlockHeaders), step) + require.Subset(t, + nullify.Fill(items), + nullify.Fill(resp.BlockHeaders), + ) + next = resp.Pagination.NextKey + } + }) + t.Run("Total", func(t *testing.T) { + resp, err := k.BlockHeaderAll(wctx, request(nil, 0, 0, true)) + require.NoError(t, err) + require.Equal(t, nbItems, int(resp.Pagination.Total)) + require.ElementsMatch(t, + nullify.Fill(items), + nullify.Fill(resp.BlockHeaders), + ) + }) + }) } func TestKeeper_BlockHeader(t *testing.T) { diff --git a/x/lightclient/keeper/grpc_query_chain_state_test.go b/x/lightclient/keeper/grpc_query_chain_state_test.go index e44eba4e16..e8e9fe175e 100644 --- a/x/lightclient/keeper/grpc_query_chain_state_test.go +++ b/x/lightclient/keeper/grpc_query_chain_state_test.go @@ -4,8 +4,10 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" "github.com/stretchr/testify/require" keepertest "github.com/zeta-chain/zetacore/testutil/keeper" + "github.com/zeta-chain/zetacore/testutil/nullify" "github.com/zeta-chain/zetacore/testutil/sample" "github.com/zeta-chain/zetacore/x/lightclient/types" ) @@ -30,6 +32,64 @@ func TestKeeper_ChainStateAll(t *testing.T) { require.NoError(t, err) require.Equal(t, chainState, res.ChainState[0]) }) + + t.Run("can run paginated queries", func(t *testing.T) { + k, ctx, _, _ := keepertest.LightclientKeeper(t) + wctx := sdk.WrapSDKContext(ctx) + nbItems := 5 + + items := make([]types.ChainState, nbItems) + for i := range items { + items[i] = sample.ChainState(int64(i)) + k.SetChainState(ctx, items[i]) + } + + request := func(next []byte, offset, limit uint64, total bool) *types.QueryAllChainStateRequest { + return &types.QueryAllChainStateRequest{ + Pagination: &query.PageRequest{ + Key: next, + Offset: offset, + Limit: limit, + CountTotal: total, + }, + } + } + t.Run("ByOffset", func(t *testing.T) { + step := 2 + for i := 0; i < nbItems; i += step { + resp, err := k.ChainStateAll(wctx, request(nil, uint64(i), uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.ChainState), step) + require.Subset(t, + nullify.Fill(items), + nullify.Fill(resp.ChainState), + ) + } + }) + t.Run("ByKey", func(t *testing.T) { + step := 2 + var next []byte + for i := 0; i < nbItems; i += step { + resp, err := k.ChainStateAll(wctx, request(next, 0, uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.ChainState), step) + require.Subset(t, + nullify.Fill(items), + nullify.Fill(resp.ChainState), + ) + next = resp.Pagination.NextKey + } + }) + t.Run("Total", func(t *testing.T) { + resp, err := k.ChainStateAll(wctx, request(nil, 0, 0, true)) + require.NoError(t, err) + require.Equal(t, nbItems, int(resp.Pagination.Total)) + require.ElementsMatch(t, + nullify.Fill(items), + nullify.Fill(resp.ChainState), + ) + }) + }) } func TestKeeper_ChainState(t *testing.T) {