github.com/Finschia/finschia-sdk@v0.48.1/types/context_test.go (about)

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