summaryrefslogtreecommitdiff
path: root/subplotlib
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@digital-scurf.org>2020-12-19 12:08:14 +0000
committerDaniel Silverstone <dsilvers@digital-scurf.org>2020-12-21 08:39:33 +0000
commitc25d2a1991bf436bc17161325b677a39853529b4 (patch)
tree106de9bb4c9fca60564aa03bc82fc4fb5bd8eb9a /subplotlib
parent02575de1b29997dda61e7656700a4d61735a62da (diff)
downloadsubplot-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.toml2
-rw-r--r--subplotlib/src/step.rs22
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