github.com/cosmos/cosmos-sdk@v0.50.10/x/params/keeper/keeper_test.go (about) 1 package keeper_test 2 3 import ( 4 "reflect" 5 "testing" 6 7 "github.com/stretchr/testify/require" 8 "github.com/stretchr/testify/suite" 9 10 "cosmossdk.io/math" 11 "cosmossdk.io/store/prefix" 12 storetypes "cosmossdk.io/store/types" 13 14 "github.com/cosmos/cosmos-sdk/baseapp" 15 "github.com/cosmos/cosmos-sdk/testutil" 16 sdk "github.com/cosmos/cosmos-sdk/types" 17 moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" 18 "github.com/cosmos/cosmos-sdk/x/params" 19 "github.com/cosmos/cosmos-sdk/x/params/keeper" 20 "github.com/cosmos/cosmos-sdk/x/params/types" 21 "github.com/cosmos/cosmos-sdk/x/params/types/proposal" 22 ) 23 24 type KeeperTestSuite struct { 25 suite.Suite 26 27 ctx sdk.Context 28 paramsKeeper keeper.Keeper 29 queryClient proposal.QueryClient 30 } 31 32 func (suite *KeeperTestSuite) SetupTest() { 33 encodingCfg := moduletestutil.MakeTestEncodingConfig(params.AppModuleBasic{}) 34 key := storetypes.NewKVStoreKey(types.StoreKey) 35 tkey := storetypes.NewTransientStoreKey("params_transient_test") 36 37 suite.ctx = testutil.DefaultContext(key, tkey) 38 suite.paramsKeeper = keeper.NewKeeper(encodingCfg.Codec, encodingCfg.Amino, key, tkey) 39 suite.paramsKeeper.Subspace("bank") 40 suite.paramsKeeper.Subspace("staking") 41 42 queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, encodingCfg.InterfaceRegistry) 43 proposal.RegisterQueryServer(queryHelper, suite.paramsKeeper) 44 45 suite.queryClient = proposal.NewQueryClient(queryHelper) 46 } 47 48 func TestKeeperTestSuite(t *testing.T) { 49 suite.Run(t, new(KeeperTestSuite)) 50 } 51 52 func validateNoOp(_ interface{}) error { return nil } 53 54 func TestKeeper(t *testing.T) { 55 kvs := []struct { 56 key string 57 param int64 58 }{ 59 {"key1", 10}, 60 {"key2", 55}, 61 {"key3", 182}, 62 {"key4", 17582}, 63 {"key5", 2768554}, 64 {"key6", 1157279}, 65 {"key7", 9058701}, 66 } 67 68 table := types.NewKeyTable( 69 types.NewParamSetPair([]byte("key1"), int64(0), validateNoOp), 70 types.NewParamSetPair([]byte("key2"), int64(0), validateNoOp), 71 types.NewParamSetPair([]byte("key3"), int64(0), validateNoOp), 72 types.NewParamSetPair([]byte("key4"), int64(0), validateNoOp), 73 types.NewParamSetPair([]byte("key5"), int64(0), validateNoOp), 74 types.NewParamSetPair([]byte("key6"), int64(0), validateNoOp), 75 types.NewParamSetPair([]byte("key7"), int64(0), validateNoOp), 76 types.NewParamSetPair([]byte("extra1"), bool(false), validateNoOp), 77 types.NewParamSetPair([]byte("extra2"), string(""), validateNoOp), 78 ) 79 80 cdc, ctx, skey, _, keeper := testComponents() 81 82 store := prefix.NewStore(ctx.KVStore(skey), []byte("test/")) 83 space := keeper.Subspace("test") 84 require.False(t, space.HasKeyTable()) 85 space = space.WithKeyTable(table) 86 require.True(t, space.HasKeyTable()) 87 88 // Set params 89 for i, kv := range kvs { 90 kv := kv 91 require.NotPanics(t, func() { space.Set(ctx, []byte(kv.key), kv.param) }, "space.Set panics, tc #%d", i) 92 } 93 94 // Test space.Get 95 for i, kv := range kvs { 96 i, kv := i, kv 97 var param int64 98 require.NotPanics(t, func() { space.Get(ctx, []byte(kv.key), ¶m) }, "space.Get panics, tc #%d", i) 99 require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) 100 } 101 102 // Test space.GetRaw 103 for i, kv := range kvs { 104 var param int64 105 bz := space.GetRaw(ctx, []byte(kv.key)) 106 err := cdc.UnmarshalJSON(bz, ¶m) 107 require.Nil(t, err, "err is not nil, tc #%d", i) 108 require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) 109 } 110 111 // Test store.Get equals space.Get 112 for i, kv := range kvs { 113 var param int64 114 bz := store.Get([]byte(kv.key)) 115 require.NotNil(t, bz, "KVStore.Get returns nil, tc #%d", i) 116 err := cdc.UnmarshalJSON(bz, ¶m) 117 require.NoError(t, err, "UnmarshalJSON returns error, tc #%d", i) 118 require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i) 119 } 120 121 // Test invalid space.Get 122 for i, kv := range kvs { 123 kv := kv 124 var param bool 125 require.Panics(t, func() { space.Get(ctx, []byte(kv.key), ¶m) }, "invalid space.Get not panics, tc #%d", i) 126 } 127 128 // Test invalid space.Set 129 for i, kv := range kvs { 130 kv := kv 131 require.Panics(t, func() { space.Set(ctx, []byte(kv.key), true) }, "invalid space.Set not panics, tc #%d", i) 132 } 133 134 // Test GetSubspace 135 for i, kv := range kvs { 136 i, kv := i, kv 137 var gparam, param int64 138 gspace, ok := keeper.GetSubspace("test") 139 require.True(t, ok, "cannot retrieve subspace, tc #%d", i) 140 141 require.NotPanics(t, func() { gspace.Get(ctx, []byte(kv.key), &gparam) }) 142 require.NotPanics(t, func() { space.Get(ctx, []byte(kv.key), ¶m) }) 143 require.Equal(t, gparam, param, "GetSubspace().Get not equal with space.Get, tc #%d", i) 144 145 require.NotPanics(t, func() { gspace.Set(ctx, []byte(kv.key), int64(i)) }) 146 require.NotPanics(t, func() { space.Get(ctx, []byte(kv.key), ¶m) }) 147 require.Equal(t, int64(i), param, "GetSubspace().Set not equal with space.Get, tc #%d", i) 148 } 149 } 150 151 func indirect(ptr interface{}) interface{} { 152 return reflect.ValueOf(ptr).Elem().Interface() 153 } 154 155 func TestGetSubspaces(t *testing.T) { 156 _, _, _, _, keeper := testComponents() 157 158 table := types.NewKeyTable( 159 types.NewParamSetPair([]byte("string"), "", validateNoOp), 160 types.NewParamSetPair([]byte("bool"), false, validateNoOp), 161 ) 162 163 _ = keeper.Subspace("key1").WithKeyTable(table) 164 _ = keeper.Subspace("key2").WithKeyTable(table) 165 166 spaces := keeper.GetSubspaces() 167 require.Len(t, spaces, 2) 168 169 var names []string 170 for _, ss := range spaces { 171 names = append(names, ss.Name()) 172 } 173 174 require.Contains(t, names, "key1") 175 require.Contains(t, names, "key2") 176 } 177 178 func TestSubspace(t *testing.T) { 179 cdc, ctx, key, _, keeper := testComponents() 180 181 kvs := []struct { 182 key string 183 param interface{} 184 zero interface{} 185 ptr interface{} 186 }{ 187 {"string", "test", "", new(string)}, 188 {"bool", true, false, new(bool)}, 189 {"int16", int16(1), int16(0), new(int16)}, 190 {"int32", int32(1), int32(0), new(int32)}, 191 {"int64", int64(1), int64(0), new(int64)}, 192 {"uint16", uint16(1), uint16(0), new(uint16)}, 193 {"uint32", uint32(1), uint32(0), new(uint32)}, 194 {"uint64", uint64(1), uint64(0), new(uint64)}, 195 {"int", math.NewInt(1), math.Int{}, new(math.Int)}, 196 {"uint", math.NewUint(1), math.Uint{}, new(math.Uint)}, 197 {"dec", math.LegacyNewDec(1), math.LegacyDec{}, new(math.LegacyDec)}, 198 {"struct", s{1}, s{0}, new(s)}, 199 } 200 201 table := types.NewKeyTable( 202 types.NewParamSetPair([]byte("string"), "", validateNoOp), 203 types.NewParamSetPair([]byte("bool"), false, validateNoOp), 204 types.NewParamSetPair([]byte("int16"), int16(0), validateNoOp), 205 types.NewParamSetPair([]byte("int32"), int32(0), validateNoOp), 206 types.NewParamSetPair([]byte("int64"), int64(0), validateNoOp), 207 types.NewParamSetPair([]byte("uint16"), uint16(0), validateNoOp), 208 types.NewParamSetPair([]byte("uint32"), uint32(0), validateNoOp), 209 types.NewParamSetPair([]byte("uint64"), uint64(0), validateNoOp), 210 types.NewParamSetPair([]byte("int"), math.Int{}, validateNoOp), 211 types.NewParamSetPair([]byte("uint"), math.Uint{}, validateNoOp), 212 types.NewParamSetPair([]byte("dec"), math.LegacyDec{}, validateNoOp), 213 types.NewParamSetPair([]byte("struct"), s{}, validateNoOp), 214 ) 215 216 store := prefix.NewStore(ctx.KVStore(key), []byte("test/")) 217 space := keeper.Subspace("test").WithKeyTable(table) 218 219 // Test space.Set, space.Modified 220 for i, kv := range kvs { 221 i, kv := i, kv 222 require.False(t, space.Modified(ctx, []byte(kv.key)), "space.Modified returns true before setting, tc #%d", i) 223 require.NotPanics(t, func() { space.Set(ctx, []byte(kv.key), kv.param) }, "space.Set panics, tc #%d", i) 224 require.True(t, space.Modified(ctx, []byte(kv.key)), "space.Modified returns false after setting, tc #%d", i) 225 } 226 227 // Test space.Get, space.GetIfExists 228 for i, kv := range kvs { 229 i, kv := i, kv 230 require.NotPanics(t, func() { space.GetIfExists(ctx, []byte("invalid"), kv.ptr) }, "space.GetIfExists panics when no value exists, tc #%d", i) 231 require.Equal(t, kv.zero, indirect(kv.ptr), "space.GetIfExists unmarshalls when no value exists, tc #%d", i) 232 require.Panics(t, func() { space.Get(ctx, []byte("invalid"), kv.ptr) }, "invalid space.Get not panics when no value exists, tc #%d", i) 233 require.Equal(t, kv.zero, indirect(kv.ptr), "invalid space.Get unmarshalls when no value exists, tc #%d", i) 234 235 require.NotPanics(t, func() { space.GetIfExists(ctx, []byte(kv.key), kv.ptr) }, "space.GetIfExists panics, tc #%d", i) 236 require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) 237 require.NotPanics(t, func() { space.Get(ctx, []byte(kv.key), kv.ptr) }, "space.Get panics, tc #%d", i) 238 require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) 239 240 require.Panics(t, func() { space.Get(ctx, []byte("invalid"), kv.ptr) }, "invalid space.Get not panics when no value exists, tc #%d", i) 241 require.Equal(t, kv.param, indirect(kv.ptr), "invalid space.Get unmarshalls when no value existt, tc #%d", i) 242 243 require.Panics(t, func() { space.Get(ctx, []byte(kv.key), nil) }, "invalid space.Get not panics when the pointer is nil, tc #%d", i) 244 require.Panics(t, func() { space.Get(ctx, []byte(kv.key), new(invalid)) }, "invalid space.Get not panics when the pointer is different type, tc #%d", i) 245 } 246 247 // Test store.Get equals space.Get 248 for i, kv := range kvs { 249 bz := store.Get([]byte(kv.key)) 250 require.NotNil(t, bz, "store.Get() returns nil, tc #%d", i) 251 err := cdc.UnmarshalJSON(bz, kv.ptr) 252 require.NoError(t, err, "cdc.UnmarshalJSON() returns error, tc #%d", i) 253 require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) 254 } 255 } 256 257 type paramJSON struct { 258 Param1 int64 `json:"param1,omitempty" yaml:"param1,omitempty"` 259 Param2 string `json:"param2,omitempty" yaml:"param2,omitempty"` 260 } 261 262 func TestJSONUpdate(t *testing.T) { 263 _, ctx, _, _, keeper := testComponents() 264 265 key := []byte("key") 266 267 space := keeper.Subspace("test").WithKeyTable(types.NewKeyTable(types.NewParamSetPair(key, paramJSON{}, validateNoOp))) 268 269 var param paramJSON 270 271 err := space.Update(ctx, key, []byte(`{"param1": "10241024"}`)) 272 require.NoError(t, err) 273 space.Get(ctx, key, ¶m) 274 require.Equal(t, paramJSON{10241024, ""}, param) 275 276 err = space.Update(ctx, key, []byte(`{"param2": "helloworld"}`)) 277 require.NoError(t, err) 278 space.Get(ctx, key, ¶m) 279 require.Equal(t, paramJSON{10241024, "helloworld"}, param) 280 281 err = space.Update(ctx, key, []byte(`{"param1": "20482048"}`)) 282 require.NoError(t, err) 283 space.Get(ctx, key, ¶m) 284 require.Equal(t, paramJSON{20482048, "helloworld"}, param) 285 286 err = space.Update(ctx, key, []byte(`{"param1": "40964096", "param2": "goodbyeworld"}`)) 287 require.NoError(t, err) 288 space.Get(ctx, key, ¶m) 289 require.Equal(t, paramJSON{40964096, "goodbyeworld"}, param) 290 }