Skip to content

Commit b8500ca

Browse files
committed
Create Envs, a factory for making mock Envs
1 parent 9e016c7 commit b8500ca

File tree

2 files changed

+170
-12
lines changed

2 files changed

+170
-12
lines changed

packages/std/src/testing/mock.rs

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

@@ -1295,6 +1388,71 @@ mod tests {
12951388
)
12961389
}
12971390

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

packages/std/src/testing/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub use mock::DistributionQuerier;
1919
pub use mock::StakingQuerier;
2020
pub use mock::{
2121
mock_dependencies, mock_dependencies_with_balance, mock_dependencies_with_balances, mock_env,
22-
mock_wasmd_attr, BankQuerier, MockApi, MockQuerier, MockQuerierCustomHandlerResult,
22+
mock_wasmd_attr, BankQuerier, Envs, MockApi, MockQuerier, MockQuerierCustomHandlerResult,
2323
MOCK_CONTRACT_ADDR,
2424
};
2525
#[cfg(feature = "ibc2")]

0 commit comments

Comments
 (0)