Skip to content

Commit 7636045

Browse files
committed
Create Envs, a factory for making mock Envs
1 parent 6f25116 commit 7636045

File tree

2 files changed

+170
-12
lines changed

2 files changed

+170
-12
lines changed

packages/std/src/testing/mock.rs

+169-11
Original file line numberDiff line numberDiff line change
@@ -392,17 +392,110 @@ fn validate_length(bytes: &[u8]) -> StdResult<()> {
392392
/// // `env3` is one block and 5.5 seconds later
393393
/// ```
394394
pub fn mock_env() -> Env {
395-
let contract_addr = MockApi::default().addr_make("cosmos2contract");
396-
Env {
397-
block: BlockInfo {
398-
height: 12_345,
399-
time: Timestamp::from_nanos(1_571_797_419_879_305_533),
400-
chain_id: "cosmos-testnet-14002".to_string(),
401-
},
402-
transaction: Some(TransactionInfo { index: 3 }),
403-
contract: ContractInfo {
404-
address: contract_addr,
405-
},
395+
let mut envs = Envs::new(BECH32_PREFIX);
396+
envs.make()
397+
}
398+
399+
/// A factory type that stores chain information such as bech32 prefix and can make mock `Env`s from there.
400+
///
401+
/// It increments height for each mock call and block time by 5 seconds but is otherwise dumb.
402+
///
403+
/// In contrast to using `mock_env`, the bech32 prefix must always be specified.
404+
///
405+
/// ## Examples
406+
///
407+
/// Typical usage
408+
///
409+
/// ```
410+
/// # use cosmwasm_std::Timestamp;
411+
/// use cosmwasm_std::testing::Envs;
412+
///
413+
/// let mut envs = Envs::new("food");
414+
///
415+
/// let env = envs.make();
416+
/// assert_eq!(env.contract.address.as_str(), "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj");
417+
/// assert_eq!(env.block.height, 12_345);
418+
/// assert_eq!(env.block.time, Timestamp::from_nanos(1_571_797_419_879_305_533));
419+
///
420+
/// let env = envs.make();
421+
/// assert_eq!(env.contract.address.as_str(), "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj");
422+
/// assert_eq!(env.block.height, 12_346);
423+
/// assert_eq!(env.block.time, Timestamp::from_nanos(1_571_797_424_879_305_533));
424+
///
425+
/// let env = envs.make();
426+
/// assert_eq!(env.contract.address.as_str(), "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj");
427+
/// assert_eq!(env.block.height, 12_347);
428+
/// assert_eq!(env.block.time, Timestamp::from_nanos(1_571_797_429_879_305_533));
429+
/// ```
430+
///
431+
/// Or use with iterator
432+
///
433+
/// ```
434+
/// # use cosmwasm_std::Timestamp;
435+
/// use cosmwasm_std::testing::Envs;
436+
///
437+
/// let mut envs = Envs::new("food");
438+
///
439+
/// for (index, env) in envs.take(100).enumerate() {
440+
/// assert_eq!(env.contract.address.as_str(), "food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj");
441+
/// assert_eq!(env.block.height, 12_345 + index as u64);
442+
/// assert_eq!(env.block.time, Timestamp::from_nanos(1_571_797_419_879_305_533).plus_seconds((index*5) as u64));
443+
/// }
444+
/// ```
445+
pub struct Envs {
446+
contract_address: Addr,
447+
last_height: u64,
448+
last_time: Timestamp,
449+
envs_produced: u64,
450+
}
451+
452+
impl Envs {
453+
pub fn new(
454+
bech32_prefix: &'static str, /* static due to MockApi's Copy requirement. No better idea for now. */
455+
) -> Self {
456+
let api = MockApi::default().with_prefix(bech32_prefix);
457+
Envs {
458+
// Default values here for compatibility with old `mock_env` function. They could be changed to anything else if there is a good reason.
459+
contract_address: api.addr_make("cosmos2contract"),
460+
last_height: 12_344,
461+
last_time: Timestamp::from_nanos(1_571_797_419_879_305_533).minus_seconds(5),
462+
envs_produced: 0,
463+
}
464+
}
465+
466+
pub fn make(&mut self) -> Env {
467+
let height = self.last_height + 1;
468+
let time = self.last_time.plus_seconds(5);
469+
470+
self.last_height = height;
471+
self.last_time = time;
472+
self.envs_produced += 1;
473+
474+
Env {
475+
block: BlockInfo {
476+
height,
477+
time,
478+
chain_id: "cosmos-testnet-14002".to_string(),
479+
},
480+
transaction: Some(TransactionInfo { index: 3 }),
481+
contract: ContractInfo {
482+
address: self.contract_address.clone(),
483+
},
484+
}
485+
}
486+
}
487+
488+
// The iterator implementation can produce 1 million envs and then stops for no good reason.
489+
impl Iterator for Envs {
490+
type Item = Env;
491+
492+
fn next(&mut self) -> Option<Self::Item> {
493+
if self.envs_produced < 1_000_000 {
494+
let item = self.make();
495+
Some(item)
496+
} else {
497+
None
498+
}
406499
}
407500
}
408501

@@ -1285,6 +1378,71 @@ mod tests {
12851378
)
12861379
}
12871380

1381+
#[test]
1382+
fn envs_works() {
1383+
let mut envs = Envs::new("food");
1384+
1385+
let env = envs.make();
1386+
assert_eq!(
1387+
env.contract.address.as_str(),
1388+
"food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1389+
);
1390+
assert_eq!(env.block.height, 12_345);
1391+
assert_eq!(
1392+
env.block.time,
1393+
Timestamp::from_nanos(1_571_797_419_879_305_533)
1394+
);
1395+
1396+
let env = envs.make();
1397+
assert_eq!(
1398+
env.contract.address.as_str(),
1399+
"food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1400+
);
1401+
assert_eq!(env.block.height, 12_346);
1402+
assert_eq!(
1403+
env.block.time,
1404+
Timestamp::from_nanos(1_571_797_424_879_305_533)
1405+
);
1406+
1407+
let env = envs.make();
1408+
assert_eq!(
1409+
env.contract.address.as_str(),
1410+
"food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1411+
);
1412+
assert_eq!(env.block.height, 12_347);
1413+
assert_eq!(
1414+
env.block.time,
1415+
Timestamp::from_nanos(1_571_797_429_879_305_533)
1416+
);
1417+
}
1418+
1419+
#[test]
1420+
fn envs_implements_iteratorworks() {
1421+
let envs = Envs::new("food");
1422+
1423+
let result: Vec<_> = envs.into_iter().take(5).collect();
1424+
1425+
assert_eq!(
1426+
result[0].contract.address.as_str(),
1427+
"food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1428+
);
1429+
assert_eq!(result[0].block.height, 12_345);
1430+
assert_eq!(
1431+
result[0].block.time,
1432+
Timestamp::from_nanos(1_571_797_419_879_305_533)
1433+
);
1434+
1435+
assert_eq!(
1436+
result[4].contract.address.as_str(),
1437+
"food1jpev2csrppg792t22rn8z8uew8h3sjcpglcd0qv9g8gj8ky922ts74yrjj"
1438+
);
1439+
assert_eq!(result[4].block.height, 12_349);
1440+
assert_eq!(
1441+
result[4].block.time,
1442+
Timestamp::from_nanos(1_571_797_439_879_305_533)
1443+
);
1444+
}
1445+
12881446
#[test]
12891447
fn addr_validate_works() {
12901448
// default prefix is 'cosmwasm'

packages/std/src/testing/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub use mock::DistributionQuerier;
2121
pub use mock::StakingQuerier;
2222
pub use mock::{
2323
mock_dependencies, mock_dependencies_with_balance, mock_dependencies_with_balances, mock_env,
24-
mock_wasmd_attr, BankQuerier, MockApi, MockQuerier, MockQuerierCustomHandlerResult,
24+
mock_wasmd_attr, BankQuerier, Envs, MockApi, MockQuerier, MockQuerierCustomHandlerResult,
2525
MOCK_CONTRACT_ADDR,
2626
};
2727
#[cfg(feature = "stargate")]

0 commit comments

Comments
 (0)