#![deny(clippy::all, missing_docs, unsafe_code)]
pub use ansi_term::Style;
use std::fmt::{self, Debug, Display};
mod printer;
#[cfg(windows)]
use ctor::*;
#[cfg(windows)]
#[ctor]
fn init() {
output_vt100::try_init().ok();
}
pub struct Comparison<'a, TLeft, TRight>
where
TLeft: ?Sized,
TRight: ?Sized,
{
left: &'a TLeft,
right: &'a TRight,
}
impl<'a, TLeft, TRight> Comparison<'a, TLeft, TRight>
where
TLeft: ?Sized,
TRight: ?Sized,
{
pub fn new(left: &'a TLeft, right: &'a TRight) -> Comparison<'a, TLeft, TRight> {
Comparison { left, right }
}
}
impl<'a, TLeft, TRight> Display for Comparison<'a, TLeft, TRight>
where
TLeft: Debug + ?Sized,
TRight: Debug + ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let left_debug = format!("{:#?}", self.left);
let right_debug = format!("{:#?}", self.right);
printer::write_header(f)?;
printer::write_lines(f, &left_debug, &right_debug)
}
}
#[macro_export]
macro_rules! assert_eq {
($left:expr , $right:expr,) => ({
$crate::assert_eq!($left, $right)
});
($left:expr , $right:expr) => ({
match (&($left), &($right)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
::std::panic!("assertion failed: `(left == right)`\
\n\
\n{}\
\n",
$crate::Comparison::new(left_val, right_val))
}
}
}
});
($left:expr , $right:expr, $($arg:tt)*) => ({
match (&($left), &($right)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
::std::panic!("assertion failed: `(left == right)`: {}\
\n\
\n{}\
\n",
format_args!($($arg)*),
$crate::Comparison::new(left_val, right_val))
}
}
}
});
}
#[macro_export]
macro_rules! assert_ne {
($left:expr, $right:expr) => ({
$crate::assert_ne!(@ $left, $right, "", "");
});
($left:expr, $right:expr,) => ({
$crate::assert_ne!(@ $left, $right, "", "");
});
($left:expr, $right:expr, $($arg:tt)+) => ({
$crate::assert_ne!(@ $left, $right, ": ", $($arg)+);
});
(@ $left:expr, $right:expr, $maybe_semicolon:expr, $($arg:tt)+) => ({
match (&($left), &($right)) {
(left_val, right_val) => {
if *left_val == *right_val {
let left_dbg = ::std::format!("{:?}", &*left_val);
let right_dbg = ::std::format!("{:?}", &*right_val);
if left_dbg != right_dbg {
::std::panic!("assertion failed: `(left != right)`{}{}\
\n\
\n{}\
\n{}: According to the `PartialEq` implementation, both of the values \
are partially equivalent, even if the `Debug` outputs differ.\
\n\
\n",
$maybe_semicolon,
format_args!($($arg)+),
$crate::Comparison::new(left_val, right_val),
$crate::Style::new()
.bold()
.underline()
.paint("Note"))
}
::std::panic!("assertion failed: `(left != right)`{}{}\
\n\
\n{}:\
\n{:#?}\
\n\
\n",
$maybe_semicolon,
format_args!($($arg)+),
$crate::Style::new().bold().paint("Both sides"),
left_val)
}
}
}
});
}
#[cfg(test)]
#[allow(clippy::eq_op)]
#[no_implicit_prelude]
mod test {
mod assert_eq {
use ::std::string::{String, ToString};
#[test]
fn passes() {
let a = "some value";
crate::assert_eq!(a, a);
}
#[test]
fn passes_unsized() {
let a: &[u8] = b"e";
crate::assert_eq!(*a, *a);
}
#[test]
fn passes_comparable_types() {
let s0: &'static str = "foo";
let s1: String = "foo".to_string();
crate::assert_eq!(s0, s1);
}
#[test]
#[should_panic(expected = r#"assertion failed: `(left == right)`
[1mDiff[0m [31m< left[0m / [32mright >[0m :
[31m<[0m[1;48;5;52;31m666[0m
[32m>[0m[1;48;5;22;32m999[0m
"#)]
fn fails() {
crate::assert_eq!(666, 999);
}
#[test]
#[should_panic(expected = r#"assertion failed: `(left == right)`
[1mDiff[0m [31m< left[0m / [32mright >[0m :
[31m<[0m[1;48;5;52;31m666[0m
[32m>[0m[1;48;5;22;32m999[0m
"#)]
fn fails_trailing_comma() {
crate::assert_eq!(666, 999,);
}
#[test]
#[should_panic(expected = r#"assertion failed: `(left == right)`
[1mDiff[0m [31m< left[0m / [32mright >[0m :
[
101,
[32m> 101,[0m
]
"#)]
fn fails_unsized() {
let a: &[u8] = b"e";
let b: &[u8] = b"ee";
crate::assert_eq!(*a, *b);
}
#[test]
#[should_panic(
expected = r#"assertion failed: `(left == right)`: custom panic message
[1mDiff[0m [31m< left[0m / [32mright >[0m :
[31m<[0m[1;48;5;52;31m666[0m
[32m>[0m[1;48;5;22;32m999[0m
"#
)]
fn fails_custom() {
crate::assert_eq!(666, 999, "custom panic message");
}
#[test]
#[should_panic(
expected = r#"assertion failed: `(left == right)`: custom panic message
[1mDiff[0m [31m< left[0m / [32mright >[0m :
[31m<[0m[1;48;5;52;31m666[0m
[32m>[0m[1;48;5;22;32m999[0m
"#
)]
fn fails_custom_trailing_comma() {
crate::assert_eq!(666, 999, "custom panic message",);
}
}
mod assert_ne {
use ::std::string::{String, ToString};
#[test]
fn passes() {
let a = "a";
let b = "b";
crate::assert_ne!(a, b);
}
#[test]
fn passes_unsized() {
let a: &[u8] = b"e";
let b: &[u8] = b"ee";
crate::assert_ne!(*a, *b);
}
#[test]
fn passes_comparable_types() {
let s0: &'static str = "foo";
let s1: String = "bar".to_string();
crate::assert_ne!(s0, s1);
}
#[test]
#[should_panic(expected = r#"assertion failed: `(left != right)`
[1mBoth sides[0m:
666
"#)]
fn fails() {
crate::assert_ne!(666, 666);
}
#[test]
#[should_panic(expected = r#"assertion failed: `(left != right)`
[1mBoth sides[0m:
666
"#)]
fn fails_trailing_comma() {
crate::assert_ne!(666, 666,);
}
#[test]
#[should_panic(expected = r#"assertion failed: `(left != right)`
[1mBoth sides[0m:
[
101,
]
"#)]
fn fails_unsized() {
let a: &[u8] = b"e";
crate::assert_ne!(*a, *a);
}
#[test]
#[should_panic(
expected = r#"assertion failed: `(left != right)`: custom panic message
[1mBoth sides[0m:
666
"#
)]
fn fails_custom() {
crate::assert_ne!(666, 666, "custom panic message");
}
#[test]
#[should_panic(
expected = r#"assertion failed: `(left != right)`: custom panic message
[1mBoth sides[0m:
666
"#
)]
fn fails_custom_trailing_comma() {
crate::assert_ne!(666, 666, "custom panic message",);
}
#[test]
#[should_panic(expected = r#"assertion failed: `(left != right)`
[1mDiff[0m [31m< left[0m / [32mright >[0m :
[31m<[0m[1;48;5;52;31m-[0m[31m0.0[0m
[32m>0.0[0m
[1;4mNote[0m: According to the `PartialEq` implementation, both of the values are partially equivalent, even if the `Debug` outputs differ.
"#)]
fn assert_ne_partial() {
struct Foo(f32);
use ::std::fmt;
impl fmt::Debug for Foo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
::std::write!(f, "{:.1?}", self.0)
}
}
impl ::std::cmp::PartialEq for Foo {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
crate::assert_ne!(Foo(-0.0), Foo(0.0));
}
#[test]
#[should_panic]
fn assert_ne_non_empty_return() {
fn not_zero(x: u32) -> u32 {
crate::assert_ne!(x, 0);
x
}
not_zero(0);
}
}
}