github.com/cosmos/cosmos-sdk@v0.50.10/x/group/keeper/grpc_query_test.go (about)

     1  package keeper_test
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/golang/mock/gomock"
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"cosmossdk.io/log"
    12  	storetypes "cosmossdk.io/store/types"
    13  
    14  	"github.com/cosmos/cosmos-sdk/baseapp"
    15  	"github.com/cosmos/cosmos-sdk/codec/address"
    16  	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
    17  	"github.com/cosmos/cosmos-sdk/testutil"
    18  	simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
    19  	"github.com/cosmos/cosmos-sdk/types"
    20  	moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
    21  	"github.com/cosmos/cosmos-sdk/types/query"
    22  	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
    23  	"github.com/cosmos/cosmos-sdk/x/group"
    24  	groupkeeper "github.com/cosmos/cosmos-sdk/x/group/keeper"
    25  	"github.com/cosmos/cosmos-sdk/x/group/module"
    26  	grouptestutil "github.com/cosmos/cosmos-sdk/x/group/testutil"
    27  )
    28  
    29  type fixture struct {
    30  	ctx          types.Context
    31  	keeper       groupkeeper.Keeper
    32  	queryClient  group.QueryClient
    33  	addrs        []types.AccAddress
    34  	defaultGroup *group.MsgCreateGroupWithPolicyResponse
    35  }
    36  
    37  func initKeeper(t *testing.T) *fixture {
    38  	t.Helper()
    39  	var (
    40  		groupKeeper       groupkeeper.Keeper
    41  		interfaceRegistry codectypes.InterfaceRegistry
    42  	)
    43  
    44  	key := storetypes.NewKVStoreKey(group.StoreKey)
    45  	testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test"))
    46  	encCfg := moduletestutil.MakeTestEncodingConfig(module.AppModuleBasic{})
    47  
    48  	ctx := testCtx.Ctx
    49  
    50  	bApp := baseapp.NewBaseApp(
    51  		"group",
    52  		log.NewNopLogger(),
    53  		testCtx.DB,
    54  		encCfg.TxConfig.TxDecoder(),
    55  	)
    56  
    57  	addrs := simtestutil.CreateIncrementalAccounts(6)
    58  	ctrl := gomock.NewController(t)
    59  	accountKeeper := grouptestutil.NewMockAccountKeeper(ctrl)
    60  	for _, addr := range addrs {
    61  		accountKeeper.EXPECT().GetAccount(gomock.Any(), addr).Return(authtypes.NewBaseAccountWithAddress(addr)).AnyTimes()
    62  	}
    63  	accountKeeper.EXPECT().AddressCodec().Return(address.NewBech32Codec("cosmos")).AnyTimes()
    64  
    65  	// group policy expected calls
    66  	accountKeeper.EXPECT().GetAccount(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
    67  	accountKeeper.EXPECT().NewAccount(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
    68  	accountKeeper.EXPECT().SetAccount(gomock.Any(), gomock.Any()).AnyTimes()
    69  
    70  	groupKeeper = groupkeeper.NewKeeper(key, encCfg.Codec, bApp.MsgServiceRouter(), accountKeeper, group.DefaultConfig())
    71  	queryHelper := baseapp.NewQueryServerTestHelper(ctx, interfaceRegistry)
    72  	group.RegisterQueryServer(queryHelper, groupKeeper)
    73  	queryClient := group.NewQueryClient(queryHelper)
    74  
    75  	msgGroupAndPolicy := &group.MsgCreateGroupWithPolicy{
    76  		Admin: addrs[0].String(),
    77  		Members: []group.MemberRequest{
    78  			{Address: addrs[1].String(), Weight: "1"},
    79  			{Address: addrs[3].String(), Weight: "2"},
    80  		},
    81  	}
    82  	err := msgGroupAndPolicy.SetDecisionPolicy(group.NewThresholdDecisionPolicy("2", time.Second, 20))
    83  	require.NoError(t, err)
    84  
    85  	resp, err := groupKeeper.CreateGroupWithPolicy(ctx, msgGroupAndPolicy)
    86  	require.NoError(t, err)
    87  
    88  	return &fixture{
    89  		ctx:          ctx,
    90  		keeper:       groupKeeper,
    91  		queryClient:  queryClient,
    92  		addrs:        addrs,
    93  		defaultGroup: resp,
    94  	}
    95  }
    96  
    97  func TestQueryGroupInfo(t *testing.T) {
    98  	fixture := initKeeper(t)
    99  
   100  	testCases := []struct {
   101  		name      string
   102  		req       group.QueryGroupInfoRequest
   103  		expErrMsg string
   104  	}{
   105  		{
   106  			name:      "invalid req",
   107  			expErrMsg: "group: not found",
   108  		},
   109  		{
   110  			name:      "unknown id",
   111  			req:       group.QueryGroupInfoRequest{GroupId: 20},
   112  			expErrMsg: "group: not found",
   113  		},
   114  		{
   115  			name:      "valid id",
   116  			req:       group.QueryGroupInfoRequest{GroupId: 1},
   117  			expErrMsg: "",
   118  		},
   119  	}
   120  
   121  	for _, tc := range testCases {
   122  		t.Run(tc.name, func(t *testing.T) {
   123  			_, err := fixture.queryClient.GroupInfo(fixture.ctx, &tc.req)
   124  			if tc.expErrMsg != "" {
   125  				require.Error(t, err)
   126  				require.Contains(t, err.Error(), tc.expErrMsg)
   127  			} else {
   128  				require.NoError(t, err)
   129  			}
   130  		})
   131  	}
   132  }
   133  
   134  func TestQueryGroupPolicyInfo(t *testing.T) {
   135  	fixture := initKeeper(t)
   136  
   137  	testCases := []struct {
   138  		name      string
   139  		req       group.QueryGroupPolicyInfoRequest
   140  		expErrMsg string
   141  	}{
   142  		{
   143  			name:      "valid address",
   144  			req:       group.QueryGroupPolicyInfoRequest{Address: fixture.defaultGroup.GroupPolicyAddress},
   145  			expErrMsg: "",
   146  		},
   147  		{
   148  			name:      "unexisting address",
   149  			req:       group.QueryGroupPolicyInfoRequest{Address: fixture.addrs[5].String()},
   150  			expErrMsg: "group policy: not found",
   151  		},
   152  		{
   153  			name:      "invalid address",
   154  			req:       group.QueryGroupPolicyInfoRequest{Address: "invalid address"},
   155  			expErrMsg: "decoding bech32 failed",
   156  		},
   157  	}
   158  
   159  	for _, tc := range testCases {
   160  		t.Run(tc.name, func(t *testing.T) {
   161  			_, err := fixture.queryClient.GroupPolicyInfo(fixture.ctx, &tc.req)
   162  			if tc.expErrMsg != "" {
   163  				require.Error(t, err)
   164  				require.Contains(t, err.Error(), tc.expErrMsg)
   165  			} else {
   166  				require.NoError(t, err)
   167  			}
   168  		})
   169  	}
   170  }
   171  
   172  func TestQueryGroupMembers(t *testing.T) {
   173  	fixture := initKeeper(t)
   174  
   175  	testCases := []struct {
   176  		name      string
   177  		req       group.QueryGroupMembersRequest
   178  		postRun   func(resp *group.QueryGroupMembersResponse)
   179  		expErrMsg string
   180  	}{
   181  		{
   182  			name: "valid group",
   183  			req:  group.QueryGroupMembersRequest{GroupId: 1},
   184  			postRun: func(resp *group.QueryGroupMembersResponse) {
   185  				require.Len(t, resp.Members, 2)
   186  			},
   187  			expErrMsg: "",
   188  		},
   189  		{
   190  			name: "unexisting group",
   191  			req:  group.QueryGroupMembersRequest{GroupId: 20},
   192  			postRun: func(resp *group.QueryGroupMembersResponse) {
   193  				require.Len(t, resp.Members, 0)
   194  			},
   195  			expErrMsg: "",
   196  		},
   197  	}
   198  
   199  	for _, tc := range testCases {
   200  		t.Run(tc.name, func(t *testing.T) {
   201  			resp, err := fixture.queryClient.GroupMembers(fixture.ctx, &tc.req)
   202  			if tc.expErrMsg != "" {
   203  				require.Error(t, err)
   204  				require.Contains(t, err.Error(), tc.expErrMsg)
   205  			} else {
   206  				require.NoError(t, err)
   207  			}
   208  
   209  			if tc.postRun != nil {
   210  				tc.postRun(resp)
   211  			}
   212  		})
   213  	}
   214  }
   215  
   216  func TestQueryGroupsByAdmin(t *testing.T) {
   217  	fixture := initKeeper(t)
   218  
   219  	testCases := []struct {
   220  		name      string
   221  		req       group.QueryGroupsByAdminRequest
   222  		postRun   func(resp *group.QueryGroupsByAdminResponse)
   223  		expErrMsg string
   224  	}{
   225  		{
   226  			name:      "valid admin",
   227  			req:       group.QueryGroupsByAdminRequest{Admin: fixture.addrs[0].String()},
   228  			postRun:   func(resp *group.QueryGroupsByAdminResponse) { require.Len(t, resp.Groups, 1) },
   229  			expErrMsg: "",
   230  		},
   231  		{
   232  			name:      "unexisting address",
   233  			req:       group.QueryGroupsByAdminRequest{Admin: fixture.addrs[5].String()},
   234  			postRun:   func(resp *group.QueryGroupsByAdminResponse) { require.Len(t, resp.Groups, 0) },
   235  			expErrMsg: "",
   236  		},
   237  		{
   238  			name:      "invalid address",
   239  			req:       group.QueryGroupsByAdminRequest{Admin: "invalid address"},
   240  			expErrMsg: "decoding bech32 failed",
   241  		},
   242  	}
   243  
   244  	for _, tc := range testCases {
   245  		t.Run(tc.name, func(t *testing.T) {
   246  			resp, err := fixture.queryClient.GroupsByAdmin(fixture.ctx, &tc.req)
   247  			if tc.expErrMsg != "" {
   248  				require.Error(t, err)
   249  				require.Contains(t, err.Error(), tc.expErrMsg)
   250  			} else {
   251  				require.NoError(t, err)
   252  			}
   253  
   254  			if tc.postRun != nil {
   255  				tc.postRun(resp)
   256  			}
   257  		})
   258  	}
   259  }
   260  
   261  func TestQueryGroupPoliciesByGroup(t *testing.T) {
   262  	fixture := initKeeper(t)
   263  
   264  	testCases := []struct {
   265  		name      string
   266  		req       group.QueryGroupPoliciesByGroupRequest
   267  		postRun   func(resp *group.QueryGroupPoliciesByGroupResponse)
   268  		expErrMsg string
   269  	}{
   270  		{
   271  			name:      "valid group",
   272  			req:       group.QueryGroupPoliciesByGroupRequest{GroupId: 1},
   273  			postRun:   func(resp *group.QueryGroupPoliciesByGroupResponse) { require.Len(t, resp.GroupPolicies, 1) },
   274  			expErrMsg: "",
   275  		},
   276  		{
   277  			name:      "unexisting group",
   278  			req:       group.QueryGroupPoliciesByGroupRequest{GroupId: 20},
   279  			postRun:   func(resp *group.QueryGroupPoliciesByGroupResponse) { require.Len(t, resp.GroupPolicies, 0) },
   280  			expErrMsg: "",
   281  		},
   282  	}
   283  
   284  	for _, tc := range testCases {
   285  		t.Run(tc.name, func(t *testing.T) {
   286  			resp, err := fixture.keeper.GroupPoliciesByGroup(fixture.ctx, &tc.req)
   287  			if tc.expErrMsg != "" {
   288  				require.Error(t, err)
   289  				require.Contains(t, err.Error(), tc.expErrMsg)
   290  			} else {
   291  				require.NoError(t, err)
   292  			}
   293  
   294  			if tc.postRun != nil {
   295  				tc.postRun(resp)
   296  			}
   297  		})
   298  	}
   299  }
   300  
   301  func TestQueryGroupPoliciesByAdmin(t *testing.T) {
   302  	fixture := initKeeper(t)
   303  
   304  	testCases := []struct {
   305  		name      string
   306  		req       group.QueryGroupPoliciesByAdminRequest
   307  		postRun   func(resp *group.QueryGroupPoliciesByAdminResponse)
   308  		expErrMsg string
   309  	}{
   310  		{
   311  			name:      "valid admin",
   312  			req:       group.QueryGroupPoliciesByAdminRequest{Admin: fixture.addrs[0].String()},
   313  			postRun:   func(resp *group.QueryGroupPoliciesByAdminResponse) { require.Len(t, resp.GroupPolicies, 1) },
   314  			expErrMsg: "",
   315  		},
   316  		{
   317  			name:      "unexisting address",
   318  			req:       group.QueryGroupPoliciesByAdminRequest{Admin: fixture.addrs[5].String()},
   319  			postRun:   func(resp *group.QueryGroupPoliciesByAdminResponse) { require.Len(t, resp.GroupPolicies, 0) },
   320  			expErrMsg: "",
   321  		},
   322  		{
   323  			name:      "invalid address",
   324  			req:       group.QueryGroupPoliciesByAdminRequest{Admin: "invalid address"},
   325  			expErrMsg: "decoding bech32 failed",
   326  		},
   327  	}
   328  
   329  	for _, tc := range testCases {
   330  		t.Run(tc.name, func(t *testing.T) {
   331  			resp, err := fixture.keeper.GroupPoliciesByAdmin(fixture.ctx, &tc.req)
   332  			if tc.expErrMsg != "" {
   333  				require.Error(t, err)
   334  				require.Contains(t, err.Error(), tc.expErrMsg)
   335  			} else {
   336  				require.NoError(t, err)
   337  			}
   338  
   339  			if tc.postRun != nil {
   340  				tc.postRun(resp)
   341  			}
   342  		})
   343  	}
   344  }
   345  
   346  func TestQueryGroupsByMember(t *testing.T) {
   347  	fixture := initKeeper(t)
   348  
   349  	members := []group.MemberRequest{
   350  		{Address: fixture.addrs[3].String(), Weight: "1"}, {Address: fixture.addrs[4].String(), Weight: "2"},
   351  	}
   352  	_, err := fixture.keeper.CreateGroup(fixture.ctx, &group.MsgCreateGroup{
   353  		Admin:   fixture.addrs[1].String(),
   354  		Members: members,
   355  	})
   356  	require.NoError(t, err)
   357  
   358  	// not part of any group
   359  	resp, err := fixture.queryClient.GroupsByMember(context.Background(), &group.QueryGroupsByMemberRequest{
   360  		Address: fixture.addrs[5].String(),
   361  	})
   362  	require.NoError(t, err)
   363  	require.Len(t, resp.Groups, 0)
   364  
   365  	// expect one group
   366  	resp, err = fixture.queryClient.GroupsByMember(context.Background(), &group.QueryGroupsByMemberRequest{
   367  		Address: fixture.addrs[4].String(),
   368  	})
   369  	require.NoError(t, err)
   370  	require.Len(t, resp.Groups, 1)
   371  
   372  	// expect two groups
   373  	resp, err = fixture.queryClient.GroupsByMember(context.Background(), &group.QueryGroupsByMemberRequest{
   374  		Address: fixture.addrs[3].String(),
   375  	})
   376  	require.NoError(t, err)
   377  	require.Len(t, resp.Groups, 2)
   378  }
   379  
   380  func TestQueryGroups(t *testing.T) {
   381  	fixture := initKeeper(t)
   382  
   383  	members := []group.MemberRequest{
   384  		{Address: fixture.addrs[3].String(), Weight: "1"},
   385  	}
   386  	_, err := fixture.keeper.CreateGroup(fixture.ctx, &group.MsgCreateGroup{
   387  		Admin:   fixture.addrs[2].String(),
   388  		Members: members,
   389  	})
   390  	require.NoError(t, err)
   391  
   392  	testCases := []struct {
   393  		name         string
   394  		expErr       bool
   395  		expLen       int
   396  		itemsPerPage uint64
   397  	}{
   398  		{
   399  			name:         "success case, without pagination",
   400  			expErr:       false,
   401  			expLen:       2,
   402  			itemsPerPage: 10,
   403  		},
   404  		{
   405  			name:         "success case, with pagination",
   406  			expErr:       false,
   407  			expLen:       1,
   408  			itemsPerPage: 1,
   409  		},
   410  		{
   411  			name:   "success without pagination",
   412  			expErr: false,
   413  			expLen: 2,
   414  		},
   415  	}
   416  
   417  	for _, tc := range testCases {
   418  		t.Run(tc.name, func(t *testing.T) {
   419  			resp, err := fixture.queryClient.Groups(context.Background(), &group.QueryGroupsRequest{
   420  				Pagination: &query.PageRequest{
   421  					Limit: tc.itemsPerPage,
   422  				},
   423  			})
   424  
   425  			if tc.expErr {
   426  				require.Error(t, err)
   427  			} else {
   428  				require.NoError(t, err)
   429  				require.Equal(t, len(resp.Groups), tc.expLen)
   430  			}
   431  		})
   432  	}
   433  }