diff options
Diffstat (limited to 'subplotlib/src')
-rw-r--r-- | subplotlib/src/file.rs | 12 | ||||
-rw-r--r-- | subplotlib/src/prelude.rs | 12 | ||||
-rw-r--r-- | subplotlib/src/scenario.rs | 26 | ||||
-rw-r--r-- | subplotlib/src/step.rs | 20 | ||||
-rw-r--r-- | subplotlib/src/steplibrary/datadir.rs | 3 | ||||
-rw-r--r-- | subplotlib/src/steplibrary/files.rs | 10 | ||||
-rw-r--r-- | subplotlib/src/steplibrary/runcmd.rs | 26 | ||||
-rw-r--r-- | subplotlib/src/types.rs | 2 | ||||
-rw-r--r-- | subplotlib/src/utils.rs | 4 |
9 files changed, 68 insertions, 47 deletions
diff --git a/subplotlib/src/file.rs b/subplotlib/src/file.rs index 84f3495..c1c9afe 100644 --- a/subplotlib/src/file.rs +++ b/subplotlib/src/file.rs @@ -7,7 +7,8 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; -use base64::decode; +use base64::prelude::{Engine as _, BASE64_STANDARD}; + /// An embedded data file. /// /// Embedded data files have names and content. The subplot template will generate @@ -82,11 +83,16 @@ impl SubplotDataFile { /// /// 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 = BASE64_STANDARD + .decode(name) + .expect("Subplot generated bad base64?"); let name = String::from_utf8_lossy(&name); let name: PathBuf = name.as_ref().into(); let name = name.into(); - let data = decode(data).expect("Subplot generated bad base64?").into(); + let data = BASE64_STANDARD + .decode(data) + .expect("Subplot generated bad base64?") + .into(); Self { name, data } } diff --git a/subplotlib/src/prelude.rs b/subplotlib/src/prelude.rs index e0ac627..9397fa7 100644 --- a/subplotlib/src/prelude.rs +++ b/subplotlib/src/prelude.rs @@ -16,16 +16,16 @@ //! The primary thing you will need to learn, as a step function author, is //! the [`#[step]`][macro@step] attribute macro, and it interacts with contexts. -// Re-export fehler's macros so that step functions can use them -pub use fehler::throw; +// Re-export culpa's macros so that step functions can use them +pub use culpa::throw; /// Indicate what type a function throws /// -/// This attribute macro comes from the [`fehler`] crate and is used +/// This attribute macro comes from the [`culpa`] crate and is used /// to indicate that a function "throws" a particular kind of error. /// /// ```rust /// # use std::io; -/// # use fehler::throws; +/// # use culpa::throws; /// #[throws(io::Error)] /// fn create_thingy() { /// // something which might cause an io::Error @@ -51,10 +51,10 @@ pub use fehler::throw; /// // When https://github.com/rust-lang/rust/issues/83976 is resolved, the below // can be added to this doc string. -// You can see more documentation on this in the [fehler crate docs][fehler::throws]. +// You can see more documentation on this in the [culpa crate docs][culpa::throws]. // Alternatively we can get rid of this entirely if and when // https://github.com/rust-lang/rust/issues/81893 is fixed. -pub use fehler::throws; +pub use culpa::throws; // Re-export the lazy_static macro #[doc(hidden)] diff --git a/subplotlib/src/scenario.rs b/subplotlib/src/scenario.rs index 7a78ae5..9bcc43d 100644 --- a/subplotlib/src/scenario.rs +++ b/subplotlib/src/scenario.rs @@ -107,7 +107,7 @@ where C: ContextElement, { fn new() -> Self { - Self(PhantomData::default()) + Self(PhantomData) } } @@ -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<Vec<Box<dyn ScenarioContextHookKind>>>, } @@ -174,9 +175,9 @@ impl DebuggedContext { C: Debug, { let body = if alternate { - format!("{:#?}", obj) + format!("{obj:#?}") } else { - format!("{:?}", obj) + format!("{obj:?}") }; self.body.push(body); } @@ -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: <Container![]>::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 7a70e23..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<StepFunc>, reg: Box<dyn Fn(&Scenario)>, } @@ -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<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), } @@ -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<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") } } @@ -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 + } } diff --git a/subplotlib/src/steplibrary/datadir.rs b/subplotlib/src/steplibrary/datadir.rs index 5a344df..5060f63 100644 --- a/subplotlib/src/steplibrary/datadir.rs +++ b/subplotlib/src/steplibrary/datadir.rs @@ -150,8 +150,7 @@ pub fn datadir_has_enough_space(datadir: &Datadir, bytes: u64) { let available = fs2::available_space(datadir.base_path())?; if available < bytes { throw!(format!( - "Available space check failed, wanted {} bytes, but only {} were available", - bytes, available + "Available space check failed, wanted {bytes} bytes, but only {available} were available", )); } } diff --git a/subplotlib/src/steplibrary/files.rs b/subplotlib/src/steplibrary/files.rs index 8abe546..b1596ae 100644 --- a/subplotlib/src/steplibrary/files.rs +++ b/subplotlib/src/steplibrary/files.rs @@ -90,7 +90,7 @@ pub fn touch_with_timestamp(context: &Datadir, filename: &Path, mtime: &str) { let fd = format_description!( "[year]-[month]-[day] [hour]:[minute]:[second] [offset_hour]:[offset_minute]" ); - let full_time = format!("{} +00:00", mtime); + let full_time = format!("{mtime} +00:00"); let ts = OffsetDateTime::parse(&full_time, &fd)?; let (secs, nanos) = (ts.unix_timestamp(), 0); let mtime = FileTime::from_unix_time(secs, nanos); @@ -99,6 +99,7 @@ pub fn touch_with_timestamp(context: &Datadir, filename: &Path, mtime: &str) { drop( OpenOptions::new() .create(true) + .truncate(false) .write(true) .open(&full_path)?, ); @@ -130,7 +131,7 @@ pub fn remember_metadata(context: &ScenarioContext, filename: &Path) { |context: &Datadir| context.canonicalise_filename(filename), false, )?; - let metadata = fs::metadata(&full_path)?; + let metadata = fs::metadata(full_path)?; context.with_mut( |context: &mut Files| { context.metadata.insert(filename.to_owned(), metadata); @@ -154,6 +155,7 @@ pub fn touch(context: &Datadir, filename: &Path) { drop( OpenOptions::new() .create(true) + .truncate(false) .write(true) .open(&full_path)?, ); @@ -320,7 +322,7 @@ pub fn has_remembered_metadata(context: &ScenarioContext, filename: &Path) { |context: &Datadir| context.canonicalise_filename(filename), false, )?; - let metadata = fs::metadata(&full_path)?; + let metadata = fs::metadata(full_path)?; if let Some(remembered) = context.with( |context: &Files| Ok(context.metadata.get(filename).cloned()), false, @@ -359,7 +361,7 @@ pub fn has_different_metadata(context: &ScenarioContext, filename: &Path) { |context: &Datadir| context.canonicalise_filename(filename), false, )?; - let metadata = fs::metadata(&full_path)?; + let metadata = fs::metadata(full_path)?; if let Some(remembered) = context.with( |context: &Files| Ok(context.metadata.get(filename).cloned()), false, diff --git a/subplotlib/src/steplibrary/runcmd.rs b/subplotlib/src/steplibrary/runcmd.rs index 6692441..99605a3 100644 --- a/subplotlib/src/steplibrary/runcmd.rs +++ b/subplotlib/src/steplibrary/runcmd.rs @@ -353,7 +353,7 @@ pub fn exit_code_is(context: &Runcmd, exit: i32) { #[step] pub fn exit_code_is_not(context: &Runcmd, exit: i32) { if context.exitcode.is_none() || context.exitcode == Some(exit) { - throw!(format!("Expected exit code to not equal {}", exit)); + throw!(format!("Expected exit code to not equal {exit}")); } } @@ -422,7 +422,7 @@ fn check_matches(runcmd: &Runcmd, which: Stream, how: MatchKind, against: &str) #[step] pub fn stdout_is(runcmd: &Runcmd, text: &str) { if !check_matches(runcmd, Stream::Stdout, MatchKind::Exact, text)? { - throw!(format!("stdout is not {:?}", text)); + throw!(format!("stdout is not {text:?}")); } } @@ -435,7 +435,7 @@ pub fn stdout_is(runcmd: &Runcmd, text: &str) { #[step] pub fn stdout_isnt(runcmd: &Runcmd, text: &str) { if check_matches(runcmd, Stream::Stdout, MatchKind::Exact, text)? { - throw!(format!("stdout is exactly {:?}", text)); + throw!(format!("stdout is exactly {text:?}")); } } @@ -448,7 +448,7 @@ pub fn stdout_isnt(runcmd: &Runcmd, text: &str) { #[step] pub fn stderr_is(runcmd: &Runcmd, text: &str) { if !check_matches(runcmd, Stream::Stderr, MatchKind::Exact, text)? { - throw!(format!("stderr is not {:?}", text)); + throw!(format!("stderr is not {text:?}")); } } @@ -461,7 +461,7 @@ pub fn stderr_is(runcmd: &Runcmd, text: &str) { #[step] pub fn stderr_isnt(runcmd: &Runcmd, text: &str) { if check_matches(runcmd, Stream::Stderr, MatchKind::Exact, text)? { - throw!(format!("stderr is exactly {:?}", text)); + throw!(format!("stderr is exactly {text:?}")); } } @@ -474,7 +474,7 @@ pub fn stderr_isnt(runcmd: &Runcmd, text: &str) { #[step] pub fn stdout_contains(runcmd: &Runcmd, text: &str) { if !check_matches(runcmd, Stream::Stdout, MatchKind::Contains, text)? { - throw!(format!("stdout does not contain {:?}", text)); + throw!(format!("stdout does not contain {text:?}")); } } @@ -487,7 +487,7 @@ pub fn stdout_contains(runcmd: &Runcmd, text: &str) { #[step] pub fn stdout_doesnt_contain(runcmd: &Runcmd, text: &str) { if check_matches(runcmd, Stream::Stdout, MatchKind::Contains, text)? { - throw!(format!("stdout contains {:?}", text)); + throw!(format!("stdout contains {text:?}")); } } @@ -500,7 +500,7 @@ pub fn stdout_doesnt_contain(runcmd: &Runcmd, text: &str) { #[step] pub fn stderr_contains(runcmd: &Runcmd, text: &str) { if !check_matches(runcmd, Stream::Stderr, MatchKind::Contains, text)? { - throw!(format!("stderr does not contain {:?}", text)); + throw!(format!("stderr does not contain {text:?}")); } } @@ -513,7 +513,7 @@ pub fn stderr_contains(runcmd: &Runcmd, text: &str) { #[step] pub fn stderr_doesnt_contain(runcmd: &Runcmd, text: &str) { if check_matches(runcmd, Stream::Stderr, MatchKind::Contains, text)? { - throw!(format!("stderr contains {:?}", text)); + throw!(format!("stderr contains {text:?}")); } } @@ -527,7 +527,7 @@ pub fn stderr_doesnt_contain(runcmd: &Runcmd, text: &str) { #[step] pub fn stdout_matches_regex(runcmd: &Runcmd, regex: &str) { if !check_matches(runcmd, Stream::Stdout, MatchKind::Regex, regex)? { - throw!(format!("stdout does not match {:?}", regex)); + throw!(format!("stdout does not match {regex:?}")); } } @@ -541,7 +541,7 @@ pub fn stdout_matches_regex(runcmd: &Runcmd, regex: &str) { #[step] pub fn stdout_doesnt_match_regex(runcmd: &Runcmd, regex: &str) { if check_matches(runcmd, Stream::Stdout, MatchKind::Regex, regex)? { - throw!(format!("stdout matches {:?}", regex)); + throw!(format!("stdout matches {regex:?}")); } } @@ -555,7 +555,7 @@ pub fn stdout_doesnt_match_regex(runcmd: &Runcmd, regex: &str) { #[step] pub fn stderr_matches_regex(runcmd: &Runcmd, regex: &str) { if !check_matches(runcmd, Stream::Stderr, MatchKind::Regex, regex)? { - throw!(format!("stderr does not match {:?}", regex)); + throw!(format!("stderr does not match {regex:?}")); } } @@ -569,6 +569,6 @@ pub fn stderr_matches_regex(runcmd: &Runcmd, regex: &str) { #[step] pub fn stderr_doesnt_match_regex(runcmd: &Runcmd, regex: &str) { if check_matches(runcmd, Stream::Stderr, MatchKind::Regex, regex)? { - throw!(format!("stderr matches {:?}", regex)); + throw!(format!("stderr matches {regex:?}")); } } diff --git a/subplotlib/src/types.rs b/subplotlib/src/types.rs index 963ce87..d2377ca 100644 --- a/subplotlib/src/types.rs +++ b/subplotlib/src/types.rs @@ -11,7 +11,7 @@ pub type StepError = ::std::boxed::Box<dyn ::std::error::Error>; /// Result type using [`StepError`]. /// /// This is useful for use in situations where you -/// might use [`#[throws(...)]`][macro@fehler::throws]. Step functions +/// might use [`#[throws(...)]`][macro@culpa::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 642848a..25a9360 100644 --- a/subplotlib/src/utils.rs +++ b/subplotlib/src/utils.rs @@ -1,5 +1,7 @@ //! Utility functions used by subplotlib or the generated test functions +use base64::prelude::{Engine as _, BASE64_STANDARD}; + /// Decode a base64 string. /// /// If the result is not a valid utf8 string then it is lossily coerced. @@ -14,6 +16,6 @@ /// /// 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"); + let dec = BASE64_STANDARD.decode(input).expect("bad base64"); String::from_utf8_lossy(&dec).to_string() } |