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), &param) }, "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, &param)
   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, &param)
   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), &param) }, "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), &param) })
   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), &param) })
   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, &param)
   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, &param)
   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, &param)
   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, &param)
   289  	require.Equal(t, paramJSON{40964096, "goodbyeworld"}, param)
   290  }