429 lines
11 KiB
Rust
429 lines
11 KiB
Rust
mod verify_pred {
|
|
use googletest::prelude::*;
|
|
use googletest::Result;
|
|
use indoc::indoc;
|
|
|
|
#[test]
|
|
fn supports_function_call_with_non_debug_types() -> Result<()> {
|
|
// Non-Debug - cannot be printed.
|
|
struct Apple;
|
|
fn f(_a: &Apple, _b: u32, _c: u32) -> bool {
|
|
false
|
|
}
|
|
fn g(_a: u32) -> u32 {
|
|
5
|
|
}
|
|
|
|
let a = &Apple;
|
|
let res = verify_pred!(f(a, g(g(3)), 1 + 2));
|
|
verify_that!(
|
|
res,
|
|
err(displays_as(contains_substring(indoc! {"
|
|
f(a, g(g(3)), 1 + 2) was false with
|
|
a does not implement Debug,
|
|
g(g(3)) = 5,
|
|
1 + 2 = 3,
|
|
at"
|
|
})))
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn supports_trailing_comma() -> Result<()> {
|
|
verify_that!(verify_pred!(false,), err(anything()))
|
|
}
|
|
|
|
#[test]
|
|
fn supports_non_function() -> Result<()> {
|
|
verify_pred!(true)?;
|
|
verify_that!(verify_pred!(false), err(anything()))
|
|
}
|
|
|
|
#[test]
|
|
fn does_not_print_literals() -> Result<()> {
|
|
trait Foo {
|
|
fn f(&self, _a: u32, _b: i32, _c: u32, _d: &str) -> bool {
|
|
false
|
|
}
|
|
}
|
|
impl Foo for i32 {}
|
|
|
|
let res = verify_pred!(0.f(1, 2_i32.abs(), 1 + 2, "hello"));
|
|
verify_that!(
|
|
res,
|
|
err(displays_as(contains_substring(indoc! {r#"
|
|
0.f(1, 2_i32.abs(), 1 + 2, "hello") was false with
|
|
2_i32.abs() = 2,
|
|
1 + 2 = 3,
|
|
at"#
|
|
})))
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn supports_chained_field_access_and_method_calls_with_non_debug_types() -> Result<()> {
|
|
// Non-Debug
|
|
struct Apple {
|
|
b: Banana,
|
|
}
|
|
#[derive(Debug)]
|
|
struct Banana;
|
|
impl Banana {
|
|
fn c(&self, _c: &Cherry, _d: u32) -> bool {
|
|
false
|
|
}
|
|
}
|
|
// Non-Debug - cannot be printed.
|
|
struct Cherry;
|
|
|
|
let a = Apple { b: Banana };
|
|
let c = &Cherry;
|
|
let d = 3;
|
|
let res = verify_pred!(a.b.c(c, d));
|
|
verify_that!(
|
|
res,
|
|
err(displays_as(contains_substring(indoc! {"
|
|
a.b.c(c, d) was false with
|
|
a does not implement Debug,
|
|
a.b = Banana,
|
|
c does not implement Debug,
|
|
d = 3,
|
|
at"
|
|
})))
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn evaluates_functions_and_arguments_exactly_once() -> Result<()> {
|
|
let mut a = 0;
|
|
let mut foo = |_b: u32| {
|
|
a += 1;
|
|
false
|
|
};
|
|
let mut b = 0;
|
|
let mut bar = || {
|
|
b += 10;
|
|
b
|
|
};
|
|
|
|
let res = verify_pred!(foo(bar()));
|
|
verify_that!(
|
|
res,
|
|
err(displays_as(contains_substring(indoc! {"
|
|
foo(bar()) was false with
|
|
bar() = 10,
|
|
at"
|
|
})))
|
|
)?;
|
|
|
|
verify_that!((a, b), eq((1, 10)))
|
|
}
|
|
|
|
#[test]
|
|
fn evaluates_methods_and_arguments_exactly_once() -> Result<()> {
|
|
struct Apple(u32);
|
|
impl Apple {
|
|
fn c(&mut self, _b: bool) -> bool {
|
|
self.0 += 1;
|
|
false
|
|
}
|
|
}
|
|
let mut a = Apple(0);
|
|
let mut b = Apple(10);
|
|
|
|
let res = verify_pred!(a.c(b.c(false)));
|
|
verify_that!(
|
|
res,
|
|
err(displays_as(contains_substring(indoc! {"
|
|
a.c(b.c(false)) was false with
|
|
a does not implement Debug,
|
|
b.c(false) = false,
|
|
at"
|
|
})))
|
|
)?;
|
|
|
|
verify_that!((a.0, b.0), eq((1, 11)))
|
|
}
|
|
|
|
#[test]
|
|
fn supports_chained_method_calls() -> Result<()> {
|
|
#[derive(Debug)]
|
|
struct Apple;
|
|
impl Apple {
|
|
fn b(&self, _b: u32) -> Banana {
|
|
Banana
|
|
}
|
|
}
|
|
// Non-Debug: not printed on error.
|
|
struct Banana;
|
|
impl Banana {
|
|
fn c(&self, _c0: u32, _c1: Cherry) -> bool {
|
|
false
|
|
}
|
|
}
|
|
// Non-Debug: not printed on error.
|
|
#[derive(Copy, Clone)]
|
|
struct Cherry;
|
|
|
|
let a = Apple;
|
|
let v = 10;
|
|
let res = verify_pred!(a.b(v).c(11, Cherry));
|
|
verify_that!(
|
|
res,
|
|
err(displays_as(contains_substring(indoc! {"
|
|
a.b(v).c(11, Cherry) was false with
|
|
a = Apple,
|
|
v = 10,
|
|
a.b(v) does not implement Debug,
|
|
Cherry does not implement Debug,
|
|
at"
|
|
})))
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn prints_consumed_values() -> Result<()> {
|
|
// Non-Debug
|
|
struct Apple;
|
|
impl Apple {
|
|
fn b(self) -> Banana {
|
|
Banana
|
|
}
|
|
}
|
|
#[derive(Debug)]
|
|
struct Banana;
|
|
impl Banana {
|
|
fn c(self) -> bool {
|
|
false
|
|
}
|
|
}
|
|
|
|
let a = Apple;
|
|
let res = verify_pred!(a.b().c());
|
|
verify_that!(
|
|
res,
|
|
err(displays_as(contains_substring(indoc! {"
|
|
a.b().c() was false with
|
|
a does not implement Debug,
|
|
a.b() = Banana,
|
|
at"
|
|
})))
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn works_with_realistic_example_with_consumed_intermediate_values() -> Result<()> {
|
|
let res =
|
|
verify_pred!(vec![1, 2].into_iter().map(|x| x * 2).collect::<Vec<_>>().is_empty());
|
|
verify_that!(
|
|
res,
|
|
err(displays_as(contains_substring(indoc! {"
|
|
vec! [1, 2].into_iter().map(| x | x * 2).collect :: < Vec < _ > >
|
|
().is_empty() was false with
|
|
vec! [1, 2] = [1, 2],
|
|
vec! [1, 2].into_iter() = IntoIter([1, 2]),
|
|
| x | x * 2 does not implement Debug,
|
|
vec! [1, 2].into_iter().map(| x | x * 2) = Map { iter: IntoIter([1, 2]) },
|
|
vec! [1, 2].into_iter().map(| x | x * 2).collect :: < Vec < _ > > () = [2, 4],
|
|
at"
|
|
})))
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn values_should_be_accessible_after_test() -> Result<()> {
|
|
// Not `Copy` and should not be consumed by the generated test code.
|
|
#[derive(Debug)]
|
|
struct Apple;
|
|
impl Apple {
|
|
fn b(&self, _c: &mut u32) -> bool {
|
|
false
|
|
}
|
|
}
|
|
|
|
let mut c = 0;
|
|
let a = Apple;
|
|
let res = verify_pred!(a.b(&mut c));
|
|
verify_that!(
|
|
res,
|
|
err(displays_as(contains_substring(indoc! {"
|
|
a.b(& mut c) was false with
|
|
a = Apple,
|
|
& mut c = 0,
|
|
at"
|
|
})))
|
|
)?;
|
|
|
|
// `a` and `&mut c` should still be accessible after the test despite not being
|
|
// `Copy`.
|
|
let _ = a.b(&mut c);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn prints_values_for_mutating_expressions() -> Result<()> {
|
|
let mut a = 1;
|
|
let mut b = 2;
|
|
let mut c = 0;
|
|
trait Mutator {
|
|
fn mutate_and_false(&mut self, b: &mut u32) -> bool;
|
|
}
|
|
impl Mutator for u32 {
|
|
fn mutate_and_false(&mut self, b: &mut u32) -> bool {
|
|
*self += 10;
|
|
*b += 20;
|
|
false
|
|
}
|
|
}
|
|
|
|
// Macro to to avoid the inconsistency in how `;` and `&mut` are printed between
|
|
// Rust versions when printing out the stringified version of the block.
|
|
macro_rules! block_a {
|
|
() => {{
|
|
c += 10;
|
|
&mut a
|
|
}};
|
|
}
|
|
macro_rules! block_b {
|
|
() => {{
|
|
c += 100;
|
|
&mut b
|
|
}};
|
|
}
|
|
let res = verify_pred! { block_a!().mutate_and_false(block_b!()) };
|
|
|
|
verify_that!(
|
|
res,
|
|
err(displays_as(contains_substring(indoc! {"
|
|
block_a! ().mutate_and_false(block_b! ()) was false with
|
|
block_a! () = 1,
|
|
block_b! () = 2,
|
|
at"
|
|
})))
|
|
)?;
|
|
|
|
verify_that!((a, b, c), eq((11, 22, 110)))
|
|
}
|
|
|
|
#[test]
|
|
fn values_can_be_insulated_with_parens() -> Result<()> {
|
|
// Not `Copy` and has a consuming method.
|
|
struct Apple;
|
|
impl Apple {
|
|
fn b(self) -> Banana {
|
|
Banana
|
|
}
|
|
}
|
|
#[derive(Debug)]
|
|
struct Banana;
|
|
impl Banana {
|
|
fn c(&self) -> bool {
|
|
false
|
|
}
|
|
}
|
|
|
|
let a = Apple;
|
|
let res = verify_pred!({ a.b() }.c());
|
|
verify_that!(
|
|
res,
|
|
err(displays_as(contains_substring(indoc! {"
|
|
{ a.b() }.c() was false with
|
|
{ a.b() } = Banana,
|
|
at"
|
|
})))
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn binary_operator() -> Result<()> {
|
|
// Add chaining and function calls.
|
|
fn f(x: u32) -> u32 {
|
|
x + 1
|
|
}
|
|
#[derive(Debug)]
|
|
struct Apple;
|
|
impl Apple {
|
|
fn b(&self, y: u32) -> u32 {
|
|
y + 10
|
|
}
|
|
}
|
|
let a = Apple;
|
|
let x = 1;
|
|
let y = 2;
|
|
let res = verify_pred!(f(x) - 1 == a.b(y + 1) + f(y));
|
|
verify_that!(
|
|
res,
|
|
err(displays_as(contains_substring(indoc! {"
|
|
f(x) - 1 == a.b(y + 1) + f(y) was false with
|
|
x = 1,
|
|
f(x) = 2,
|
|
f(x) - 1 = 1,
|
|
a = Apple,
|
|
y + 1 = 3,
|
|
a.b(y + 1) = 13,
|
|
y = 2,
|
|
f(y) = 3,
|
|
a.b(y + 1) + f(y) = 16,
|
|
at"
|
|
})))
|
|
)
|
|
}
|
|
|
|
#[rustversion::before(1.77)]
|
|
#[test]
|
|
fn unary_operator() -> Result<()> {
|
|
#[derive(Debug)]
|
|
struct Apple;
|
|
impl Apple {
|
|
fn b(&self, _b: u32, _c: i32) -> i32 {
|
|
0
|
|
}
|
|
}
|
|
|
|
let a = Apple;
|
|
let b = 1;
|
|
let res = verify_pred!(!a.b(b, -1) == !-2);
|
|
verify_that!(
|
|
res,
|
|
err(displays_as(contains_substring(indoc! {"
|
|
! a.b(b, - 1) ==! - 2 was false with
|
|
a = Apple,
|
|
b = 1,
|
|
a.b(b, - 1) = 0,
|
|
! a.b(b, - 1) = -1,
|
|
! - 2 = 1,
|
|
at"
|
|
})))
|
|
)
|
|
}
|
|
|
|
#[rustversion::since(1.77)]
|
|
#[test]
|
|
fn unary_operator() -> Result<()> {
|
|
#[derive(Debug)]
|
|
struct Apple;
|
|
impl Apple {
|
|
fn b(&self, _b: u32, _c: i32) -> i32 {
|
|
0
|
|
}
|
|
}
|
|
|
|
let a = Apple;
|
|
let b = 1;
|
|
let res = verify_pred!(!a.b(b, -1) == !-2);
|
|
verify_that!(
|
|
res,
|
|
err(displays_as(contains_substring(indoc! {"
|
|
! a.b(b, - 1) == ! - 2 was false with
|
|
a = Apple,
|
|
b = 1,
|
|
a.b(b, - 1) = 0,
|
|
! a.b(b, - 1) = -1,
|
|
! - 2 = 1,
|
|
at"
|
|
})))
|
|
)
|
|
}
|
|
}
|