diff options
Diffstat (limited to 'vendor/snapbox/src')
-rw-r--r-- | vendor/snapbox/src/assert.rs | 49 | ||||
-rw-r--r-- | vendor/snapbox/src/cmd.rs | 146 | ||||
-rw-r--r-- | vendor/snapbox/src/harness.rs | 4 | ||||
-rw-r--r-- | vendor/snapbox/src/path.rs | 1 | ||||
-rw-r--r-- | vendor/snapbox/src/report/color.rs | 128 | ||||
-rw-r--r-- | vendor/snapbox/src/report/diff.rs | 18 |
6 files changed, 234 insertions, 112 deletions
diff --git a/vendor/snapbox/src/assert.rs b/vendor/snapbox/src/assert.rs index ab87f1554..f0267c071 100644 --- a/vendor/snapbox/src/assert.rs +++ b/vendor/snapbox/src/assert.rs @@ -1,3 +1,10 @@ +#[cfg(feature = "color")] +use anstream::panic; +#[cfg(feature = "color")] +use anstream::stderr; +#[cfg(not(feature = "color"))] +use std::io::stderr; + use crate::data::{DataFormat, NormalizeMatches, NormalizeNewlines, NormalizePaths}; use crate::Action; @@ -232,36 +239,25 @@ impl Assert { use std::io::Write; let _ = writeln!( - std::io::stderr(), + stderr(), "{}: {}", self.palette.warn("Ignoring failure"), err ); } Action::Verify => { - use std::fmt::Write; - let mut buffer = String::new(); - write!(&mut buffer, "{}", err).unwrap(); - if let Some(action_var) = self.action_var.as_deref() { - writeln!( - &mut buffer, - "{}", - self.palette - .hint(format_args!("Update with {}=overwrite", action_var)) - ) - .unwrap(); - } - panic!("{}", buffer); + let message = if let Some(action_var) = self.action_var.as_deref() { + self.palette + .hint(format!("Update with {}=overwrite", action_var)) + } else { + crate::report::Styled::new(String::new(), Default::default()) + }; + panic!("{err}{message}"); } Action::Overwrite => { use std::io::Write; - let _ = writeln!( - std::io::stderr(), - "{}: {}", - self.palette.warn("Fixing"), - err - ); + let _ = writeln!(stderr(), "{}: {}", self.palette.warn("Fixing"), err); actual.write_to(expected_path).unwrap(); } } @@ -415,20 +411,17 @@ impl Assert { } if ok { use std::io::Write; - let _ = write!(std::io::stderr(), "{}", buffer); + let _ = write!(stderr(), "{}", buffer); match self.action { Action::Skip => unreachable!("Bailed out earlier"), Action::Ignore => { - let _ = write!( - std::io::stderr(), - "{}", - self.palette.warn("Ignoring above failures") - ); + let _ = + write!(stderr(), "{}", self.palette.warn("Ignoring above failures")); } Action::Verify => unreachable!("Something had to fail to get here"), Action::Overwrite => { let _ = write!( - std::io::stderr(), + stderr(), "{}", self.palette.warn("Overwrote above failures") ); @@ -519,7 +512,7 @@ impl Default for Assert { action_var: Default::default(), normalize_paths: true, substitutions: Default::default(), - palette: crate::report::Palette::auto(), + palette: crate::report::Palette::color(), data_format: Default::default(), } .substitutions(crate::Substitutions::with_exe()) diff --git a/vendor/snapbox/src/cmd.rs b/vendor/snapbox/src/cmd.rs index 72de3563c..8529852f9 100644 --- a/vendor/snapbox/src/cmd.rs +++ b/vendor/snapbox/src/cmd.rs @@ -1,5 +1,8 @@ //! Run commands and assert on their behavior +#[cfg(feature = "color")] +use anstream::panic; + /// Process spawning for testing of non-interactive commands #[derive(Debug)] pub struct Command { @@ -923,10 +926,9 @@ pub fn display_exit_status(status: std::process::ExitStatus) -> String { #[cfg(windows)] fn detailed_exit_status(status: std::process::ExitStatus) -> Option<String> { - use winapi::shared::minwindef::DWORD; - use winapi::um::winnt::*; + use windows_sys::Win32::Foundation::*; - let extra = match status.code().unwrap() as DWORD { + let extra = match status.code().unwrap() as NTSTATUS { STATUS_ACCESS_VIOLATION => "STATUS_ACCESS_VIOLATION", STATUS_IN_PAGE_ERROR => "STATUS_IN_PAGE_ERROR", STATUS_INVALID_HANDLE => "STATUS_INVALID_HANDLE", @@ -1028,3 +1030,141 @@ fn target_dir() -> std::path::PathBuf { }) .unwrap() } + +#[cfg(feature = "examples")] +pub use examples::{compile_example, compile_examples}; + +#[cfg(feature = "examples")] +pub(crate) mod examples { + /// Prepare an example for testing + /// + /// Unlike `cargo_bin!`, this does not inherit all of the current compiler settings. It + /// will match the current target and profile but will not get feature flags. Pass those arguments + /// to the compiler via `args`. + /// + /// ## Example + /// + /// ```rust,no_run + /// snapbox::cmd::compile_example("snap-example-fixture", []); + /// ``` + #[cfg(feature = "examples")] + pub fn compile_example<'a>( + target_name: &str, + args: impl IntoIterator<Item = &'a str>, + ) -> Result<std::path::PathBuf, crate::Error> { + crate::debug!("Compiling example {}", target_name); + let messages = escargot::CargoBuild::new() + .current_target() + .current_release() + .example(target_name) + .args(args) + .exec() + .map_err(|e| crate::Error::new(e.to_string()))?; + for message in messages { + let message = message.map_err(|e| crate::Error::new(e.to_string()))?; + let message = message + .decode() + .map_err(|e| crate::Error::new(e.to_string()))?; + crate::debug!("Message: {:?}", message); + if let Some(bin) = decode_example_message(&message) { + let (name, bin) = bin?; + assert_eq!(target_name, name); + return bin; + } + } + + Err(crate::Error::new(format!( + "Unknown error building example {}", + target_name + ))) + } + + /// Prepare all examples for testing + /// + /// Unlike `cargo_bin!`, this does not inherit all of the current compiler settings. It + /// will match the current target and profile but will not get feature flags. Pass those arguments + /// to the compiler via `args`. + /// + /// ## Example + /// + /// ```rust,no_run + /// let examples = snapbox::cmd::compile_examples([]).unwrap().collect::<Vec<_>>(); + /// ``` + #[cfg(feature = "examples")] + pub fn compile_examples<'a>( + args: impl IntoIterator<Item = &'a str>, + ) -> Result< + impl Iterator<Item = (String, Result<std::path::PathBuf, crate::Error>)>, + crate::Error, + > { + crate::debug!("Compiling examples"); + let mut examples = std::collections::BTreeMap::new(); + + let messages = escargot::CargoBuild::new() + .current_target() + .current_release() + .examples() + .args(args) + .exec() + .map_err(|e| crate::Error::new(e.to_string()))?; + for message in messages { + let message = message.map_err(|e| crate::Error::new(e.to_string()))?; + let message = message + .decode() + .map_err(|e| crate::Error::new(e.to_string()))?; + crate::debug!("Message: {:?}", message); + if let Some(bin) = decode_example_message(&message) { + let (name, bin) = bin?; + examples.insert(name.to_owned(), bin); + } + } + + Ok(examples.into_iter()) + } + + #[allow(clippy::type_complexity)] + fn decode_example_message<'m>( + message: &'m escargot::format::Message, + ) -> Option<Result<(&'m str, Result<std::path::PathBuf, crate::Error>), crate::Error>> { + match message { + escargot::format::Message::CompilerMessage(msg) => { + let level = msg.message.level; + if level == escargot::format::diagnostic::DiagnosticLevel::Ice + || level == escargot::format::diagnostic::DiagnosticLevel::Error + { + let output = msg + .message + .rendered + .as_deref() + .unwrap_or_else(|| msg.message.message.as_ref()) + .to_owned(); + if is_example_target(&msg.target) { + let bin = Err(crate::Error::new(output)); + Some(Ok((msg.target.name.as_ref(), bin))) + } else { + Some(Err(crate::Error::new(output))) + } + } else { + None + } + } + escargot::format::Message::CompilerArtifact(artifact) => { + if !artifact.profile.test && is_example_target(&artifact.target) { + let path = artifact + .executable + .clone() + .expect("cargo is new enough for this to be present"); + let bin = Ok(path.into_owned()); + Some(Ok((artifact.target.name.as_ref(), bin))) + } else { + None + } + } + _ => None, + } + } + + fn is_example_target(target: &escargot::format::Target) -> bool { + target.crate_types == ["bin"] && target.kind == ["example"] + } +} diff --git a/vendor/snapbox/src/harness.rs b/vendor/snapbox/src/harness.rs index ee1035aaa..77e085ebc 100644 --- a/vendor/snapbox/src/harness.rs +++ b/vendor/snapbox/src/harness.rs @@ -99,7 +99,7 @@ where overrides .matched(&path, is_dir) .is_whitelist() - .then(|| path) + .then_some(path) } else { Some(path) } @@ -114,6 +114,7 @@ where let actual = (test)(&case.fixture)?; let actual = actual.to_string(); let actual = crate::Data::text(actual).normalize(NormalizeNewlines); + #[allow(deprecated)] let verify = Verifier::new() .palette(crate::report::Palette::auto()) .action(self.action); @@ -199,6 +200,7 @@ impl Verifier { impl Default for Verifier { fn default() -> Self { Self { + #[allow(deprecated)] palette: crate::report::Palette::auto(), action: Action::Verify, } diff --git a/vendor/snapbox/src/path.rs b/vendor/snapbox/src/path.rs index 16e4ef653..9cd1e3f94 100644 --- a/vendor/snapbox/src/path.rs +++ b/vendor/snapbox/src/path.rs @@ -1,5 +1,6 @@ //! Initialize working directories and assert on how they've changed +#[cfg(feature = "path")] use crate::data::{NormalizeMatches, NormalizeNewlines, NormalizePaths}; /// Working directory for tests #[derive(Debug)] diff --git a/vendor/snapbox/src/report/color.rs b/vendor/snapbox/src/report/color.rs index f1cd363b4..1b74a3c58 100644 --- a/vendor/snapbox/src/report/color.rs +++ b/vendor/snapbox/src/report/color.rs @@ -1,127 +1,111 @@ -#[derive(Copy, Clone, Debug)] -#[allow(dead_code)] +#[derive(Copy, Clone, Debug, Default)] pub struct Palette { - pub(crate) info: styled::Style, - pub(crate) warn: styled::Style, - pub(crate) error: styled::Style, - pub(crate) hint: styled::Style, - pub(crate) expected: styled::Style, - pub(crate) actual: styled::Style, + pub(crate) info: anstyle::Style, + pub(crate) warn: anstyle::Style, + pub(crate) error: anstyle::Style, + pub(crate) hint: anstyle::Style, + pub(crate) expected: anstyle::Style, + pub(crate) actual: anstyle::Style, } impl Palette { - #[cfg(feature = "color")] - pub fn always() -> Self { - Self { - info: styled::Style(yansi::Style::new(yansi::Color::Green)), - warn: styled::Style(yansi::Style::new(yansi::Color::Yellow)), - error: styled::Style(yansi::Style::new(yansi::Color::Red)), - hint: styled::Style(yansi::Style::new(yansi::Color::Unset).dimmed()), - expected: styled::Style(yansi::Style::new(yansi::Color::Green).underline()), - actual: styled::Style(yansi::Style::new(yansi::Color::Red).underline()), + pub fn color() -> Self { + if cfg!(feature = "color") { + Self { + info: anstyle::AnsiColor::Green.into(), + warn: anstyle::AnsiColor::Yellow.into(), + error: anstyle::AnsiColor::Red.into(), + hint: anstyle::Effects::DIMMED.into(), + expected: anstyle::AnsiColor::Green | anstyle::Effects::UNDERLINE, + actual: anstyle::AnsiColor::Red | anstyle::Effects::UNDERLINE, + } + } else { + Self::plain() } } - #[cfg(not(feature = "color"))] + pub fn plain() -> Self { + Self::default() + } + + #[deprecated(since = "0.4.9", note = "Renamed to `Palette::color")] pub fn always() -> Self { - Self::never() + Self::color() } + #[deprecated(since = "0.4.9", note = "Renamed to `Palette::plain")] pub fn never() -> Self { - Self { - info: Default::default(), - warn: Default::default(), - error: Default::default(), - hint: Default::default(), - expected: Default::default(), - actual: Default::default(), - } + Self::plain() } + #[deprecated( + since = "0.4.9", + note = "Use `Palette::always`, `auto` behavior is now implicit" + )] pub fn auto() -> Self { if is_colored() { - Self::always() + Self::color() } else { - Self::never() + Self::plain() } } pub fn info<D: std::fmt::Display>(self, item: D) -> Styled<D> { - self.info.paint(item) + Styled::new(item, self.info) } pub fn warn<D: std::fmt::Display>(self, item: D) -> Styled<D> { - self.warn.paint(item) + Styled::new(item, self.warn) } pub fn error<D: std::fmt::Display>(self, item: D) -> Styled<D> { - self.error.paint(item) + Styled::new(item, self.error) } pub fn hint<D: std::fmt::Display>(self, item: D) -> Styled<D> { - self.hint.paint(item) + Styled::new(item, self.hint) } pub fn expected<D: std::fmt::Display>(self, item: D) -> Styled<D> { - self.expected.paint(item) + Styled::new(item, self.expected) } pub fn actual<D: std::fmt::Display>(self, item: D) -> Styled<D> { - self.actual.paint(item) + Styled::new(item, self.actual) } } fn is_colored() -> bool { #[cfg(feature = "color")] { - concolor::get(concolor::Stream::Either).ansi_color() + anstream::AutoStream::choice(&std::io::stderr()) != anstream::ColorChoice::Never } - #[cfg(not(feature = "color"))] { false } } -pub(crate) use styled::Style; -pub use styled::Styled; - -#[cfg(feature = "color")] -mod styled { - #[derive(Copy, Clone, Debug, Default)] - pub(crate) struct Style(pub(crate) yansi::Style); - - impl Style { - pub(crate) fn paint<T: std::fmt::Display>(self, item: T) -> Styled<T> { - Styled(self.0.paint(item)) - } - } - - pub struct Styled<D: std::fmt::Display>(yansi::Paint<D>); +pub(crate) use anstyle::Style; - impl<D: std::fmt::Display> std::fmt::Display for Styled<D> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.0.fmt(f) - } - } +#[derive(Debug)] +pub struct Styled<D> { + display: D, + style: anstyle::Style, } -#[cfg(not(feature = "color"))] -mod styled { - #[derive(Copy, Clone, Debug, Default)] - pub(crate) struct Style; - - impl Style { - pub(crate) fn paint<T: std::fmt::Display>(self, item: T) -> Styled<T> { - Styled(item) - } +impl<D: std::fmt::Display> Styled<D> { + pub(crate) fn new(display: D, style: anstyle::Style) -> Self { + Self { display, style } } +} - pub struct Styled<D: std::fmt::Display>(D); - - impl<D: std::fmt::Display> std::fmt::Display for Styled<D> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.0.fmt(f) - } +impl<D: std::fmt::Display> std::fmt::Display for Styled<D> { + #[inline] + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.style.render())?; + self.display.fmt(f)?; + write!(f, "{}", self.style.render_reset())?; + Ok(()) } } diff --git a/vendor/snapbox/src/report/diff.rs b/vendor/snapbox/src/report/diff.rs index adc9f7935..67f6810b5 100644 --- a/vendor/snapbox/src/report/diff.rs +++ b/vendor/snapbox/src/report/diff.rs @@ -1,3 +1,5 @@ +use crate::report::Styled; + pub fn write_diff( writer: &mut dyn std::fmt::Write, expected: &crate::Data, @@ -169,13 +171,13 @@ fn write_change( } else { write!(writer, "{:>4} ", " ",)?; } - write!(writer, "{} ", style.paint(sign))?; + write!(writer, "{} ", Styled::new(sign, style))?; for &(emphasized, change) in change.values() { let cur_style = if emphasized { em_style } else { style }; - write!(writer, "{}", cur_style.paint(change))?; + write!(writer, "{}", Styled::new(change, cur_style))?; } if change.missing_newline() { - writeln!(writer, "{}", em_style.paint("∅"))?; + writeln!(writer, "{}", Styled::new("∅", em_style))?; } Ok(()) @@ -192,7 +194,7 @@ mod test { let expected_name = "A"; let actual = "Hello\nWorld\n"; let actual_name = "B"; - let palette = crate::report::Palette::never(); + let palette = crate::report::Palette::plain(); let mut actual_diff = String::new(); write_diff_inner( @@ -221,7 +223,7 @@ mod test { let expected_name = "A"; let actual = "Hello\n"; let actual_name = "B"; - let palette = crate::report::Palette::never(); + let palette = crate::report::Palette::plain(); let mut actual_diff = String::new(); write_diff_inner( @@ -250,7 +252,7 @@ mod test { let expected_name = "A"; let actual = "Hello\nWorld\n"; let actual_name = "B"; - let palette = crate::report::Palette::never(); + let palette = crate::report::Palette::plain(); let mut actual_diff = String::new(); write_diff_inner( @@ -280,7 +282,7 @@ mod test { let expected_name = "A"; let actual = "Hello\nWorld"; let actual_name = "B"; - let palette = crate::report::Palette::never(); + let palette = crate::report::Palette::plain(); let mut actual_diff = String::new(); write_diff_inner( @@ -334,7 +336,7 @@ mod test { actual.push_str("?\n"); let actual_name = "B"; - let palette = crate::report::Palette::never(); + let palette = crate::report::Palette::plain(); let mut actual_diff = String::new(); write_diff_inner( |