github.com/Finschia/finschia-sdk@v0.49.1/x/capability/keeper/keeper_test.go (about)

     1  package keeper_test
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/suite"
     8  	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
     9  
    10  	"github.com/Finschia/finschia-sdk/codec"
    11  	"github.com/Finschia/finschia-sdk/simapp"
    12  	sdk "github.com/Finschia/finschia-sdk/types"
    13  	banktypes "github.com/Finschia/finschia-sdk/x/bank/types"
    14  	"github.com/Finschia/finschia-sdk/x/capability/keeper"
    15  	"github.com/Finschia/finschia-sdk/x/capability/types"
    16  	stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types"
    17  )
    18  
    19  type KeeperTestSuite struct {
    20  	suite.Suite
    21  
    22  	cdc    codec.Codec
    23  	ctx    sdk.Context
    24  	app    *simapp.SimApp
    25  	keeper *keeper.Keeper
    26  }
    27  
    28  func (suite *KeeperTestSuite) SetupTest() {
    29  	checkTx := false
    30  	app := simapp.Setup(checkTx)
    31  	cdc := app.AppCodec()
    32  
    33  	// create new keeper so we can define custom scoping before init and seal
    34  	keeper := keeper.NewKeeper(cdc, app.GetKey(types.StoreKey), app.GetMemKey(types.MemStoreKey))
    35  
    36  	suite.app = app
    37  	suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1})
    38  	suite.keeper = keeper
    39  	suite.cdc = cdc
    40  }
    41  
    42  func (suite *KeeperTestSuite) TestSeal() {
    43  	sk := suite.keeper.ScopeToModule(banktypes.ModuleName)
    44  	suite.Require().Panics(func() {
    45  		suite.keeper.ScopeToModule("  ")
    46  	})
    47  
    48  	caps := make([]*types.Capability, 5)
    49  	// Get Latest Index before creating new ones to sychronize indices correctly
    50  	prevIndex := suite.keeper.GetLatestIndex(suite.ctx)
    51  
    52  	for i := range caps {
    53  		cap, err := sk.NewCapability(suite.ctx, fmt.Sprintf("transfer-%d", i))
    54  		suite.Require().NoError(err)
    55  		suite.Require().NotNil(cap)
    56  		suite.Require().Equal(uint64(i)+prevIndex, cap.GetIndex())
    57  
    58  		caps[i] = cap
    59  	}
    60  
    61  	suite.Require().NotPanics(func() {
    62  		suite.keeper.Seal()
    63  	})
    64  
    65  	for i, cap := range caps {
    66  		got, ok := sk.GetCapability(suite.ctx, fmt.Sprintf("transfer-%d", i))
    67  		suite.Require().True(ok)
    68  		suite.Require().Equal(cap, got)
    69  		suite.Require().Equal(uint64(i)+prevIndex, got.GetIndex())
    70  	}
    71  
    72  	suite.Require().Panics(func() {
    73  		suite.keeper.Seal()
    74  	})
    75  
    76  	suite.Require().Panics(func() {
    77  		_ = suite.keeper.ScopeToModule(stakingtypes.ModuleName)
    78  	})
    79  }
    80  
    81  func (suite *KeeperTestSuite) TestNewCapability() {
    82  	sk := suite.keeper.ScopeToModule(banktypes.ModuleName)
    83  
    84  	got, ok := sk.GetCapability(suite.ctx, "transfer")
    85  	suite.Require().False(ok)
    86  	suite.Require().Nil(got)
    87  
    88  	cap, err := sk.NewCapability(suite.ctx, "transfer")
    89  	suite.Require().NoError(err)
    90  	suite.Require().NotNil(cap)
    91  
    92  	got, ok = sk.GetCapability(suite.ctx, "transfer")
    93  	suite.Require().True(ok)
    94  	suite.Require().Equal(cap, got)
    95  	suite.Require().True(cap == got, "expected memory addresses to be equal")
    96  
    97  	got, ok = sk.GetCapability(suite.ctx, "invalid")
    98  	suite.Require().False(ok)
    99  	suite.Require().Nil(got)
   100  
   101  	got, ok = sk.GetCapability(suite.ctx, "transfer")
   102  	suite.Require().True(ok)
   103  	suite.Require().Equal(cap, got)
   104  	suite.Require().True(cap == got, "expected memory addresses to be equal")
   105  
   106  	cap2, err := sk.NewCapability(suite.ctx, "transfer")
   107  	suite.Require().Error(err)
   108  	suite.Require().Nil(cap2)
   109  
   110  	got, ok = sk.GetCapability(suite.ctx, "transfer")
   111  	suite.Require().True(ok)
   112  	suite.Require().Equal(cap, got)
   113  	suite.Require().True(cap == got, "expected memory addresses to be equal")
   114  
   115  	cap, err = sk.NewCapability(suite.ctx, "   ")
   116  	suite.Require().Error(err)
   117  	suite.Require().Nil(cap)
   118  }
   119  
   120  func (suite *KeeperTestSuite) TestAuthenticateCapability() {
   121  	sk1 := suite.keeper.ScopeToModule(banktypes.ModuleName)
   122  	sk2 := suite.keeper.ScopeToModule(stakingtypes.ModuleName)
   123  
   124  	cap1, err := sk1.NewCapability(suite.ctx, "transfer")
   125  	suite.Require().NoError(err)
   126  	suite.Require().NotNil(cap1)
   127  
   128  	forgedCap := types.NewCapability(cap1.Index) // index should be the same index as the first capability
   129  	suite.Require().False(sk1.AuthenticateCapability(suite.ctx, forgedCap, "transfer"))
   130  	suite.Require().False(sk2.AuthenticateCapability(suite.ctx, forgedCap, "transfer"))
   131  
   132  	cap2, err := sk2.NewCapability(suite.ctx, "bond")
   133  	suite.Require().NoError(err)
   134  	suite.Require().NotNil(cap2)
   135  
   136  	got, ok := sk1.GetCapability(suite.ctx, "transfer")
   137  	suite.Require().True(ok)
   138  
   139  	suite.Require().True(sk1.AuthenticateCapability(suite.ctx, cap1, "transfer"))
   140  	suite.Require().True(sk1.AuthenticateCapability(suite.ctx, got, "transfer"))
   141  	suite.Require().False(sk1.AuthenticateCapability(suite.ctx, cap1, "invalid"))
   142  	suite.Require().False(sk1.AuthenticateCapability(suite.ctx, cap2, "transfer"))
   143  
   144  	suite.Require().True(sk2.AuthenticateCapability(suite.ctx, cap2, "bond"))
   145  	suite.Require().False(sk2.AuthenticateCapability(suite.ctx, cap2, "invalid"))
   146  	suite.Require().False(sk2.AuthenticateCapability(suite.ctx, cap1, "bond"))
   147  
   148  	err = sk2.ReleaseCapability(suite.ctx, cap2)
   149  	suite.Require().NoError(err)
   150  	suite.Require().False(sk2.AuthenticateCapability(suite.ctx, cap2, "bond"))
   151  
   152  	badCap := types.NewCapability(100)
   153  	suite.Require().False(sk1.AuthenticateCapability(suite.ctx, badCap, "transfer"))
   154  	suite.Require().False(sk2.AuthenticateCapability(suite.ctx, badCap, "bond"))
   155  
   156  	suite.Require().False(sk1.AuthenticateCapability(suite.ctx, cap1, "  "))
   157  	suite.Require().False(sk1.AuthenticateCapability(suite.ctx, nil, "transfer"))
   158  }
   159  
   160  func (suite *KeeperTestSuite) TestClaimCapability() {
   161  	sk1 := suite.keeper.ScopeToModule(banktypes.ModuleName)
   162  	sk2 := suite.keeper.ScopeToModule(stakingtypes.ModuleName)
   163  	sk3 := suite.keeper.ScopeToModule("foo")
   164  
   165  	cap, err := sk1.NewCapability(suite.ctx, "transfer")
   166  	suite.Require().NoError(err)
   167  	suite.Require().NotNil(cap)
   168  
   169  	suite.Require().Error(sk1.ClaimCapability(suite.ctx, cap, "transfer"))
   170  	suite.Require().NoError(sk2.ClaimCapability(suite.ctx, cap, "transfer"))
   171  
   172  	got, ok := sk1.GetCapability(suite.ctx, "transfer")
   173  	suite.Require().True(ok)
   174  	suite.Require().Equal(cap, got)
   175  
   176  	got, ok = sk2.GetCapability(suite.ctx, "transfer")
   177  	suite.Require().True(ok)
   178  	suite.Require().Equal(cap, got)
   179  
   180  	suite.Require().Error(sk3.ClaimCapability(suite.ctx, cap, "  "))
   181  	suite.Require().Error(sk3.ClaimCapability(suite.ctx, nil, "transfer"))
   182  }
   183  
   184  func (suite *KeeperTestSuite) TestGetOwners() {
   185  	sk1 := suite.keeper.ScopeToModule(banktypes.ModuleName)
   186  	sk2 := suite.keeper.ScopeToModule(stakingtypes.ModuleName)
   187  	sk3 := suite.keeper.ScopeToModule("foo")
   188  
   189  	sks := []keeper.ScopedKeeper{sk1, sk2, sk3}
   190  
   191  	cap, err := sk1.NewCapability(suite.ctx, "transfer")
   192  	suite.Require().NoError(err)
   193  	suite.Require().NotNil(cap)
   194  
   195  	suite.Require().NoError(sk2.ClaimCapability(suite.ctx, cap, "transfer"))
   196  	suite.Require().NoError(sk3.ClaimCapability(suite.ctx, cap, "transfer"))
   197  
   198  	expectedOrder := []string{banktypes.ModuleName, "foo", stakingtypes.ModuleName}
   199  	// Ensure all scoped keepers can get owners
   200  	for _, sk := range sks {
   201  		owners, ok := sk.GetOwners(suite.ctx, "transfer")
   202  		mods, gotCap, err := sk.LookupModules(suite.ctx, "transfer")
   203  
   204  		suite.Require().True(ok, "could not retrieve owners")
   205  		suite.Require().NotNil(owners, "owners is nil")
   206  
   207  		suite.Require().NoError(err, "could not retrieve modules")
   208  		suite.Require().NotNil(gotCap, "capability is nil")
   209  		suite.Require().NotNil(mods, "modules is nil")
   210  		suite.Require().Equal(cap, gotCap, "caps not equal")
   211  
   212  		suite.Require().Equal(len(expectedOrder), len(owners.Owners), "length of owners is unexpected")
   213  		for i, o := range owners.Owners {
   214  			// Require owner is in expected position
   215  			suite.Require().Equal(expectedOrder[i], o.Module, "module is unexpected")
   216  			suite.Require().Equal(expectedOrder[i], mods[i], "module in lookup is unexpected")
   217  		}
   218  	}
   219  
   220  	// foo module releases capability
   221  	err = sk3.ReleaseCapability(suite.ctx, cap)
   222  	suite.Require().Nil(err, "could not release capability")
   223  
   224  	// new expected order and scoped capabilities
   225  	expectedOrder = []string{banktypes.ModuleName, stakingtypes.ModuleName}
   226  	sks = []keeper.ScopedKeeper{sk1, sk2}
   227  
   228  	// Ensure all scoped keepers can get owners
   229  	for _, sk := range sks {
   230  		owners, ok := sk.GetOwners(suite.ctx, "transfer")
   231  		mods, cap, err := sk.LookupModules(suite.ctx, "transfer")
   232  
   233  		suite.Require().True(ok, "could not retrieve owners")
   234  		suite.Require().NotNil(owners, "owners is nil")
   235  
   236  		suite.Require().NoError(err, "could not retrieve modules")
   237  		suite.Require().NotNil(cap, "capability is nil")
   238  		suite.Require().NotNil(mods, "modules is nil")
   239  
   240  		suite.Require().Equal(len(expectedOrder), len(owners.Owners), "length of owners is unexpected")
   241  		for i, o := range owners.Owners {
   242  			// Require owner is in expected position
   243  			suite.Require().Equal(expectedOrder[i], o.Module, "module is unexpected")
   244  			suite.Require().Equal(expectedOrder[i], mods[i], "module in lookup is unexpected")
   245  		}
   246  	}
   247  
   248  	_, ok := sk1.GetOwners(suite.ctx, "  ")
   249  	suite.Require().False(ok, "got owners from empty capability name")
   250  }
   251  
   252  func (suite *KeeperTestSuite) TestReleaseCapability() {
   253  	sk1 := suite.keeper.ScopeToModule(banktypes.ModuleName)
   254  	sk2 := suite.keeper.ScopeToModule(stakingtypes.ModuleName)
   255  
   256  	cap1, err := sk1.NewCapability(suite.ctx, "transfer")
   257  	suite.Require().NoError(err)
   258  	suite.Require().NotNil(cap1)
   259  
   260  	suite.Require().NoError(sk2.ClaimCapability(suite.ctx, cap1, "transfer"))
   261  
   262  	cap2, err := sk2.NewCapability(suite.ctx, "bond")
   263  	suite.Require().NoError(err)
   264  	suite.Require().NotNil(cap2)
   265  
   266  	suite.Require().Error(sk1.ReleaseCapability(suite.ctx, cap2))
   267  
   268  	suite.Require().NoError(sk2.ReleaseCapability(suite.ctx, cap1))
   269  	got, ok := sk2.GetCapability(suite.ctx, "transfer")
   270  	suite.Require().False(ok)
   271  	suite.Require().Nil(got)
   272  
   273  	suite.Require().NoError(sk1.ReleaseCapability(suite.ctx, cap1))
   274  	got, ok = sk1.GetCapability(suite.ctx, "transfer")
   275  	suite.Require().False(ok)
   276  	suite.Require().Nil(got)
   277  
   278  	suite.Require().Error(sk1.ReleaseCapability(suite.ctx, nil))
   279  }
   280  
   281  func (suite *KeeperTestSuite) TestRevertCapability() {
   282  	sk := suite.keeper.ScopeToModule(banktypes.ModuleName)
   283  
   284  	ms := suite.ctx.MultiStore()
   285  
   286  	msCache := ms.CacheMultiStore()
   287  	cacheCtx := suite.ctx.WithMultiStore(msCache)
   288  
   289  	capName := "revert"
   290  	// Create capability on cached context
   291  	cap, err := sk.NewCapability(cacheCtx, capName)
   292  	suite.Require().NoError(err, "could not create capability")
   293  
   294  	// Check that capability written in cached context
   295  	gotCache, ok := sk.GetCapability(cacheCtx, capName)
   296  	suite.Require().True(ok, "could not retrieve capability from cached context")
   297  	suite.Require().Equal(cap, gotCache, "did not get correct capability from cached context")
   298  
   299  	// Check that capability is NOT written to original context
   300  	got, ok := sk.GetCapability(suite.ctx, capName)
   301  	suite.Require().False(ok, "retrieved capability from original context before write")
   302  	suite.Require().Nil(got, "capability not nil in original store")
   303  
   304  	// Write to underlying memKVStore
   305  	msCache.Write()
   306  
   307  	got, ok = sk.GetCapability(suite.ctx, capName)
   308  	suite.Require().True(ok, "could not retrieve capability from context")
   309  	suite.Require().Equal(cap, got, "did not get correct capability from context")
   310  }
   311  
   312  func TestKeeperTestSuite(t *testing.T) {
   313  	suite.Run(t, new(KeeperTestSuite))
   314  }