summaryrefslogtreecommitdiff
path: root/subplotlib
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@digital-scurf.org>2022-04-01 20:34:25 +0100
committerDaniel Silverstone <dsilvers@digital-scurf.org>2022-04-01 20:34:25 +0100
commit4f2142453c7d25f581dfce761db9a4003355eeca (patch)
tree0136d2389b9ac645bbac496c0f3a9aba0a25f3b5 /subplotlib
parent1a3f06dc0604ba575ed932bf4c26545a948d0593 (diff)
downloadsubplot-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.rs72
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