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 }