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 }