diff --git a/src/lib.rs b/src/lib.rs index 77f2955..2eaecd7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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 { - 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. diff --git a/src/sim.rs b/src/sim.rs index 1e4dd35..3178210 100644 --- a/src/sim.rs +++ b/src/sim.rs @@ -414,7 +414,7 @@ mod test { }; use crate::{ - elapsed, hold, + elapsed, hold, World, net::{TcpListener, TcpStream}, sim_elapsed, Builder, Result, }; @@ -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); diff --git a/src/world.rs b/src/world.rs index c23594c..2fd2698 100644 --- a/src/world.rs +++ b/src/world.rs @@ -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) }