diff options
author | Daniel Silverstone <dsilvers@digital-scurf.org> | 2022-04-01 20:34:25 +0100 |
---|---|---|
committer | Daniel Silverstone <dsilvers@digital-scurf.org> | 2022-04-01 20:34:25 +0100 |
commit | 4f2142453c7d25f581dfce761db9a4003355eeca (patch) | |
tree | 0136d2389b9ac645bbac496c0f3a9aba0a25f3b5 /subplotlib | |
parent | 1a3f06dc0604ba575ed932bf4c26545a948d0593 (diff) | |
download | subplot-4f2142453c7d25f581dfce761db9a4003355eeca.tar.gz |
(subplotlib): Make ScenarioContext implement Debug
Signed-off-by: Daniel Silverstone <dsilvers@digital-scurf.org>
Diffstat (limited to 'subplotlib')
-rw-r--r-- | subplotlib/src/scenario.rs | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/subplotlib/src/scenario.rs b/subplotlib/src/scenario.rs index 9f8e29b..0e25d8b 100644 --- a/subplotlib/src/scenario.rs +++ b/subplotlib/src/scenario.rs @@ -4,6 +4,7 @@ //! Instead instances of it are constructed in the generated test functions and //! will be run automatically. +use core::fmt; use std::fmt::Debug; use std::{cell::RefCell, marker::PhantomData, sync::Mutex}; @@ -123,6 +124,9 @@ trait ScenarioContextHookKind { /// Leave a step fn step_stops(&self, contexts: &ScenarioContext) -> StepResult; + + /// Produce your debug output + fn debug(&self, contexts: &ScenarioContext, dc: &mut DebuggedContext, alternate: bool); } impl<C> ScenarioContextHookKind for ScenarioContextHook<C> @@ -144,6 +148,10 @@ where fn step_stops(&self, contexts: &ScenarioContext) -> StepResult { contexts.with_mut(|c: &mut C| c.step_stops(), true) } + + fn debug(&self, contexts: &ScenarioContext, dc: &mut DebuggedContext, alternate: bool) { + contexts.with_generic(|c: &C| dc.add(c, alternate)); + } } /// A container for all scenario contexts @@ -155,6 +163,54 @@ pub struct ScenarioContext { hooks: RefCell<Vec<Box<dyn ScenarioContextHookKind>>>, } +#[derive(Default)] +struct DebuggedContext { + body: Vec<String>, +} + +impl DebuggedContext { + fn add<C>(&mut self, obj: &C, alternate: bool) + where + C: Debug, + { + let body = if alternate { + format!("{:#?}", obj) + } else { + format!("{:?}", obj) + }; + self.body.push(body); + } +} + +struct DebugContextString<'a>(&'a str); + +impl<'a> Debug for DebugContextString<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.0) + } +} + +impl Debug for DebuggedContext { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list() + .entries(self.body.iter().map(|s| DebugContextString(s))) + .finish() + } +} + +impl Debug for ScenarioContext { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut contexts = DebuggedContext::default(); + for hook in self.hooks.borrow().iter() { + hook.debug(self, &mut contexts, f.alternate()); + } + f.debug_struct("ScenarioContext") + .field("title", &self.title) + .field("contexts", &contexts) + .finish() + } +} + impl ScenarioContext { fn new(title: &str) -> Self { Self { @@ -187,6 +243,22 @@ impl ScenarioContext { } } + fn with_generic<C, F>(&self, func: F) + where + F: FnOnce(&C), + C: ContextElement, + { + let sci: &ScenarioContextItem<C> = self + .inner + .try_get() + .expect("Scenario Context item not initialised"); + let lock = match sci.0.lock() { + Ok(lock) => lock, + Err(pe) => pe.into_inner(), + }; + func(&lock) + } + /// With the extracted immutable context, run the function f. pub fn with<C, F, R>(&self, func: F, defuse_poison: bool) -> Result<R, StepError> where |