use std::cell::RefCell;
use std::rc::Rc;
use simu::SimEnv;
type Log = Rc<RefCell<Vec<String>>>;
fn new_log() -> Log { Rc::new(RefCell::new(Vec::new())) }
#[test]
fn basic_fire_and_wake() {
let mut env = SimEnv::with_seed(0);
let (trigger, awaitable) = env.event();
let log = new_log();
{
let h = env.handle();
let log2 = log.clone();
env.spawn(async move {
awaitable.await;
log2.borrow_mut().push(format!("B:{}", h.now()));
});
}
{
let h = env.handle();
let log2 = log.clone();
env.spawn(async move {
h.timeout(5.0).await;
trigger.fire();
log2.borrow_mut().push(format!("A:{}", h.now()));
});
}
env.run();
assert_eq!(*log.borrow(), vec!["A:5", "B:5"]);
assert_eq!(env.now(), 5.0);
}
#[test]
fn fire_before_await_resolves_immediately() {
let mut env = SimEnv::with_seed(0);
let (trigger, awaitable) = env.event();
let log = new_log();
{
let h = env.handle();
env.spawn(async move {
h.timeout(2.0).await;
trigger.fire();
});
}
{
let h = env.handle();
let log2 = log.clone();
env.spawn(async move {
h.timeout(3.0).await;
awaitable.await; log2.borrow_mut().push(format!("B:{}", h.now()));
});
}
env.run();
assert_eq!(*log.borrow(), vec!["B:3"]);
}
#[test]
fn multi_waiter_all_wake() {
let mut env = SimEnv::with_seed(0);
let (trigger, awaitable) = env.event();
let log = new_log();
for label in ["W1", "W2", "W3"] {
let log2 = log.clone();
let h = env.handle();
let aw = awaitable.clone();
let label = label.to_string();
env.spawn(async move {
aw.await;
log2.borrow_mut().push(format!("{}:{}", label, h.now()));
});
}
{
let h = env.handle();
env.spawn(async move {
h.timeout(7.0).await;
trigger.fire();
});
}
env.run();
assert_eq!(env.now(), 7.0);
let entries = log.borrow();
assert_eq!(entries.len(), 3);
assert!(entries.contains(&"W1:7".to_string()));
assert!(entries.contains(&"W2:7".to_string()));
assert!(entries.contains(&"W3:7".to_string()));
}
#[test]
fn clone_shares_underlying_event() {
let mut env = SimEnv::with_seed(0);
let (trigger, awaitable) = env.event();
let awaitable2 = awaitable.clone();
let log = new_log();
for (aw, label) in [(awaitable, "orig"), (awaitable2, "clone")] {
let h = env.handle();
let log2 = log.clone();
let label = label.to_string();
env.spawn(async move {
aw.await;
log2.borrow_mut().push(format!("{}:{}", label, h.now()));
});
}
{
let h = env.handle();
env.spawn(async move {
h.timeout(3.0).await;
trigger.fire();
});
}
env.run();
let entries = log.borrow();
assert_eq!(entries.len(), 2);
assert!(entries.contains(&"orig:3".to_string()));
assert!(entries.contains(&"clone:3".to_string()));
}
#[test]
fn envhandle_event_method() {
let mut env = SimEnv::with_seed(0);
let h = env.handle();
let (trigger, awaitable) = h.event(); let log = new_log();
{
let h = env.handle();
let log2 = log.clone();
env.spawn(async move {
awaitable.await;
log2.borrow_mut().push(format!("woken:{}", h.now()));
});
}
{
let h = env.handle();
env.spawn(async move {
h.timeout(4.0).await;
trigger.fire();
});
}
env.run();
assert_eq!(*log.borrow(), vec!["woken:4"]);
}
#[test]
fn dropped_unfired_trigger_strands_waiter() {
let mut env = SimEnv::with_seed(0);
let log = new_log();
let l2 = log.clone();
let (trigger, awaitable) = env.event();
env.spawn(async move {
awaitable.await;
l2.borrow_mut().push("resolved".to_string());
});
drop(trigger);
env.run();
assert!(log.borrow().is_empty(), "waiter unexpectedly resolved: {:?}", log.borrow());
}