From 6741b6a4479c27ab428bf2c3dd5d0af0963dd899 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sat, 12 Aug 2023 11:35:22 +0100 Subject: subplotlib: Add storage of location into scenario/scenariostep Signed-off-by: Daniel Silverstone --- subplotlib/src/scenario.rs | 20 +++++++++++++------- subplotlib/src/step.rs | 20 +++++++++++++------- 2 files changed, 26 insertions(+), 14 deletions(-) (limited to 'subplotlib') diff --git a/subplotlib/src/scenario.rs b/subplotlib/src/scenario.rs index a83e215..9bcc43d 100644 --- a/subplotlib/src/scenario.rs +++ b/subplotlib/src/scenario.rs @@ -159,6 +159,7 @@ where /// This container allows the running of code within a given scenario context. pub struct ScenarioContext { title: String, + location: &'static str, inner: Container![], hooks: RefCell>>, } @@ -212,9 +213,10 @@ impl Debug for ScenarioContext { } impl ScenarioContext { - fn new(title: &str) -> Self { + fn new(title: &str, location: &'static str) -> Self { Self { title: title.to_string(), + location, inner: ::new(), hooks: RefCell::new(Vec::new()), } @@ -303,12 +305,12 @@ impl ScenarioContext { /// ``` /// # use subplotlib::prelude::*; /// -/// let mut scenario = Scenario::new("example scenario"); +/// let mut scenario = Scenario::new("example scenario", "unknown"); /// /// let run_step = subplotlib::steplibrary::runcmd::run::Builder::default() /// .argv0("true") /// .args("") -/// .build("when I run true".to_string()); +/// .build("when I run true".to_string(), "unknown"); /// scenario.add_step(run_step, None); /// /// ``` @@ -319,9 +321,9 @@ pub struct Scenario { impl Scenario { /// Create a new scenario with the given title - pub fn new(title: &str) -> Self { + pub fn new(title: &str, location: &'static str) -> Self { Self { - contexts: ScenarioContext::new(title), + contexts: ScenarioContext::new(title, location), steps: Vec::new(), } } @@ -372,7 +374,11 @@ impl Scenario { // Firstly, we start all the contexts let mut ret = Ok(()); let mut highest_start = None; - println!("scenario: {}", self.contexts.title()); + println!( + "{}: scenario: {}", + self.contexts.location, + self.contexts.title() + ); for (i, hook) in self.contexts.hooks.borrow().iter().enumerate() { let res = hook.scenario_starts(&self.contexts); if res.is_err() { @@ -387,7 +393,7 @@ impl Scenario { if ret.is_ok() { let mut highest = None; for (i, step) in self.steps.iter().map(|(step, _)| step).enumerate() { - println!(" step: {}", step.step_text()); + println!("{}: step: {}", step.location(), step.step_text()); let mut highest_prep = None; for (i, prep) in self.contexts.hooks.borrow().iter().enumerate() { let res = prep.step_starts(&self.contexts, step.step_text()); diff --git a/subplotlib/src/step.rs b/subplotlib/src/step.rs index 12b4ddf..76b9193 100644 --- a/subplotlib/src/step.rs +++ b/subplotlib/src/step.rs @@ -25,11 +25,12 @@ type StepFunc = dyn Fn(&ScenarioContext, bool) -> 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, + location: &'static str, func: Box, reg: Box, } @@ -40,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(step_text: String, func: F, reg: R) -> Self + pub fn new(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), } @@ -55,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) -> String { + fn render_panic(location: &str, name: &str, err: Box) -> String { if let Some(msg) = err.downcast_ref::<&str>() { - format!("step {name} panic'd: {msg}") + format!("{location}: step {name} panic'd: {msg}") } else if let Some(msg) = err.downcast_ref::() { - format!("step {name} panic'd: {msg}") + format!("{location}: step {name} panic'd: {msg}") } else { - format!("step {name} panic'd") + format!("{location}: step {name} panic'd") } } @@ -73,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 @@ -85,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 + } } -- cgit v1.2.1