diff options
author | Daniel Silverstone <dsilvers@digital-scurf.org> | 2020-12-19 12:08:14 +0000 |
---|---|---|
committer | Daniel Silverstone <dsilvers@digital-scurf.org> | 2020-12-21 08:39:33 +0000 |
commit | c25d2a1991bf436bc17161325b677a39853529b4 (patch) | |
tree | 106de9bb4c9fca60564aa03bc82fc4fb5bd8eb9a /subplotlib | |
parent | 02575de1b29997dda61e7656700a4d61735a62da (diff) | |
download | subplot-c25d2a1991bf436bc17161325b677a39853529b4.tar.gz |
subplotlib: Enable catching of panics
Signed-off-by: Daniel Silverstone <dsilvers@digital-scurf.org>
Diffstat (limited to 'subplotlib')
-rw-r--r-- | subplotlib/Cargo.toml | 2 | ||||
-rw-r--r-- | subplotlib/src/step.rs | 22 |
2 files changed, 22 insertions, 2 deletions
diff --git a/subplotlib/Cargo.toml b/subplotlib/Cargo.toml index 5ca2616..2e6c306 100644 --- a/subplotlib/Cargo.toml +++ b/subplotlib/Cargo.toml @@ -10,4 +10,4 @@ fehler = "1" subplotlib-derive = { version="0.1", path = "../subplotlib-derive" } lazy_static = "1" base64 = "0.13" -state = "0.4"
\ No newline at end of file +state = "0.4" diff --git a/subplotlib/src/step.rs b/subplotlib/src/step.rs index 3eb6a0c..f83b29d 100644 --- a/subplotlib/src/step.rs +++ b/subplotlib/src/step.rs @@ -4,6 +4,9 @@ //! here to provide wrappers to make the scenarios easier to work with. //! +use std::any::Any; +use std::panic::{catch_unwind, AssertUnwindSafe}; + use crate::scenario::ScenarioContext; use crate::types::StepResult; @@ -32,11 +35,28 @@ impl ScenarioStep { } } + /// Attempt to render a message. + /// If something panics with a type other than a static string or + /// a formatted string then we won't be able to render it sadly. + fn render_panic(name: &str, err: Box<dyn Any + Send>) -> String { + if let Some(msg) = err.downcast_ref::<&str>() { + format!("step {} panic'd: {}", name, msg) + } else if let Some(msg) = err.downcast_ref::<String>() { + format!("step {} panic'd: {}", name, msg) + } else { + format!("step {} panic'd", name) + } + } + /// Call the step function /// /// This simply calls the encased step function pub fn call(&self, context: &ScenarioContext) -> StepResult { - (*self.func)(context) + // Note, panic here will be absorbed and so there's a risk that + // subsequent step calls may not be sound. There's not a lot we can + // do to ensure things are good except try. + let func = AssertUnwindSafe(|| (*self.func)(context)); + catch_unwind(func).map_err(|e| Self::render_panic(self.name(), e))? } /// Return the name of this step |