summaryrefslogtreecommitdiff
path: root/subplotlib/src/step.rs
diff options
context:
space:
mode:
Diffstat (limited to 'subplotlib/src/step.rs')
-rw-r--r--subplotlib/src/step.rs24
1 files changed, 16 insertions, 8 deletions
diff --git a/subplotlib/src/step.rs b/subplotlib/src/step.rs
index bbea249..76b9193 100644
--- a/subplotlib/src/step.rs
+++ b/subplotlib/src/step.rs
@@ -10,6 +10,8 @@ use std::panic::{catch_unwind, AssertUnwindSafe};
use crate::scenario::{Scenario, ScenarioContext};
use crate::types::StepResult;
+type StepFunc = dyn Fn(&ScenarioContext, bool) -> StepResult;
+
/// A ScenarioStep is one step in a scenario.
///
/// In essence, a scenario step is a named closure. Its name can be used when
@@ -23,12 +25,13 @@ use crate::types::StepResult;
/// # use subplotlib::prelude::*;
///
/// let step = ScenarioStep::new(
-/// "when everything works".to_string(), |ctx, ok| Ok(()), |scen| ()
+/// "when everything works".to_string(), |ctx, ok| Ok(()), |scen| (), "unknown"
/// );
/// ```
pub struct ScenarioStep {
step_text: String,
- func: Box<dyn Fn(&ScenarioContext, bool) -> StepResult>,
+ location: &'static str,
+ func: Box<StepFunc>,
reg: Box<dyn Fn(&Scenario)>,
}
@@ -38,13 +41,14 @@ impl ScenarioStep {
/// This is used to construct a scenario step from a function which
/// takes the scenario context container. This will generally be
/// called from the generated build method for the step.
- pub fn new<F, R>(step_text: String, func: F, reg: R) -> Self
+ pub fn new<F, R>(step_text: String, func: F, reg: R, location: &'static str) -> Self
where
F: Fn(&ScenarioContext, bool) -> StepResult + 'static,
R: Fn(&Scenario) + 'static,
{
Self {
step_text,
+ location,
func: Box::new(func),
reg: Box::new(reg),
}
@@ -53,13 +57,13 @@ 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 {
+ fn render_panic(location: &str, name: &str, err: Box<dyn Any + Send>) -> String {
if let Some(msg) = err.downcast_ref::<&str>() {
- format!("step {} panic'd: {}", name, msg)
+ format!("{location}: step {name} panic'd: {msg}")
} else if let Some(msg) = err.downcast_ref::<String>() {
- format!("step {} panic'd: {}", name, msg)
+ format!("{location}: step {name} panic'd: {msg}")
} else {
- format!("step {} panic'd", name)
+ format!("{location}: step {name} panic'd")
}
}
@@ -71,7 +75,7 @@ impl ScenarioStep {
// 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, defuse_poison));
- catch_unwind(func).map_err(|e| Self::render_panic(self.step_text(), e))?
+ catch_unwind(func).map_err(|e| Self::render_panic(self.location(), self.step_text(), e))?
}
/// Return the full text of this step
@@ -83,4 +87,8 @@ impl ScenarioStep {
pub(crate) fn register_contexts(&self, scenario: &Scenario) {
(*self.reg)(scenario);
}
+
+ pub(crate) fn location(&self) -> &'static str {
+ self.location
+ }
}