Skip to content

Commit

Permalink
Make sim_elapsed function safe to call outside of simulation (#170)
Browse files Browse the repository at this point in the history
If customer set custom timer for tracing subscriber that uses
sim_elapsed to log simulation time, this function might be called
before world or host set. E.g. with DEBUG level logging set
this function panics on internal log lines in turmoil crate
code before host is set.
  • Loading branch information
tereshch-aws authored Feb 20, 2024
1 parent ce025e2 commit cbaaaba
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 5 deletions.
14 changes: 10 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,17 @@ pub fn elapsed() -> Duration {

/// Returns how long the simulation has been executing for in virtual time.
///
/// Must be called from within a Turmoil simulation. Will return None if the
/// duration is not available, typically because there is no currently executing
/// host.
/// Will return None if the duration is not available, typically because
/// there is no currently executing host or world.
pub fn sim_elapsed() -> Option<Duration> {
World::try_current(|world| world.current_host().timer.sim_elapsed()).ok()
World::try_current(|world| {
world
.try_current_host()
.map(|host| host.timer.sim_elapsed())
.ok()
})
.ok()
.flatten()
}

/// Lookup an IP address by host name.
Expand Down
17 changes: 16 additions & 1 deletion src/sim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ mod test {
};

use crate::{
elapsed, hold,
elapsed, hold, World,
net::{TcpListener, TcpStream},
sim_elapsed, Builder, Result,
};
Expand Down Expand Up @@ -560,6 +560,21 @@ mod test {
Ok(())
}

/// This is a regression test to ensure it is safe to call sim_elapsed
/// if current world of host is not set.
#[test]
fn sim_elapsed_time() -> Result {
// Safe to call outside of simution while there
// is no current world set
assert!(sim_elapsed().is_none());

let sim = Builder::new().build();
// Safe to call while there is no current host set
World::enter(&sim.world, || assert!(sim_elapsed().is_none()));

Ok(())
}

#[test]
fn hold_release_peers() -> Result {
let global = Duration::from_millis(2);
Expand Down
5 changes: 5 additions & 0 deletions src/world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ impl World {
self.hosts.get(&addr).expect("host missing")
}

pub(crate) fn try_current_host(&self) -> TurmoilResult<&Host> {
let addr = self.current.ok_or("current host missing")?;
self.hosts.get(&addr).ok_or_else(|| "host missing".into())
}

pub(crate) fn lookup(&mut self, host: impl ToIpAddr) -> IpAddr {
self.dns.lookup(host)
}
Expand Down

0 comments on commit cbaaaba

Please sign in to comment.