github.com/Finschia/finschia-sdk@v0.48.1/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  	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
    10  
    11  	"github.com/Finschia/finschia-sdk/baseapp"
    12  	"github.com/Finschia/finschia-sdk/simapp"
    13  	"github.com/Finschia/finschia-sdk/store/prefix"
    14  	sdk "github.com/Finschia/finschia-sdk/types"
    15  	"github.com/Finschia/finschia-sdk/x/params/types"
    16  	"github.com/Finschia/finschia-sdk/x/params/types/proposal"
    17  )
    18  
    19  type KeeperTestSuite struct {
    20  	suite.Suite
    21  
    22  	app *simapp.SimApp
    23  	ctx sdk.Context
    24  
    25  	queryClient proposal.QueryClient
    26  }
    27  
    28  func (suite *KeeperTestSuite) SetupTest() {
    29  	suite.app, suite.ctx = createTestApp(true)
    30  
    31  	queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.app.InterfaceRegistry())
    32  	proposal.RegisterQueryServer(queryHelper, suite.app.ParamsKeeper)
    33  	suite.queryClient = proposal.NewQueryClient(queryHelper)
    34  }
    35  
    36  func TestKeeperTestSuite(t *testing.T) {
    37  	suite.Run(t, new(KeeperTestSuite))
    38  }
    39  
    40  // returns context and app
    41  func createTestApp(isCheckTx bool) (*simapp.SimApp, sdk.Context) {
    42  	app := simapp.Setup(isCheckTx)
    43  	ctx := app.BaseApp.NewContext(isCheckTx, tmproto.Header{})
    44  
    45  	return app, ctx
    46  }
    47  
    48  func validateNoOp(_ interface{}) error { return nil }
    49  
    50  func TestKeeper(t *testing.T) {
    51  	kvs := []struct {
    52  		key   string
    53  		param int64
    54  	}{
    55  		{"key1", 10},
    56  		{"key2", 55},
    57  		{"key3", 182},
    58  		{"key4", 17582},
    59  		{"key5", 2768554},
    60  		{"key6", 1157279},
    61  		{"key7", 9058701},
    62  	}
    63  
    64  	table := types.NewKeyTable(
    65  		types.NewParamSetPair([]byte("key1"), int64(0), validateNoOp),
    66  		types.NewParamSetPair([]byte("key2"), int64(0), validateNoOp),
    67  		types.NewParamSetPair([]byte("key3"), int64(0), validateNoOp),
    68  		types.NewParamSetPair([]byte("key4"), int64(0), validateNoOp),
    69  		types.NewParamSetPair([]byte("key5"), int64(0), validateNoOp),
    70  		types.NewParamSetPair([]byte("key6"), int64(0), validateNoOp),
    71  		types.NewParamSetPair([]byte("key7"), int64(0), validateNoOp),
    72  		types.NewParamSetPair([]byte("extra1"), bool(false), validateNoOp),
    73  		types.NewParamSetPair([]byte("extra2"), string(""), validateNoOp),
    74  	)
    75  
    76  	cdc, ctx, skey, keeper := testComponents()
    77  
    78  	store := prefix.NewStore(ctx.KVStore(skey), []byte("test/"))
    79  	space := keeper.Subspace("test")
    80  	require.False(t, space.HasKeyTable())
    81  	space = space.WithKeyTable(table)
    82  	require.True(t, space.HasKeyTable())
    83  
    84  	// Set params
    85  	for i, kv := range kvs {
    86  		kv := kv
    87  		require.NotPanics(t, func() { space.Set(ctx, []byte(kv.key), kv.param) }, "space.Set panics, tc #%d", i)
    88  	}
    89  
    90  	// Test space.Get
    91  	for i, kv := range kvs {
    92  		i, kv := i, kv
    93  		var param int64
    94  		require.NotPanics(t, func() { space.Get(ctx, []byte(kv.key), &param) }, "space.Get panics, tc #%d", i)
    95  		require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i)
    96  	}
    97  
    98  	// Test space.GetRaw
    99  	for i, kv := range kvs {
   100  		var param int64
   101  		bz := space.GetRaw(ctx, []byte(kv.key))
   102  		err := cdc.UnmarshalJSON(bz, &param)
   103  		require.Nil(t, err, "err is not nil, tc #%d", i)
   104  		require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i)
   105  	}
   106  
   107  	// Test store.Get equals space.Get
   108  	for i, kv := range kvs {
   109  		var param int64
   110  		bz := store.Get([]byte(kv.key))
   111  		require.NotNil(t, bz, "KVStore.Get returns nil, tc #%d", i)
   112  		err := cdc.UnmarshalJSON(bz, &param)
   113  		require.NoError(t, err, "UnmarshalJSON returns error, tc #%d", i)
   114  		require.Equal(t, kv.param, param, "stored param not equal, tc #%d", i)
   115  	}
   116  
   117  	// Test invalid space.Get
   118  	for i, kv := range kvs {
   119  		kv := kv
   120  		var param bool
   121  		require.Panics(t, func() { space.Get(ctx, []byte(kv.key), &param) }, "invalid space.Get not panics, tc #%d", i)
   122  	}
   123  
   124  	// Test invalid space.Set
   125  	for i, kv := range kvs {
   126  		kv := kv
   127  		require.Panics(t, func() { space.Set(ctx, []byte(kv.key), true) }, "invalid space.Set not panics, tc #%d", i)
   128  	}
   129  
   130  	// Test GetSubspace
   131  	for i, kv := range kvs {
   132  		i, kv := i, kv
   133  		var gparam, param int64
   134  		gspace, ok := keeper.GetSubspace("test")
   135  		require.True(t, ok, "cannot retrieve subspace, tc #%d", i)
   136  
   137  		require.NotPanics(t, func() { gspace.Get(ctx, []byte(kv.key), &gparam) })
   138  		require.NotPanics(t, func() { space.Get(ctx, []byte(kv.key), &param) })
   139  		require.Equal(t, gparam, param, "GetSubspace().Get not equal with space.Get, tc #%d", i)
   140  
   141  		require.NotPanics(t, func() { gspace.Set(ctx, []byte(kv.key), int64(i)) })
   142  		require.NotPanics(t, func() { space.Get(ctx, []byte(kv.key), &param) })
   143  		require.Equal(t, int64(i), param, "GetSubspace().Set not equal with space.Get, tc #%d", i)
   144  	}
   145  }
   146  
   147  func indirect(ptr interface{}) interface{} {
   148  	return reflect.ValueOf(ptr).Elem().Interface()
   149  }
   150  
   151  func TestSubspace(t *testing.T) {
   152  	cdc, ctx, key, keeper := testComponents()
   153  
   154  	kvs := []struct {
   155  		key   string
   156  		param interface{}
   157  		zero  interface{}
   158  		ptr   interface{}
   159  	}{
   160  		{"string", "test", "", new(string)},
   161  		{"bool", true, false, new(bool)},
   162  		{"int16", int16(1), int16(0), new(int16)},
   163  		{"int32", int32(1), int32(0), new(int32)},
   164  		{"int64", int64(1), int64(0), new(int64)},
   165  		{"uint16", uint16(1), uint16(0), new(uint16)},
   166  		{"uint32", uint32(1), uint32(0), new(uint32)},
   167  		{"uint64", uint64(1), uint64(0), new(uint64)},
   168  		{"int", sdk.NewInt(1), *new(sdk.Int), new(sdk.Int)},
   169  		{"uint", sdk.NewUint(1), *new(sdk.Uint), new(sdk.Uint)},
   170  		{"dec", sdk.NewDec(1), *new(sdk.Dec), new(sdk.Dec)},
   171  		{"struct", s{1}, s{0}, new(s)},
   172  	}
   173  
   174  	table := types.NewKeyTable(
   175  		types.NewParamSetPair([]byte("string"), "", validateNoOp),
   176  		types.NewParamSetPair([]byte("bool"), false, validateNoOp),
   177  		types.NewParamSetPair([]byte("int16"), int16(0), validateNoOp),
   178  		types.NewParamSetPair([]byte("int32"), int32(0), validateNoOp),
   179  		types.NewParamSetPair([]byte("int64"), int64(0), validateNoOp),
   180  		types.NewParamSetPair([]byte("uint16"), uint16(0), validateNoOp),
   181  		types.NewParamSetPair([]byte("uint32"), uint32(0), validateNoOp),
   182  		types.NewParamSetPair([]byte("uint64"), uint64(0), validateNoOp),
   183  		types.NewParamSetPair([]byte("int"), sdk.Int{}, validateNoOp),
   184  		types.NewParamSetPair([]byte("uint"), sdk.Uint{}, validateNoOp),
   185  		types.NewParamSetPair([]byte("dec"), sdk.Dec{}, validateNoOp),
   186  		types.NewParamSetPair([]byte("struct"), s{}, validateNoOp),
   187  	)
   188  
   189  	store := prefix.NewStore(ctx.KVStore(key), []byte("test/"))
   190  	space := keeper.Subspace("test").WithKeyTable(table)
   191  
   192  	// Test space.Set
   193  	for i, kv := range kvs {
   194  		i, kv := i, kv
   195  		require.NotPanics(t, func() { space.Set(ctx, []byte(kv.key), kv.param) }, "space.Set panics, tc #%d", i)
   196  	}
   197  
   198  	// Test space.Get, space.GetIfExists
   199  	for i, kv := range kvs {
   200  		i, kv := i, kv
   201  		require.NotPanics(t, func() { space.GetIfExists(ctx, []byte("invalid"), kv.ptr) }, "space.GetIfExists panics when no value exists, tc #%d", i)
   202  		require.Equal(t, kv.zero, indirect(kv.ptr), "space.GetIfExists unmarshalls when no value exists, tc #%d", i)
   203  		require.Panics(t, func() { space.Get(ctx, []byte("invalid"), kv.ptr) }, "invalid space.Get not panics when no value exists, tc #%d", i)
   204  		require.Equal(t, kv.zero, indirect(kv.ptr), "invalid space.Get unmarshalls when no value exists, tc #%d", i)
   205  
   206  		require.NotPanics(t, func() { space.GetIfExists(ctx, []byte(kv.key), kv.ptr) }, "space.GetIfExists panics, tc #%d", i)
   207  		require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i)
   208  		require.NotPanics(t, func() { space.Get(ctx, []byte(kv.key), kv.ptr) }, "space.Get panics, tc #%d", i)
   209  		require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i)
   210  
   211  		require.Panics(t, func() { space.Get(ctx, []byte("invalid"), kv.ptr) }, "invalid space.Get not panics when no value exists, tc #%d", i)
   212  		require.Equal(t, kv.param, indirect(kv.ptr), "invalid space.Get unmarshalls when no value existt, tc #%d", i)
   213  
   214  		require.Panics(t, func() { space.Get(ctx, []byte(kv.key), nil) }, "invalid space.Get not panics when the pointer is nil, tc #%d", i)
   215  		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)
   216  	}
   217  
   218  	// Test store.Get equals space.Get
   219  	for i, kv := range kvs {
   220  		bz := store.Get([]byte(kv.key))
   221  		require.NotNil(t, bz, "store.Get() returns nil, tc #%d", i)
   222  		err := cdc.UnmarshalJSON(bz, kv.ptr)
   223  		require.NoError(t, err, "cdc.UnmarshalJSON() returns error, tc #%d", i)
   224  		require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i)
   225  	}
   226  }
   227  
   228  type paramJSON struct {
   229  	Param1 int64  `json:"param1,omitempty" yaml:"param1,omitempty"`
   230  	Param2 string `json:"param2,omitempty" yaml:"param2,omitempty"`
   231  }
   232  
   233  func TestJSONUpdate(t *testing.T) {
   234  	_, ctx, _, keeper := testComponents()
   235  
   236  	key := []byte("key")
   237  
   238  	space := keeper.Subspace("test").WithKeyTable(types.NewKeyTable(types.NewParamSetPair(key, paramJSON{}, validateNoOp)))
   239  
   240  	var param paramJSON
   241  
   242  	err := space.Update(ctx, key, []byte(`{"param1": "10241024"}`))
   243  	require.NoError(t, err)
   244  	space.Get(ctx, key, &param)
   245  	require.Equal(t, paramJSON{10241024, ""}, param)
   246  
   247  	err = space.Update(ctx, key, []byte(`{"param2": "helloworld"}`))
   248  	require.NoError(t, err)
   249  	space.Get(ctx, key, &param)
   250  	require.Equal(t, paramJSON{10241024, "helloworld"}, param)
   251  
   252  	err = space.Update(ctx, key, []byte(`{"param1": "20482048"}`))
   253  	require.NoError(t, err)
   254  	space.Get(ctx, key, &param)
   255  	require.Equal(t, paramJSON{20482048, "helloworld"}, param)
   256  
   257  	err = space.Update(ctx, key, []byte(`{"param1": "40964096", "param2": "goodbyeworld"}`))
   258  	require.NoError(t, err)
   259  	space.Get(ctx, key, &param)
   260  	require.Equal(t, paramJSON{40964096, "goodbyeworld"}, param)
   261  }