summaryrefslogtreecommitdiffstats
path: root/vendor/snapbox/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/snapbox/src')
-rw-r--r--vendor/snapbox/src/assert.rs49
-rw-r--r--vendor/snapbox/src/cmd.rs146
-rw-r--r--vendor/snapbox/src/harness.rs4
-rw-r--r--vendor/snapbox/src/path.rs1
-rw-r--r--vendor/snapbox/src/report/color.rs128
-rw-r--r--vendor/snapbox/src/report/diff.rs18
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(