Skip to content

Commit

Permalink
Merge d084599 into 55f9b7a
Browse files Browse the repository at this point in the history
  • Loading branch information
tommilligan committed Aug 23, 2021
2 parents 55f9b7a + d084599 commit cf21269
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/check.yml
Expand Up @@ -25,6 +25,11 @@ jobs:
with:
toolchain: stable
override: true
- name: Install toolchain (nightly)
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
override: false
- name: Install additional test dependencies
env:
CARGO_TARGET_DIR: cargo_target
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,8 @@
# Unreleased

- Adds the `unstable` feature to the `pretty_assertions` crate, for use with nightly rustc ([#81](https://github.com/colin-kiegel/rust-pretty-assertions/pull/81), [@tommilligan](https://github.com/tommilligan))
- Add a drop in replacement for the unstable stdlib `assert_matches` macro, behind the `unstable` flag - thanks [@gilescope](https://github.com/gilescope) for the suggestion! ([#81](https://github.com/colin-kiegel/rust-pretty-assertions/issues/81), [@tommilligan](https://github.com/tommilligan))

# v0.7.2

- Fix macro hygiene for expansion in a `no_implicit_prelude` context ([#70](https://github.com/colin-kiegel/rust-pretty-assertions/issues/70), [@tommilligan](https://github.com/tommilligan))
Expand Down
7 changes: 5 additions & 2 deletions pretty_assertions/Cargo.toml
Expand Up @@ -17,8 +17,11 @@ categories = ["development-tools"]
keywords = ["assert", "diff", "pretty", "color"]
readme = "README.md"

[badges]
travis-ci = { repository = "colin-kiegel/rust-pretty-assertions" }
[features]
default = []

# Enable unstable features requiring nightly rustc
unstable = []

[dependencies]
ansi_term = "0.12.1"
Expand Down
89 changes: 89 additions & 0 deletions pretty_assertions/src/lib.rs
Expand Up @@ -62,6 +62,13 @@
//! you include.
//! * `assert_ne` is also switched to multi-line presentation, but does _not_ show
//! a diff.
//!
//! ## Features
//!
//! Features provided by the crate are as follows:
//!
//! - `unstable`: opt-in to unstable features that may not follow Semantic Versioning.
//! Implmenetion behind this feature is subject to change without warning between patch versions.

#![deny(clippy::all, missing_docs, unsafe_code)]

Expand Down Expand Up @@ -238,3 +245,85 @@ macro_rules! assert_ne {
}
});
}

/// Asserts that a value matches a pattern.
///
/// On panic, this macro will print a diff derived from [`Debug`] representation of
/// the value, and a string representation of the pattern.
///
/// This is a drop in replacement for [`std::assert_matches::assert_matches!`].
/// You can provide a custom panic message if desired.
///
/// # Examples
///
/// ```
/// use pretty_assertions::assert_matches;
///
/// let a = Some(3);
/// assert_matches!(a, Some(_));
///
/// assert_matches!(a, Some(value) if value > 2, "we are testing {:?} with a pattern", a);
/// ```
///
/// # Features
///
/// Requires the `unstable` feature to be enabled.
///
/// **Please note:** implementation under the `unstable` feature may be changed between
/// patch versions without warning.
#[cfg(feature = "unstable")]
#[macro_export]
macro_rules! assert_matches {
($left:expr, $( $pattern:pat )|+ $( if $guard: expr )? $(,)?) => ({
match $left {
$( $pattern )|+ $( if $guard )? => {}
ref left_val => {
$crate::assert_matches!(
@
left_val,
::std::stringify!($($pattern)|+ $(if $guard)?),
"",
""
);
}
}
});
($left:expr, $( $pattern:pat )|+ $( if $guard: expr )?, $($arg:tt)+) => ({
match $left {
$( $pattern )|+ $( if $guard )? => {}
ref left_val => {
$crate::assert_matches!(
@
left_val,
::std::stringify!($($pattern)|+ $(if $guard)?),
": ",
$($arg)+
);
}
}

});
(@ $left:expr, $right:expr, $maybe_semicolon:expr, $($arg:tt)*) => ({
match (&($left), &($right)) {
(left_val, right_val) => {
// Use the Display implementation to display the pattern,
// as using Debug would add another layer of quotes to the output.
struct Pattern<'a>(&'a str);
impl ::std::fmt::Debug for Pattern<'_> {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::std::fmt::Display::fmt(self.0, f)
}
}

::std::panic!("assertion failed: `(left matches right)`{}{}\
\n\
\n{}\
\n",
$maybe_semicolon,
format_args!($($arg)*),
$crate::Comparison::new(left_val, &Pattern(right_val))
)
}
}
});
}
86 changes: 86 additions & 0 deletions pretty_assertions/tests/macros.rs
Expand Up @@ -220,3 +220,89 @@ mod assert_ne {
not_zero(0);
}
}

#[cfg(feature = "unstable")]
mod assert_matches {
use ::std::option::Option::{None, Some};

#[test]
fn passes() {
let a = Some("some value");
::pretty_assertions::assert_matches!(a, Some(_));
}

#[test]
fn passes_unsized() {
let a: &[u8] = b"e";
::pretty_assertions::assert_matches!(*a, _);
}

#[test]
#[should_panic(expected = r#"assertion failed: `(left matches right)`
Diff < left / right > :
<None
>Some(_)
"#)]
fn fails() {
::pretty_assertions::assert_matches!(None::<usize>, Some(_));
}

#[test]
#[should_panic(expected = r#"assertion failed: `(left matches right)`
Diff < left / right > :
<Some(
< 3,
<)
>Some(3) if 0 > 0
"#)]
fn fails_guard() {
::pretty_assertions::assert_matches!(Some(3), Some(3) if 0 > 0,);
}

#[test]
#[should_panic(expected = r#"assertion failed: `(left matches right)`
Diff < left / right > :
<[
< 101,
<]
>ref b if b == b"ee"
"#)]
fn fails_unsized() {
let a: &[u8] = b"e";
::pretty_assertions::assert_matches!(*a, ref b if b == b"ee");
}

#[test]
#[should_panic(
expected = r#"assertion failed: `(left matches right)`: custom panic message
Diff < left / right > :
<666
>999
"#
)]
fn fails_custom() {
::pretty_assertions::assert_matches!(666, 999, "custom panic message");
}

#[test]
#[should_panic(
expected = r#"assertion failed: `(left matches right)`: custom panic message
Diff < left / right > :
<666
>999
"#
)]
fn fails_custom_trailing_comma() {
::pretty_assertions::assert_matches!(666, 999, "custom panic message",);
}
}
2 changes: 1 addition & 1 deletion pretty_assertions_bench/Cargo.toml
Expand Up @@ -5,7 +5,7 @@ authors = ["Tom Milligan <code@tommilligan.net>"]
edition = "2018"

[dependencies]
criterion = { version = "0.3.4", features = ["html_reports"] }
criterion = { version = "0.3.5", features = ["html_reports"] }
pretty_assertions = { path = "../pretty_assertions" }

[lib]
Expand Down
3 changes: 3 additions & 0 deletions scripts/check
Expand Up @@ -18,6 +18,9 @@ cargo clippy --all-targets -- -D warnings
eprintln "Running unit tests"
cargo test

eprintln "Running unit tests (unstable)"
cargo +nightly test --manifest-path pretty_assertions/Cargo.toml --all --features unstable

eprintln "Building documentation"
cargo doc --no-deps

Expand Down

0 comments on commit cf21269

Please sign in to comment.