summaryrefslogtreecommitdiff
path: root/subplotlib/src
diff options
context:
space:
mode:
Diffstat (limited to 'subplotlib/src')
-rw-r--r--subplotlib/src/file.rs12
-rw-r--r--subplotlib/src/prelude.rs12
-rw-r--r--subplotlib/src/scenario.rs26
-rw-r--r--subplotlib/src/step.rs20
-rw-r--r--subplotlib/src/steplibrary/datadir.rs3
-rw-r--r--subplotlib/src/steplibrary/files.rs10
-rw-r--r--subplotlib/src/steplibrary/runcmd.rs26
-rw-r--r--subplotlib/src/types.rs2
-rw-r--r--subplotlib/src/utils.rs4
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()
}