github.com/cosmos/cosmos-sdk@v0.50.10/types/context_test.go (about)

     1  package types_test
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  	"time"
     7  
     8  	abci "github.com/cometbft/cometbft/abci/types"
     9  	cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
    10  	cmttime "github.com/cometbft/cometbft/types/time"
    11  	"github.com/golang/mock/gomock"
    12  	"github.com/stretchr/testify/suite"
    13  
    14  	storetypes "cosmossdk.io/store/types"
    15  
    16  	"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
    17  	"github.com/cosmos/cosmos-sdk/testutil"
    18  	"github.com/cosmos/cosmos-sdk/testutil/mock"
    19  	"github.com/cosmos/cosmos-sdk/types"
    20  )
    21  
    22  type contextTestSuite struct {
    23  	suite.Suite
    24  }
    25  
    26  func TestContextTestSuite(t *testing.T) {
    27  	suite.Run(t, new(contextTestSuite))
    28  }
    29  
    30  func (s *contextTestSuite) TestCacheContext() {
    31  	key := storetypes.NewKVStoreKey(s.T().Name() + "_TestCacheContext")
    32  	k1 := []byte("hello")
    33  	v1 := []byte("world")
    34  	k2 := []byte("key")
    35  	v2 := []byte("value")
    36  
    37  	ctx := testutil.DefaultContext(key, storetypes.NewTransientStoreKey("transient_"+s.T().Name()))
    38  	store := ctx.KVStore(key)
    39  	store.Set(k1, v1)
    40  	s.Require().Equal(v1, store.Get(k1))
    41  	s.Require().Nil(store.Get(k2))
    42  
    43  	cctx, write := ctx.CacheContext()
    44  	cstore := cctx.KVStore(key)
    45  	s.Require().Equal(v1, cstore.Get(k1))
    46  	s.Require().Nil(cstore.Get(k2))
    47  
    48  	// emit some events
    49  	cctx.EventManager().EmitEvent(types.NewEvent("foo", types.NewAttribute("key", "value")))
    50  	cctx.EventManager().EmitEvent(types.NewEvent("bar", types.NewAttribute("key", "value")))
    51  
    52  	cstore.Set(k2, v2)
    53  	s.Require().Equal(v2, cstore.Get(k2))
    54  	s.Require().Nil(store.Get(k2))
    55  
    56  	write()
    57  
    58  	s.Require().Equal(v2, store.Get(k2))
    59  	s.Require().Len(ctx.EventManager().Events(), 2)
    60  }
    61  
    62  func (s *contextTestSuite) TestLogContext() {
    63  	key := storetypes.NewKVStoreKey(s.T().Name())
    64  	ctx := testutil.DefaultContext(key, storetypes.NewTransientStoreKey("transient_"+s.T().Name()))
    65  	ctrl := gomock.NewController(s.T())
    66  	s.T().Cleanup(ctrl.Finish)
    67  
    68  	logger := mock.NewMockLogger(ctrl)
    69  	logger.EXPECT().Debug("debug")
    70  	logger.EXPECT().Info("info")
    71  	logger.EXPECT().Error("error")
    72  
    73  	ctx = ctx.WithLogger(logger)
    74  	ctx.Logger().Debug("debug")
    75  	ctx.Logger().Info("info")
    76  	ctx.Logger().Error("error")
    77  }
    78  
    79  // Testing saving/loading sdk type values to/from the context
    80  func (s *contextTestSuite) TestContextWithCustom() {
    81  	var ctx types.Context
    82  	s.Require().True(ctx.IsZero())
    83  
    84  	ctrl := gomock.NewController(s.T())
    85  	s.T().Cleanup(ctrl.Finish)
    86  
    87  	header := cmtproto.Header{}
    88  	height := int64(1)
    89  	chainid := "chainid"
    90  	ischeck := true
    91  	txbytes := []byte("txbytes")
    92  	logger := mock.NewMockLogger(ctrl)
    93  	voteinfos := []abci.VoteInfo{{}}
    94  	meter := storetypes.NewGasMeter(10000)
    95  	blockGasMeter := storetypes.NewGasMeter(20000)
    96  	minGasPrices := types.DecCoins{types.NewInt64DecCoin("feetoken", 1)}
    97  	headerHash := []byte("headerHash")
    98  	zeroGasCfg := storetypes.GasConfig{}
    99  
   100  	ctx = types.NewContext(nil, header, ischeck, logger)
   101  	s.Require().Equal(header, ctx.BlockHeader())
   102  
   103  	ctx = ctx.
   104  		WithBlockHeight(height).
   105  		WithChainID(chainid).
   106  		WithTxBytes(txbytes).
   107  		WithVoteInfos(voteinfos).
   108  		WithGasMeter(meter).
   109  		WithMinGasPrices(minGasPrices).
   110  		WithBlockGasMeter(blockGasMeter).
   111  		WithHeaderHash(headerHash).
   112  		WithKVGasConfig(zeroGasCfg).
   113  		WithTransientKVGasConfig(zeroGasCfg)
   114  
   115  	s.Require().Equal(height, ctx.BlockHeight())
   116  	s.Require().Equal(chainid, ctx.ChainID())
   117  	s.Require().Equal(ischeck, ctx.IsCheckTx())
   118  	s.Require().Equal(txbytes, ctx.TxBytes())
   119  	s.Require().Equal(logger, ctx.Logger())
   120  	s.Require().Equal(voteinfos, ctx.VoteInfos())
   121  	s.Require().Equal(meter, ctx.GasMeter())
   122  	s.Require().Equal(minGasPrices, ctx.MinGasPrices())
   123  	s.Require().Equal(blockGasMeter, ctx.BlockGasMeter())
   124  	s.Require().Equal(headerHash, ctx.HeaderHash())
   125  	s.Require().False(ctx.WithIsCheckTx(false).IsCheckTx())
   126  	s.Require().Equal(zeroGasCfg, ctx.KVGasConfig())
   127  	s.Require().Equal(zeroGasCfg, ctx.TransientKVGasConfig())
   128  
   129  	// test IsReCheckTx
   130  	s.Require().False(ctx.IsReCheckTx())
   131  	ctx = ctx.WithIsCheckTx(false)
   132  	ctx = ctx.WithIsReCheckTx(true)
   133  	s.Require().True(ctx.IsCheckTx())
   134  	s.Require().True(ctx.IsReCheckTx())
   135  
   136  	// test consensus param
   137  	s.Require().Equal(cmtproto.ConsensusParams{}, ctx.ConsensusParams())
   138  	cp := cmtproto.ConsensusParams{}
   139  	s.Require().Equal(cp, ctx.WithConsensusParams(cp).ConsensusParams())
   140  
   141  	// test inner context
   142  	newContext := context.WithValue(ctx.Context(), struct{}{}, "value")
   143  	s.Require().NotEqual(ctx.Context(), ctx.WithContext(newContext).Context())
   144  }
   145  
   146  // Testing saving/loading of header fields to/from the context
   147  func (s *contextTestSuite) TestContextHeader() {
   148  	var ctx types.Context
   149  
   150  	height := int64(5)
   151  	time := time.Now()
   152  	addr := secp256k1.GenPrivKey().PubKey().Address()
   153  	proposer := types.ConsAddress(addr)
   154  
   155  	ctx = types.NewContext(nil, cmtproto.Header{}, false, nil)
   156  
   157  	ctx = ctx.
   158  		WithBlockHeight(height).
   159  		WithBlockTime(time).
   160  		WithProposer(proposer)
   161  	s.Require().Equal(height, ctx.BlockHeight())
   162  	s.Require().Equal(height, ctx.BlockHeader().Height)
   163  	s.Require().Equal(time.UTC(), ctx.BlockHeader().Time)
   164  	s.Require().Equal(proposer.Bytes(), ctx.BlockHeader().ProposerAddress)
   165  }
   166  
   167  func (s *contextTestSuite) TestWithBlockTime() {
   168  	now := time.Now()
   169  	ctx := types.NewContext(nil, cmtproto.Header{}, false, nil)
   170  	ctx = ctx.WithBlockTime(now)
   171  	cmttime2 := cmttime.Canonical(now)
   172  	s.Require().Equal(ctx.BlockTime(), cmttime2)
   173  }
   174  
   175  func (s *contextTestSuite) TestContextHeaderClone() {
   176  	cases := map[string]struct {
   177  		h cmtproto.Header
   178  	}{
   179  		"empty": {
   180  			h: cmtproto.Header{},
   181  		},
   182  		"height": {
   183  			h: cmtproto.Header{
   184  				Height: 77,
   185  			},
   186  		},
   187  		"time": {
   188  			h: cmtproto.Header{
   189  				Time: time.Unix(12345677, 12345),
   190  			},
   191  		},
   192  		"zero time": {
   193  			h: cmtproto.Header{
   194  				Time: time.Unix(0, 0),
   195  			},
   196  		},
   197  		"many items": {
   198  			h: cmtproto.Header{
   199  				Height:  823,
   200  				Time:    time.Unix(9999999999, 0),
   201  				ChainID: "silly-demo",
   202  			},
   203  		},
   204  		"many items with hash": {
   205  			h: cmtproto.Header{
   206  				Height:        823,
   207  				Time:          time.Unix(9999999999, 0),
   208  				ChainID:       "silly-demo",
   209  				AppHash:       []byte{5, 34, 11, 3, 23},
   210  				ConsensusHash: []byte{11, 3, 23, 87, 3, 1},
   211  			},
   212  		},
   213  	}
   214  
   215  	for name, tc := range cases {
   216  		tc := tc
   217  		s.T().Run(name, func(t *testing.T) {
   218  			ctx := types.NewContext(nil, tc.h, false, nil)
   219  			s.Require().Equal(tc.h.Height, ctx.BlockHeight())
   220  			s.Require().Equal(tc.h.Time.UTC(), ctx.BlockTime())
   221  
   222  			// update only changes one field
   223  			var newHeight int64 = 17
   224  			ctx = ctx.WithBlockHeight(newHeight)
   225  			s.Require().Equal(newHeight, ctx.BlockHeight())
   226  			s.Require().Equal(tc.h.Time.UTC(), ctx.BlockTime())
   227  		})
   228  	}
   229  }
   230  
   231  func (s *contextTestSuite) TestUnwrapSDKContext() {
   232  	sdkCtx := types.NewContext(nil, cmtproto.Header{}, false, nil)
   233  	ctx := types.WrapSDKContext(sdkCtx)
   234  	sdkCtx2 := types.UnwrapSDKContext(ctx)
   235  	s.Require().Equal(sdkCtx, sdkCtx2)
   236  
   237  	ctx = context.Background()
   238  	s.Require().Panics(func() { types.UnwrapSDKContext(ctx) })
   239  
   240  	// test unwrapping when we've used context.WithValue
   241  	ctx = context.WithValue(sdkCtx, struct{}{}, "bar")
   242  	sdkCtx2 = types.UnwrapSDKContext(ctx)
   243  	s.Require().Equal(sdkCtx, sdkCtx2)
   244  }