diff options
author | Daniel Silverstone <dsilvers@digital-scurf.org> | 2020-12-05 11:13:43 +0000 |
---|---|---|
committer | Daniel Silverstone <dsilvers@digital-scurf.org> | 2020-12-21 08:39:32 +0000 |
commit | 515096221b94857725e445a9669d3b2f239a9453 (patch) | |
tree | 2927056b99ad5300911f90844845ffeb44493d95 /subplotlib | |
parent | 91b29f9bd7e34434824789d33014c916e7e13243 (diff) | |
download | subplot-515096221b94857725e445a9669d3b2f239a9453.tar.gz |
subplotlib: Add a bunch of documentation
Signed-off-by: Daniel Silverstone <dsilvers@digital-scurf.org>
Diffstat (limited to 'subplotlib')
-rw-r--r-- | subplotlib/src/args.rs | 1 | ||||
-rw-r--r-- | subplotlib/src/file.rs | 45 | ||||
-rw-r--r-- | subplotlib/src/lib.rs | 8 | ||||
-rw-r--r-- | subplotlib/src/prelude.rs | 10 | ||||
-rw-r--r-- | subplotlib/src/scenario.rs | 30 | ||||
-rw-r--r-- | subplotlib/src/step.rs | 32 | ||||
-rw-r--r-- | subplotlib/src/types.rs | 13 | ||||
-rw-r--r-- | subplotlib/src/utils.rs | 8 |
8 files changed, 136 insertions, 11 deletions
diff --git a/subplotlib/src/args.rs b/subplotlib/src/args.rs deleted file mode 100644 index 8b13789..0000000 --- a/subplotlib/src/args.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/subplotlib/src/file.rs b/subplotlib/src/file.rs index 1be93df..e44c0ef 100644 --- a/subplotlib/src/file.rs +++ b/subplotlib/src/file.rs @@ -1,10 +1,39 @@ //! Subplot data files -// +//! +//! Subplot can embed data files into test suites. This module provides +//! the representation of the files in a way designed to be cheap to clone +//! so that they can be passed around "by value". use std::path::{Path, PathBuf}; use std::sync::Arc; use base64::decode; +/// An embedded data file. +/// +/// Embedded data files have names and content. The subplot template will generate +/// a `lazy_static` containing all the data files embedded into the suite. Then +/// generated test functions will extract data files +/// +/// If you are using them in your test steps you should take them by value: +/// +/// ```rust +/// # use subplotlib::prelude::*; +/// # struct Context {} +/// #[step] +/// fn step_using_a_file(context: &mut Context, somefile: SubplotDataFile) { +/// // context.stash_file(somefile); +/// } +/// ``` +/// +/// For the generated test to correctly recognise how to pass a file in, you +/// **must** mark the argument as a file in your binding: +/// +/// ```yaml +/// - when: using {somefile} as a input +/// function: step_using_a_file +/// types: +/// somefile: file +/// ``` #[derive(Debug)] pub struct SubplotDataFile { name: Arc<Path>, @@ -30,6 +59,18 @@ impl Default for SubplotDataFile { } impl SubplotDataFile { + /// Construct a new data file object + /// + /// Typically this will only be called from the generated test suite. + /// The passed in name and data must be base64 encoded strings and each will + /// be interpreted independently. The name will be treated as a [`PathBuf`] + /// and the data will be stored as a slice of bytes. + /// + /// Neither will be interpreted as utf8. + /// + /// # Panics + /// + /// This will panic if the passed in strings are not correctly base64 encoded. pub fn new(name: &str, data: &str) -> Self { let name = decode(name).expect("Subplot generated bad base64?"); let name = String::from_utf8_lossy(&name); @@ -39,10 +80,12 @@ impl SubplotDataFile { Self { name, data } } + /// Retrieve the filename pub fn name(&self) -> &Path { &self.name } + /// Retrieve the data pub fn data(&self) -> &[u8] { &self.data } diff --git a/subplotlib/src/lib.rs b/subplotlib/src/lib.rs index 9ebae0f..8c31672 100644 --- a/subplotlib/src/lib.rs +++ b/subplotlib/src/lib.rs @@ -1,6 +1,14 @@ //! Subplot test utilities //! +//! This crate is meant to be used by test suites generated using the [Subplot][] +//! code generator using the `rust` template. You should generally not use this +//! crate directly, instead test suites generated using the `rust` template will +//! `use subplotlib::prelude::*;` automatically. //! +//! If you want to explore things, then we suggest you start from the [`prelude`][mod@prelude] +//! module since it exposes everything you'd normally find in a test suite. +//! +//! [Subplot]: https://subplot.liw.fi/ pub mod file; pub mod prelude; diff --git a/subplotlib/src/prelude.rs b/subplotlib/src/prelude.rs index 1368d1e..d093e0f 100644 --- a/subplotlib/src/prelude.rs +++ b/subplotlib/src/prelude.rs @@ -1,27 +1,37 @@ //! The subplotlib prelude // Re-export fehler's macros so that step functions can use them +#[doc(inline)] pub use fehler::throw; +#[doc(inline)] pub use fehler::throws; // Re-export the lazy_static macro +#[doc(inline)] pub use lazy_static::lazy_static; // Re-export subplotlib-derive's macros so that #[step] works +#[doc(inline)] pub use subplotlib_derive::step; // Re-export the step result types +#[doc(inline)] pub use crate::types::StepError; +#[doc(inline)] pub use crate::types::StepResult; // And the step itself +#[doc(inline)] pub use crate::step::ScenarioStep; // Data files +#[doc(inline)] pub use crate::file::SubplotDataFile; // Finally a scenario itself +#[doc(inline)] pub use crate::scenario::Scenario; // Utility functions +#[doc(inline)] pub use crate::utils::base64_decode; diff --git a/subplotlib/src/scenario.rs b/subplotlib/src/scenario.rs index 5511d81..7b2b1ba 100644 --- a/subplotlib/src/scenario.rs +++ b/subplotlib/src/scenario.rs @@ -1,10 +1,17 @@ -//! Scenario -// +//! Scenarios +//! +//! In general you will not need to interact with the [`Scenario`] type directly. +//! Instead instances of it are constructed in the generated test functions and +//! will be run automatically. use crate::step::ScenarioStep; use crate::types::StepError; -/// A Scenario is the embodiment of something which can be run as a scenario. +/// The embodiment of a subplot scenario +/// +/// Scenario objects are built up by the generated test functions and then run +/// to completion. In rare cases they may be built up and cached for reuse +/// for example if a scenario is a subroutine. pub struct Scenario<C> { title: String, steps: Vec<(ScenarioStep<C>, Option<ScenarioStep<C>>)>, @@ -14,6 +21,7 @@ impl<C> Scenario<C> where C: Default, { + /// Create a new scenario with the given title pub fn new(title: &str) -> Self { Self { title: title.to_string(), @@ -21,10 +29,26 @@ where } } + /// Retrieve the scenario title + pub fn title(&self) -> &str { + &self.title + } + + /// Add a scenario step, with optional cleanup step function. pub fn add_step(&mut self, step: ScenarioStep<C>, cleanup: Option<ScenarioStep<C>>) { self.steps.push((step, cleanup)); } + /// Run the scenario to completion. + /// + /// Running the scenario to completion requires running each step in turn. + /// This will return the first encountered error, or unit if the scenario + /// runs cleanly. + /// + /// # Panics + /// + /// If any of the cleanup functions error, this will immediately panic. + /// pub fn run(self) -> Result<(), StepError> { let mut highest = None; let mut context = C::default(); diff --git a/subplotlib/src/step.rs b/subplotlib/src/step.rs index cdfba74..6b4c334 100644 --- a/subplotlib/src/step.rs +++ b/subplotlib/src/step.rs @@ -1,22 +1,35 @@ //! Scenario steps +//! +//! In general you will not need to interact with these types, they're simply +//! here to provide wrappers to make the scenarios easier to work with. +//! use crate::types::StepResult; -/// StepFunctions are one of the StepFunction or MutableStepFunction type +/// Step functions +/// +/// Each step function might take a mutable or immutable borrow of the context +/// which is used in the scenario. enum StepFunctions<C> { Immutable(Box<dyn Fn(&C) -> StepResult>), Mutable(Box<dyn Fn(&mut C) -> StepResult>), } -/// A ScenarioStep is one step in a scenario. It is, quite simply, a -/// named closure. +/// A ScenarioStep is one step in a scenario. /// +/// In essence, a scenario step is a named closure. Its name can be used when +/// reporting an error encountered in running a scenario. pub struct ScenarioStep<C> { name: String, func: StepFunctions<C>, } impl<C> ScenarioStep<C> { + /// Create a new scenario step taking an immutable context + /// + /// This is used to construct a scenario step from a function which + /// takes an immutable borrow of the context. This will generally be + /// called from the generated build method for the step. pub fn new_immutable<F>(name: &str, func: F) -> Self where F: Fn(&C) -> StepResult + 'static, @@ -27,6 +40,11 @@ impl<C> ScenarioStep<C> { } } + /// Create a new scenario step taking a mutable context + /// + /// This is used to construct a scenario step from a functino which + /// takes a mutable borrow of the context. This will generally be + /// called from the generated build method for the step. pub fn new_mutable<F>(name: &str, func: F) -> Self where F: Fn(&mut C) -> StepResult + 'static, @@ -37,10 +55,18 @@ impl<C> ScenarioStep<C> { } } + /// Call the step function + /// + /// This simply calls the encased step function pub fn call(&self, context: &mut C) -> StepResult { match &self.func { StepFunctions::Immutable(f) => f(context), StepFunctions::Mutable(f) => f(context), } } + + /// Return the name of this step + pub fn name(&self) -> &str { + &self.name + } } diff --git a/subplotlib/src/types.rs b/subplotlib/src/types.rs index 09efe8b..963ce87 100644 --- a/subplotlib/src/types.rs +++ b/subplotlib/src/types.rs @@ -1,6 +1,17 @@ //! Fundamental types used throughout subplotlib /// Generic error type which steps can return. +/// +/// Step functions constructed using the [`step`][macro@subplotlib_derive::step] +/// macro will automatically return this as the error type. It is pretty +/// generic meaning that almost every possible use of the `?` operator should +/// work. pub type StepError = ::std::boxed::Box<dyn ::std::error::Error>; -/// Result type using that, useful for use in #[throws] + +/// Result type using [`StepError`]. +/// +/// This is useful for use in situations where you +/// might use [`#[throws(...)]`][macro@fehler::throws]. Step functions +/// generated using the [`step`][macro@subplotlib_derive::step] macro will +/// automatically set this as their return type by means of `#[throws(StepResult)]`. pub type StepResult = ::std::result::Result<(), StepError>; diff --git a/subplotlib/src/utils.rs b/subplotlib/src/utils.rs index f7f1d5f..ee60f06 100644 --- a/subplotlib/src/utils.rs +++ b/subplotlib/src/utils.rs @@ -1,8 +1,12 @@ -//! Utility functions +//! Utility functions used by subplotlib or the generated test functions /// Decode a base64 string. /// -/// Note: Will panic if it's not valid base64 leading to a string +/// If the result is not a valid utf8 string then it is lossily coerced. +/// +/// # Panics +/// +/// Will panic if it's not valid base64 leading to a string. pub fn base64_decode(input: &str) -> String { let dec = base64::decode(input).expect("bad base64"); String::from_utf8_lossy(&dec).to_string() |