build(rust): vendor googletest crate
This commit was merged in pull request #76.
This commit is contained in:
1 parent
a6fe84190e
commit
6887b104d6
576 files changed
+284290
-2
No files matched your search
@@ -0,0 +1,155 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use googletest::prelude::*;
|
||||
use googletest::Result;
|
||||
use indoc::indoc;
|
||||
|
||||
#[test]
|
||||
fn matches_any_value_when_list_is_empty() -> Result<()> {
|
||||
verify_that!((), all!())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_value_with_single_matching_component() -> Result<()> {
|
||||
verify_that!(123, all!(eq(123)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn does_not_match_value_with_single_non_matching_component() -> Result<()> {
|
||||
verify_that!(123, not(all!(eq(456))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_value_with_two_matching_components() -> Result<()> {
|
||||
verify_that!("A string", all!(starts_with("A"), ends_with("string")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn does_not_match_value_with_one_non_matching_component_among_two_components() -> Result<()> {
|
||||
verify_that!(123, not(all!(eq(123), eq(456))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn supports_trailing_comma() -> Result<()> {
|
||||
verify_that!(
|
||||
"An important string",
|
||||
all!(starts_with("An"), contains_substring("important"), ends_with("string"),)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admits_matchers_without_static_lifetime() -> Result<()> {
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct AStruct(i32);
|
||||
let expected_value = AStruct(123);
|
||||
verify_that!(AStruct(123), all![eq(&expected_value)])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mismatch_description_two_failed_matchers() -> Result<()> {
|
||||
verify_that!(
|
||||
all!(starts_with("One"), starts_with("Two")).explain_match("Three"),
|
||||
displays_as(eq("* which does not start with \"One\"\n* which does not start with \"Two\""))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mismatch_description_empty_matcher() -> Result<()> {
|
||||
verify_that!(all!().explain_match("Three"), displays_as(eq("which is anything")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_multiple_failed_assertions() -> Result<()> {
|
||||
let result = verify_that!(4, all![eq(1), eq(2), eq(3)]);
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(indoc!(
|
||||
"
|
||||
Value of: 4
|
||||
Expected: has all the following properties:
|
||||
* is equal to 1
|
||||
* is equal to 2
|
||||
* is equal to 3
|
||||
Actual: 4,
|
||||
* which isn't equal to 1
|
||||
* which isn't equal to 2
|
||||
* which isn't equal to 3"
|
||||
))))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn formats_error_message_correctly_when_all_is_inside_some() -> Result<()> {
|
||||
let value = Some(4);
|
||||
let result = verify_that!(value, some(all![eq(1), eq(2), eq(3)]));
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(indoc!(
|
||||
"
|
||||
Value of: value
|
||||
Expected: has a value which has all the following properties:
|
||||
* is equal to 1
|
||||
* is equal to 2
|
||||
* is equal to 3
|
||||
Actual: Some(4),
|
||||
which has a value
|
||||
* which isn't equal to 1
|
||||
* which isn't equal to 2
|
||||
* which isn't equal to 3"
|
||||
))))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn formats_error_message_correctly_when_all_is_inside_ok() -> Result<()> {
|
||||
let value: std::result::Result<i32, std::io::Error> = Ok(4);
|
||||
let result = verify_that!(value, ok(all![eq(&1), eq(&2), eq(&3)]));
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(indoc!(
|
||||
"
|
||||
Value of: value
|
||||
Expected: is a success containing a value, which has all the following properties:
|
||||
* is equal to 1
|
||||
* is equal to 2
|
||||
* is equal to 3
|
||||
Actual: Ok(4),
|
||||
which is a success
|
||||
* which isn't equal to 1
|
||||
* which isn't equal to 2
|
||||
* which isn't equal to 3"
|
||||
))))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn formats_error_message_correctly_when_all_is_inside_err() -> Result<()> {
|
||||
let value: std::result::Result<(), &'static str> = Err("An error");
|
||||
let result = verify_that!(value, err(all![starts_with("Not"), ends_with("problem")]));
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(indoc!(
|
||||
r#"
|
||||
Value of: value
|
||||
Expected: is an error which has all the following properties:
|
||||
* starts with prefix "Not"
|
||||
* ends with suffix "problem"
|
||||
Actual: Err("An error"),
|
||||
which is an error
|
||||
* which does not start with "Not"
|
||||
* which does not end with "problem""#
|
||||
))))
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use googletest::prelude::*;
|
||||
use googletest::Result;
|
||||
use indoc::indoc;
|
||||
|
||||
#[test]
|
||||
fn matches_value_with_single_matching_component() -> Result<()> {
|
||||
verify_that!(123, any!(eq(123)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn does_not_match_value_with_single_non_matching_component() -> Result<()> {
|
||||
verify_that!(123, not(any!(eq(456))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_value_with_first_of_two_matching_components() -> Result<()> {
|
||||
verify_that!("A string", any!(starts_with("A"), starts_with("string")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_value_with_second_of_two_matching_components() -> Result<()> {
|
||||
verify_that!("A string", any!(starts_with("string"), starts_with("A")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn supports_trailing_comma() -> Result<()> {
|
||||
verify_that!(
|
||||
"An important string",
|
||||
any!(starts_with("An"), contains_substring("important"), ends_with("string"),)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn admits_matchers_without_static_lifetime() -> Result<()> {
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct AStruct(i32);
|
||||
let expected_value = AStruct(123);
|
||||
verify_that!(AStruct(123), any![eq(&expected_value)])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mismatch_description_two_failed_matchers() -> Result<()> {
|
||||
verify_that!(
|
||||
any!(starts_with("One"), starts_with("Two")).explain_match("Three"),
|
||||
displays_as(eq("* which does not start with \"One\"\n* which does not start with \"Two\""))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_multiple_failed_assertions() -> Result<()> {
|
||||
let result = verify_that!(4, any![eq(1), eq(2), eq(3)]);
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(indoc!(
|
||||
"
|
||||
Value of: 4
|
||||
Expected: has at least one of the following properties:
|
||||
* is equal to 1
|
||||
* is equal to 2
|
||||
* is equal to 3
|
||||
Actual: 4,
|
||||
* which isn't equal to 1
|
||||
* which isn't equal to 2
|
||||
* which isn't equal to 3"
|
||||
))))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn formats_error_message_correctly_when_any_is_inside_some() -> Result<()> {
|
||||
let value = Some(4);
|
||||
let result = verify_that!(value, some(any![eq(1), eq(2), eq(3)]));
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(indoc!(
|
||||
"
|
||||
Value of: value
|
||||
Expected: has a value which has at least one of the following properties:
|
||||
* is equal to 1
|
||||
* is equal to 2
|
||||
* is equal to 3
|
||||
Actual: Some(4),
|
||||
which has a value
|
||||
* which isn't equal to 1
|
||||
* which isn't equal to 2
|
||||
* which isn't equal to 3"
|
||||
))))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn formats_error_message_correctly_when_any_is_inside_ok() -> Result<()> {
|
||||
let value: std::result::Result<i32, std::io::Error> = Ok(4);
|
||||
let result = verify_that!(value, ok(any![eq(&1), eq(&2), eq(&3)]));
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(indoc!(
|
||||
"
|
||||
Value of: value
|
||||
Expected: is a success containing a value, which has at least one of the following properties:
|
||||
* is equal to 1
|
||||
* is equal to 2
|
||||
* is equal to 3
|
||||
Actual: Ok(4),
|
||||
which is a success
|
||||
* which isn't equal to 1
|
||||
* which isn't equal to 2
|
||||
* which isn't equal to 3"
|
||||
))))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn formats_error_message_correctly_when_any_is_inside_err() -> Result<()> {
|
||||
let value: std::result::Result<(), &'static str> = Err("An error");
|
||||
let result = verify_that!(value, err(any![starts_with("Not"), ends_with("problem")]));
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(indoc!(
|
||||
r#"
|
||||
Value of: value
|
||||
Expected: is an error which has at least one of the following properties:
|
||||
* starts with prefix "Not"
|
||||
* ends with suffix "problem"
|
||||
Actual: Err("An error"),
|
||||
which is an error
|
||||
* which does not start with "Not"
|
||||
* which does not end with "problem""#
|
||||
))))
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,428 @@
|
||||
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"
|
||||
})))
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use googletest::prelude::*;
|
||||
use std::fmt::{Display, Write};
|
||||
|
||||
// Make a long text with each element of the iterator on one line.
|
||||
// `collection` must contains at least one element.
|
||||
fn build_text<T: Display>(mut collection: impl Iterator<Item = T>) -> String {
|
||||
let mut text = String::new();
|
||||
write!(&mut text, "{}", collection.next().expect("Provided collection without elements"))
|
||||
.unwrap();
|
||||
for item in collection {
|
||||
write!(&mut text, "\n{item}").unwrap();
|
||||
}
|
||||
text
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn colors_appear_when_no_color_is_no_set_and_force_color_is_set() -> googletest::Result<()> {
|
||||
std::env::remove_var("NO_COLOR");
|
||||
std::env::set_var("FORCE_COLOR", "1");
|
||||
|
||||
let result = verify_that!(build_text(1..50), eq(&build_text(1..51)));
|
||||
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(
|
||||
"
|
||||
Difference(-\x1B[1;31mactual\x1B[0m / +\x1B[1;32mexpected\x1B[0m):
|
||||
1
|
||||
2
|
||||
\x1B[3m<---- 45 common lines omitted ---->\x1B[0m
|
||||
48
|
||||
49
|
||||
+\x1B[1;32m50\x1B[0m"
|
||||
)))
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use googletest::prelude::*;
|
||||
use googletest::Result;
|
||||
|
||||
#[test]
|
||||
fn all_matcher_works_as_inner_matcher() -> Result<()> {
|
||||
let value = vec![1];
|
||||
verify_that!(value, contains_each![all!(gt(&0), lt(&2))])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_pattern_works_as_inner_matcher() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct(i32);
|
||||
verify_that!(vec![AStruct(123)], contains_each![matches_pattern!(&AStruct(eq(123)))])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_pattern_works_with_property_as_inner_matcher() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct(i32);
|
||||
impl AStruct {
|
||||
fn get_value(&self) -> i32 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
verify_that!(
|
||||
vec![AStruct(123)],
|
||||
contains_each![matches_pattern!(&AStruct {
|
||||
get_value(): eq(123)
|
||||
})]
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_each_works_as_inner_matcher() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct(Vec<i32>);
|
||||
verify_that!(AStruct(vec![123]), matches_pattern!(&AStruct(ref contains_each![eq(&123)])))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pointwise_works_as_inner_matcher() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct(Vec<i32>);
|
||||
verify_that!(AStruct(vec![123]), matches_pattern!(&AStruct(ref pointwise!(eq, [&123]))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn elements_are_works_as_inner_matcher() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct(Vec<i32>);
|
||||
verify_that!(AStruct(vec![123]), matches_pattern!(&AStruct(ref elements_are![eq(&123)])))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_works_as_inner_matcher() -> Result<()> {
|
||||
verify_that!(vec![(123,)], elements_are![(eq(&123),)])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_method_returning_option_of_non_copy_value() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AnInnerStruct;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AStruct;
|
||||
|
||||
impl AStruct {
|
||||
fn get_value(&self) -> Option<AnInnerStruct> {
|
||||
Some(AnInnerStruct)
|
||||
}
|
||||
}
|
||||
|
||||
verify_that!(
|
||||
AStruct,
|
||||
matches_pattern!(&AStruct {
|
||||
get_value(): ref some(matches_pattern!(&AnInnerStruct))
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_method_returning_option_of_non_copy_enum() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnInnerStruct {
|
||||
ThisCase,
|
||||
#[allow(unused)]
|
||||
ThatCase,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct AStruct;
|
||||
impl AStruct {
|
||||
fn get_value(&self) -> Option<AnInnerStruct> {
|
||||
Some(AnInnerStruct::ThisCase)
|
||||
}
|
||||
}
|
||||
|
||||
verify_that!(
|
||||
AStruct,
|
||||
matches_pattern!(&AStruct {
|
||||
get_value(): ref some(matches_pattern!(&AnInnerStruct::ThisCase))
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_method_returning_option_ref_binding_mode() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AnInnerStruct;
|
||||
#[derive(Debug)]
|
||||
struct AStruct;
|
||||
impl AStruct {
|
||||
fn get_value(&self) -> Option<AnInnerStruct> {
|
||||
Some(AnInnerStruct)
|
||||
}
|
||||
}
|
||||
|
||||
verify_that!(
|
||||
AStruct,
|
||||
matches_pattern!(AStruct {
|
||||
get_value(): some(matches_pattern!(AnInnerStruct))
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_method_returning_option_enum_ref_binding_mode() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnInnerStruct {
|
||||
ThisCase,
|
||||
#[allow(unused)]
|
||||
ThatCase,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct AStruct;
|
||||
impl AStruct {
|
||||
fn get_value(&self) -> Option<AnInnerStruct> {
|
||||
Some(AnInnerStruct::ThisCase)
|
||||
}
|
||||
}
|
||||
|
||||
verify_that!(
|
||||
AStruct,
|
||||
matches_pattern!(AStruct {
|
||||
get_value(): some(matches_pattern!(AnInnerStruct::ThisCase))
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_property_against_predicate() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnInnerStruct {
|
||||
ThisCase,
|
||||
#[allow(unused)]
|
||||
ThatCase,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AStruct;
|
||||
impl AStruct {
|
||||
fn get_value(&self) -> AnInnerStruct {
|
||||
AnInnerStruct::ThisCase
|
||||
}
|
||||
}
|
||||
|
||||
verify_that!(
|
||||
AStruct,
|
||||
matches_pattern!(AStruct {
|
||||
get_value(): predicate(|_: &_| true)
|
||||
})
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use googletest::prelude::*;
|
||||
use googletest::Result;
|
||||
use indoc::indoc;
|
||||
|
||||
#[test]
|
||||
fn elements_are_matches_vector() -> Result<()> {
|
||||
let value = vec![1, 2, 3];
|
||||
verify_that!(value, elements_are![eq(&1), eq(&2), eq(&3)])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn elements_are_matches_slice() -> Result<()> {
|
||||
let value = vec![1, 2, 3];
|
||||
let slice = value.as_slice();
|
||||
verify_that!(slice, elements_are![eq(&1), eq(&2), eq(&3)])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn elements_are_matches_array() -> Result<()> {
|
||||
verify_that!([1, 2, 3], elements_are![eq(1), eq(2), eq(3)])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn elements_are_supports_trailing_comma() -> Result<()> {
|
||||
let value = vec![1, 2, 3];
|
||||
verify_that!(value, elements_are![eq(&1), eq(&2), eq(&3),])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn elements_are_returns_no_match_when_expected_and_actual_sizes_differ() -> Result<()> {
|
||||
let value = vec![1, 2];
|
||||
verify_that!(value, not(elements_are![eq(&1), eq(&2), eq(&3)]))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn elements_are_admits_matchers_without_static_lifetime() -> Result<()> {
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct AStruct(i32);
|
||||
let expected_value = AStruct(123);
|
||||
verify_that!(vec![AStruct(123)], elements_are![eq(&expected_value)])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn elements_are_matches_iterator_returning_by_value() -> Result<()> {
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
struct Countdown(i32);
|
||||
impl Iterator for Countdown {
|
||||
type Item = i32;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self.0 {
|
||||
0 => None,
|
||||
x => {
|
||||
self.0 -= 1;
|
||||
Some(x)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
verify_that!(Countdown(3), elements_are![eq(3), eq(2), eq(1)])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn elements_are_produces_correct_failure_message() -> Result<()> {
|
||||
let result = verify_that!(vec![1, 4, 3], elements_are![eq(&1), eq(&2), eq(&3)]);
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(indoc!(
|
||||
"
|
||||
Value of: vec![1, 4, 3]
|
||||
Expected: has elements:
|
||||
0. is equal to 1
|
||||
1. is equal to 2
|
||||
2. is equal to 3
|
||||
Actual: [1, 4, 3],
|
||||
where element #1 is 4, which isn't equal to 2"
|
||||
))))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn elements_are_produces_correct_failure_message_nested() -> Result<()> {
|
||||
let result = verify_that!(
|
||||
vec![vec![0, 1], vec![1, 2]],
|
||||
elements_are![elements_are![eq(&1), eq(&2)], elements_are![eq(&2), eq(&3)]]
|
||||
);
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(indoc!(
|
||||
"
|
||||
Expected: has elements:
|
||||
0. has elements:
|
||||
0. is equal to 1
|
||||
1. is equal to 2
|
||||
1. has elements:
|
||||
0. is equal to 2
|
||||
1. is equal to 3
|
||||
Actual: [[0, 1], [1, 2]],
|
||||
where:
|
||||
* element #0 is [0, 1], where:
|
||||
* element #0 is 0, which isn't equal to 1
|
||||
* element #1 is 1, which isn't equal to 2
|
||||
* element #1 is [1, 2], where:
|
||||
* element #0 is 1, which isn't equal to 2
|
||||
* element #1 is 2, which isn't equal to 3"
|
||||
))))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn elements_are_explain_match_wrong_size() -> Result<()> {
|
||||
let matcher = elements_are![eq(&1)];
|
||||
verify_that!(matcher.explain_match(&vec![1, 2]), displays_as(eq("whose size is 2")))
|
||||
}
|
||||
|
||||
fn create_matcher<'a>() -> impl Matcher<&'a Vec<i32>> {
|
||||
elements_are![eq(&1)]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn elements_are_works_when_matcher_is_created_in_subroutine() -> Result<()> {
|
||||
verify_that!(vec![1], create_matcher())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn elements_are_implicitly_called() -> Result<()> {
|
||||
verify_that!(vec![1, 2, 3], [eq(&1), eq(&2), eq(&3)])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn elements_are_with_auto_eq() -> Result<()> {
|
||||
verify_that!(vec![1, 2, 3], [&1, &2, lt(&43)])
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use googletest::matcher::MatcherResult;
|
||||
use googletest::prelude::*;
|
||||
use googletest::Result;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct IntField {
|
||||
int: i32,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn field_matches_integer_field() -> Result<()> {
|
||||
verify_that!(IntField { int: 32 }, field!(&IntField.int, eq(32)))
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct StringField {
|
||||
strink: String,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn field_matches_string_field() -> Result<()> {
|
||||
verify_that!(
|
||||
StringField { strink: "yes".to_string() },
|
||||
field!(&StringField.strink, ref eq("yes"))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn field_error_message_shows_field_name_and_inner_matcher() -> Result<()> {
|
||||
let matcher = field!(&IntField.int, eq(31));
|
||||
|
||||
verify_that!(
|
||||
matcher.describe(MatcherResult::Match),
|
||||
displays_as(eq("has field `int`, which is equal to 31"))
|
||||
)
|
||||
}
|
||||
|
||||
mod sub {
|
||||
#[derive(Debug)]
|
||||
pub struct SubStruct {
|
||||
pub field: i32,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn struct_in_other_module_matches() -> Result<()> {
|
||||
verify_that!(sub::SubStruct { field: 32 }, field!(&sub::SubStruct.field, eq(32)))
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Tuple(i32, #[allow(unused)] String);
|
||||
|
||||
#[test]
|
||||
fn tuple_matches_with_index() -> Result<()> {
|
||||
verify_that!(Tuple(32, "yes".to_string()), field!(&Tuple.0, eq(32)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_enum_value() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
AValue(u32),
|
||||
}
|
||||
let value = AnEnum::AValue(123);
|
||||
|
||||
verify_that!(value, field!(&AnEnum::AValue.0, eq(123)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shows_correct_failure_message_for_wrong_struct_entry() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct {
|
||||
a: Vec<u32>,
|
||||
}
|
||||
let value = AStruct { a: vec![1] };
|
||||
|
||||
let arr: [u32; 0] = [];
|
||||
let result = verify_that!(value, field!(&AStruct.a, ref container_eq(arr)));
|
||||
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(
|
||||
"which has field `a`, which contains the unexpected element 1"
|
||||
)))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn does_not_match_enum_value_with_wrong_enum_variant() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
#[allow(dead_code)] // This variant is intentionally unused.
|
||||
AValue(u32),
|
||||
AnotherValue,
|
||||
}
|
||||
let value = AnEnum::AnotherValue;
|
||||
|
||||
verify_that!(&value, not(field!(&AnEnum::AValue.0, eq(123))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shows_correct_failure_message_for_wrong_enum_value() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
#[allow(dead_code)] // This variant is intentionally unused.
|
||||
AValue {
|
||||
a: u32,
|
||||
},
|
||||
AnotherValue,
|
||||
}
|
||||
let value = AnEnum::AnotherValue;
|
||||
|
||||
let result = verify_that!(value, field!(&AnEnum::AValue.a, eq(123)));
|
||||
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring("which has the wrong enum variant `AnotherValue`")))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shows_correct_failure_message_for_wrong_enum_value_with_tuple_field() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
#[allow(dead_code)] // This variant is intentionally unused.
|
||||
AValue(u32),
|
||||
#[allow(unused)]
|
||||
AnotherValue(u32),
|
||||
}
|
||||
let value = AnEnum::AnotherValue(123);
|
||||
|
||||
let result = verify_that!(value, field!(&AnEnum::AValue.0, eq(123)));
|
||||
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring("which has the wrong enum variant `AnotherValue`")))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shows_correct_failure_message_for_wrong_enum_value_with_named_field() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
#[allow(dead_code)] // This variant is intentionally unused.
|
||||
AValue(u32),
|
||||
AnotherValue {
|
||||
#[allow(unused)]
|
||||
a: u32,
|
||||
},
|
||||
}
|
||||
let value = AnEnum::AnotherValue { a: 123 };
|
||||
|
||||
let result = verify_that!(value, field!(&AnEnum::AValue.0, eq(123)));
|
||||
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring("which has the wrong enum variant `AnotherValue`")))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_like_enum_value() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
AValue { a_field: u32 },
|
||||
}
|
||||
let value = AnEnum::AValue { a_field: 123 };
|
||||
|
||||
verify_that!(value, field!(&AnEnum::AValue.a_field, eq(123)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_copy_to_copy() -> Result<()> {
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct Strukt {
|
||||
a_field: i32,
|
||||
}
|
||||
|
||||
verify_that!(Strukt { a_field: 32 }, field!(Strukt.a_field, eq(32)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_ref_to_copy() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct Strukt {
|
||||
a_field: i32,
|
||||
}
|
||||
|
||||
verify_that!(Strukt { a_field: 32 }, field!(&Strukt.a_field, eq(32)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_ref_to_ref() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct Strukt {
|
||||
a_field: String,
|
||||
}
|
||||
|
||||
verify_that!(Strukt { a_field: "32".into() }, field!(&Strukt.a_field, ref eq("32")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_copy_to_ref() -> Result<()> {
|
||||
// It is not possible to have a copy struct with non-copy field. Hence, this
|
||||
// test case is not necessary.
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_ref_to_ref_binding_mode() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct Strukt {
|
||||
a_field: String,
|
||||
}
|
||||
|
||||
verify_that!(Strukt { a_field: "32".into() }, field!(Strukt.a_field, eq("32")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_auto_eq() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct Strukt {
|
||||
a_field: String,
|
||||
}
|
||||
|
||||
verify_that!(Strukt { a_field: "32".into() }, field!(Strukt.a_field, "32"))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_enum_with_auto_eq() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum Enum {
|
||||
Str(String),
|
||||
#[allow(unused)]
|
||||
Int(i32),
|
||||
}
|
||||
|
||||
verify_that!(Enum::Str("32".into()), field!(Enum::Str.0, "32"))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_enum_with_auto_eq_with_wrapper() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct Wrapper<I> {
|
||||
wrapped: I,
|
||||
}
|
||||
|
||||
verify_that!(
|
||||
Wrapper { wrapped: Wrapper { wrapped: 23 } },
|
||||
field!(Wrapper.wrapped, field!(Wrapper.wrapped, &23))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn supports_fully_qualified_struct_path() -> Result<()> {
|
||||
// Ensure that the macro expands to the fully-qualified struct path.
|
||||
mod googletest {}
|
||||
|
||||
let value = ::googletest::internal::test_data::TestStruct { value: 10 };
|
||||
verify_that!(value, field!(&::googletest::internal::test_data::TestStruct.value, ref eq(&10)))?;
|
||||
verify_that!(value, field!(&::googletest::internal::test_data::TestStruct.value, eq(10)))?;
|
||||
verify_that!(value, field!(::googletest::internal::test_data::TestStruct.value, eq(&10)))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn supports_generic_struct() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct Struct<S, T> {
|
||||
#[allow(dead_code)] // The property1 field is used only for adding the type parameter.
|
||||
property1: S,
|
||||
property2: T,
|
||||
}
|
||||
|
||||
let value = Struct { property1: 1, property2: 10 };
|
||||
verify_that!(&value, field!(&Struct::<i32, u32>.property2, ref eq(&10)))?;
|
||||
verify_that!(value, field!(&Struct::<i32, u32>.property2, eq(10)))?;
|
||||
verify_that!(value, field!(Struct::<i32, u32>.property2, eq(&10)))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn supports_fully_qualified_generic_struct() -> Result<()> {
|
||||
// Ensure that the macro expands to the fully-qualified struct path.
|
||||
mod googletest {}
|
||||
|
||||
let value = ::googletest::internal::test_data::GenericTestStruct { value: 10 };
|
||||
verify_that!(
|
||||
&value,
|
||||
field!(&::googletest::internal::test_data::GenericTestStruct::<i32>.value, ref eq(&10))
|
||||
)?;
|
||||
verify_that!(
|
||||
value,
|
||||
field!(&::googletest::internal::test_data::GenericTestStruct::<i32>.value, eq(10))
|
||||
)?;
|
||||
verify_that!(
|
||||
value,
|
||||
field!(::googletest::internal::test_data::GenericTestStruct::<i32>.value, eq(&10))
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright 2024 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
mod write_expr_value {
|
||||
use googletest::prelude::*;
|
||||
|
||||
// Converts the formatting call to a `String` for testing.
|
||||
macro_rules! write_expr_value {
|
||||
($expr_str:expr, $expr: expr $(,)?) => {{
|
||||
let mut s = String::new();
|
||||
::googletest::fmt::internal::__googletest__write_expr_value!(s, $expr_str, $expr);
|
||||
s
|
||||
}};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_with_debug_value_references() -> googletest::Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct Foo;
|
||||
let mut val = Foo;
|
||||
|
||||
verify_that!(write_expr_value!("val", val), eq("\n val = Foo,"))?;
|
||||
verify_that!(write_expr_value!("val", &val), eq("\n val = Foo,"))?;
|
||||
verify_that!(write_expr_value!("val", &&val), eq("\n val = Foo,"))?;
|
||||
verify_that!(write_expr_value!("val", &mut val), eq("\n val = Foo,"))?;
|
||||
verify_that!(write_expr_value!("val", &mut &mut val), eq("\n val = Foo,"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_with_non_debug_value_references() -> googletest::Result<()> {
|
||||
struct Foo;
|
||||
let mut val = Foo;
|
||||
|
||||
verify_that!(write_expr_value!("val", val), eq("\n val does not implement Debug,"))?;
|
||||
verify_that!(write_expr_value!("val", &val), eq("\n val does not implement Debug,"))?;
|
||||
verify_that!(write_expr_value!("val", &&val), eq("\n val does not implement Debug,"))?;
|
||||
verify_that!(write_expr_value!("val", &mut val), eq("\n val does not implement Debug,"))?;
|
||||
verify_that!(
|
||||
write_expr_value!("val", &mut &mut val),
|
||||
eq("\n val does not implement Debug,")
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,469 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use googletest::prelude::*;
|
||||
use googletest::Result;
|
||||
use indoc::indoc;
|
||||
|
||||
#[test]
|
||||
fn matches_enum_without_field() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
A,
|
||||
}
|
||||
let actual = AnEnum::A;
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AnEnum::A))?;
|
||||
verify_that!(actual, matches_pattern!(&AnEnum::A,))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_enum_without_field_ref_binding_mode() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
A,
|
||||
}
|
||||
let actual = AnEnum::A;
|
||||
|
||||
verify_that!(actual, matches_pattern!(AnEnum::A))?;
|
||||
verify_that!(actual, matches_pattern!(AnEnum::A,))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_enum_without_field_copy() -> Result<()> {
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum AnEnum {
|
||||
A,
|
||||
}
|
||||
let actual = AnEnum::A;
|
||||
|
||||
verify_that!(actual, matches_pattern!(AnEnum::A))?;
|
||||
verify_that!(actual, matches_pattern!(AnEnum::A,))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generates_correct_failure_output_when_enum_variant_without_field_is_not_matched() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
#[allow(unused)]
|
||||
A,
|
||||
B,
|
||||
}
|
||||
let actual = AnEnum::B;
|
||||
|
||||
let result = verify_that!(actual, matches_pattern!(&AnEnum::A));
|
||||
|
||||
const EXPECTED: &str = "is not & AnEnum :: A";
|
||||
verify_that!(result, err(displays_as(contains_substring(EXPECTED))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generates_correct_failure_output_when_enum_variant_without_field_is_matched() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
A,
|
||||
}
|
||||
let actual = AnEnum::A;
|
||||
|
||||
let result = verify_that!(actual, not(matches_pattern!(&AnEnum::A)));
|
||||
|
||||
const EXPECTED: &str = "is & AnEnum :: A";
|
||||
verify_that!(result, err(displays_as(contains_substring(EXPECTED))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn has_meaningful_assertion_failure_message_when_wrong_enum_variant_is_used() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
#[allow(unused)]
|
||||
A(u32),
|
||||
#[allow(unused)]
|
||||
B(u32),
|
||||
}
|
||||
let actual = AnEnum::A(123);
|
||||
|
||||
let result = verify_that!(actual, matches_pattern!(&AnEnum::B(eq(123))));
|
||||
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(indoc! {"
|
||||
Actual: A(123),
|
||||
which has the wrong enum variant `A`
|
||||
"
|
||||
})))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_enum_struct_non_exhaustive() -> Result<()> {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
Variant1 { a_field: u32, another_field: u32 },
|
||||
}
|
||||
let actual: AnEnum = AnEnum::Variant1 { a_field: 123, another_field: 234 };
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AnEnum::Variant1 { a_field: eq(123), .. }))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_enum_struct_with_all_non_exhaustive_fields() -> Result<()> {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
Variant1 { a: u32, b: u32 },
|
||||
Variant2 { c: u32, d: u32 },
|
||||
}
|
||||
let actual: AnEnum = AnEnum::Variant1 { a: 123, b: 234 };
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AnEnum::Variant1 { .. }))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn has_failure_when_wrong_enum_struct_variant_is_matched_with_all_non_exhaustive_fields(
|
||||
) -> Result<()> {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
Variant1 { a: u32, b: u32 },
|
||||
Variant2 { c: u32, d: u32 },
|
||||
}
|
||||
let actual: AnEnum = AnEnum::Variant1 { a: 123, b: 234 };
|
||||
|
||||
let result = verify_that!(actual, matches_pattern!(&AnEnum::Variant2 { .. }));
|
||||
|
||||
const EXPECTED: &str = indoc!(
|
||||
"
|
||||
Expected: is & AnEnum :: Variant2 { .. }
|
||||
Actual: Variant1 { a: 123, b: 234 },
|
||||
which is not & AnEnum :: Variant2 { .. }
|
||||
"
|
||||
);
|
||||
verify_that!(result, err(displays_as(contains_substring(EXPECTED))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_enum_struct_with_all_wildcard_fields() -> Result<()> {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
Variant1 { a: u32, b: u32 },
|
||||
Variant2 { c: u32, d: u32 },
|
||||
}
|
||||
let actual: AnEnum = AnEnum::Variant1 { a: 123, b: 234 };
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AnEnum::Variant1 { a: _, b: _ }))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn has_failure_when_wrong_enum_struct_variant_is_matched_with_all_wildcard_fields() -> Result<()> {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
Variant1 { a: u32, b: u32 },
|
||||
Variant2 { c: u32, d: u32 },
|
||||
}
|
||||
let actual: AnEnum = AnEnum::Variant1 { a: 123, b: 234 };
|
||||
|
||||
let result = verify_that!(actual, matches_pattern!(&AnEnum::Variant2 { c: _, d: _ }));
|
||||
|
||||
const EXPECTED: &str = indoc!(
|
||||
"
|
||||
Expected: is & AnEnum :: Variant2 { c : _, d : _, }
|
||||
Actual: Variant1 { a: 123, b: 234 },
|
||||
which is not & AnEnum :: Variant2 { c : _, d : _, }
|
||||
"
|
||||
);
|
||||
verify_that!(result, err(displays_as(contains_substring(EXPECTED))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_enum_struct_non_exhaustive_with_wildcard_fields() -> Result<()> {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
Variant1 { a: u32, b: u32 },
|
||||
Variant2 { c: u32, d: u32 },
|
||||
}
|
||||
let actual: AnEnum = AnEnum::Variant1 { a: 123, b: 234 };
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AnEnum::Variant1 { a: _, .. }))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn has_failure_when_wrong_enum_struct_variant_is_matched_non_exhaustive_with_wildcard_fields(
|
||||
) -> Result<()> {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
Variant1 { a: u32, b: u32 },
|
||||
Variant2 { c: u32, d: u32 },
|
||||
}
|
||||
let actual: AnEnum = AnEnum::Variant1 { a: 123, b: 234 };
|
||||
|
||||
let result = verify_that!(actual, matches_pattern!(&AnEnum::Variant2 { c: _, .. }));
|
||||
|
||||
const EXPECTED: &str = indoc!(
|
||||
"
|
||||
Expected: is & AnEnum :: Variant2 { c : _, .. }
|
||||
Actual: Variant1 { a: 123, b: 234 },
|
||||
which is not & AnEnum :: Variant2 { c : _, .. }
|
||||
"
|
||||
);
|
||||
verify_that!(result, err(displays_as(contains_substring(EXPECTED))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_enum_struct_exhaustive_with_multiple_variants() -> Result<()> {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
Variant1 { a_field: u32 },
|
||||
Variant2,
|
||||
}
|
||||
let actual: AnEnum = AnEnum::Variant1 { a_field: 123 };
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AnEnum::Variant1 { a_field: eq(123) }))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_match_pattern_literal() -> Result<()> {
|
||||
let actual = false;
|
||||
#[allow(clippy::redundant_pattern_matching)]
|
||||
verify_that!(actual, matches_pattern!(false))?;
|
||||
#[allow(clippy::redundant_pattern_matching)]
|
||||
verify_that!(actual, matches_pattern!(false,))?;
|
||||
let actual = 1;
|
||||
verify_that!(actual, matches_pattern!(1))?;
|
||||
verify_that!(actual, matches_pattern!(1,))?;
|
||||
let actual = "test";
|
||||
verify_that!(actual, matches_pattern!(&"test"))?;
|
||||
verify_that!(actual, matches_pattern!(&"test",))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn has_failure_when_wrong_enum_variant_is_matched_non_exhaustively() -> Result<()> {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
Variant1(i8),
|
||||
Variant2,
|
||||
}
|
||||
let actual: AnEnum = AnEnum::Variant2;
|
||||
|
||||
let result = verify_that!(actual, matches_pattern!(&AnEnum::Variant1(..)));
|
||||
|
||||
const EXPECTED: &str = indoc!(
|
||||
"
|
||||
Expected: is & AnEnum :: Variant1(..)
|
||||
Actual: Variant2,
|
||||
which is not & AnEnum :: Variant1(..)
|
||||
"
|
||||
);
|
||||
verify_that!(result, err(displays_as(contains_substring(EXPECTED))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn has_failure_when_wrong_enum_variant_is_matched_with_underscore() -> Result<()> {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
Variant1(i8),
|
||||
Variant2,
|
||||
}
|
||||
let actual: AnEnum = AnEnum::Variant2;
|
||||
|
||||
let result = verify_that!(actual, matches_pattern!(&AnEnum::Variant1(_)));
|
||||
|
||||
const EXPECTED: &str = indoc!(
|
||||
"
|
||||
Expected: is & AnEnum :: Variant1(_)
|
||||
Actual: Variant2,
|
||||
which is not & AnEnum :: Variant1(_)
|
||||
"
|
||||
);
|
||||
verify_that!(result, err(displays_as(contains_substring(EXPECTED))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn has_failure_when_wrong_enum_variant_is_matched_with_value() -> Result<()> {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
Variant1(i8),
|
||||
Variant2,
|
||||
}
|
||||
let actual: AnEnum = AnEnum::Variant2;
|
||||
|
||||
let result = verify_that!(actual, matches_pattern!(&AnEnum::Variant1(123)));
|
||||
|
||||
const EXPECTED: &str = indoc!(
|
||||
"
|
||||
Expected: is & AnEnum :: Variant1 which has field `0`, which is equal to 123
|
||||
Actual: Variant2,
|
||||
which has the wrong enum variant `Variant2`
|
||||
"
|
||||
);
|
||||
verify_that!(result, err(displays_as(contains_substring(EXPECTED))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_enum_struct_field_with_mutliple_variants() -> Result<()> {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
Variant1(i8),
|
||||
Variant2,
|
||||
}
|
||||
let actual: AnEnum = AnEnum::Variant2;
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AnEnum::Variant2))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_enum_struct_field_with_multiple_variants_non_exhaustive() -> Result<()> {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
Variant1(i8),
|
||||
Variant2,
|
||||
}
|
||||
let actual: AnEnum = AnEnum::Variant1(123);
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AnEnum::Variant1(..)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_enum_struct_field_with_multiple_variants_with_wildcard() -> Result<()> {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
Variant1(i8),
|
||||
Variant2,
|
||||
}
|
||||
let actual: AnEnum = AnEnum::Variant1(123);
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AnEnum::Variant1(_)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_enum_with_field() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
A(u32),
|
||||
}
|
||||
let actual = AnEnum::A(123);
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AnEnum::A(eq(123))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn does_not_match_wrong_enum_value() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
#[allow(unused)]
|
||||
A(u32),
|
||||
B,
|
||||
}
|
||||
let actual = AnEnum::B;
|
||||
|
||||
verify_that!(actual, not(matches_pattern!(&AnEnum::A(eq(123)))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn includes_enum_variant_in_description_with_field() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
A(u32),
|
||||
}
|
||||
let actual = AnEnum::A(123);
|
||||
|
||||
let result = verify_that!(actual, matches_pattern!(&AnEnum::A(eq(234))));
|
||||
|
||||
const EXPECTED: &str = "Expected: is & AnEnum :: A which has field `0`";
|
||||
verify_that!(result, err(displays_as(contains_substring(EXPECTED))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn includes_enum_variant_in_negative_description_with_field() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
A(u32),
|
||||
}
|
||||
let actual = AnEnum::A(123);
|
||||
|
||||
let result = verify_that!(actual, not(matches_pattern!(&AnEnum::A(eq(123)))));
|
||||
|
||||
const EXPECTED: &str = "Expected: is not & AnEnum :: A which has field `0`, which is equal to";
|
||||
verify_that!(result, err(displays_as(contains_substring(EXPECTED))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn includes_enum_variant_in_description_with_two_fields() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
A(u32, u32),
|
||||
}
|
||||
let actual = AnEnum::A(123, 234);
|
||||
|
||||
let result = verify_that!(actual, matches_pattern!(&AnEnum::A(eq(234), eq(234))));
|
||||
|
||||
const EXPECTED: &str = "Expected: is & AnEnum :: A which has all the following properties";
|
||||
verify_that!(result, err(displays_as(contains_substring(EXPECTED))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn includes_enum_variant_in_description_with_three_fields() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
A(u32, u32, u32),
|
||||
}
|
||||
let actual = AnEnum::A(123, 234, 345);
|
||||
|
||||
let result = verify_that!(actual, matches_pattern!(&AnEnum::A(eq(234), eq(234), eq(345))));
|
||||
|
||||
const EXPECTED: &str = "Expected: is & AnEnum :: A which has all the following properties";
|
||||
verify_that!(result, err(displays_as(contains_substring(EXPECTED))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn includes_enum_variant_in_description_with_named_field() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
A { field: u32 },
|
||||
}
|
||||
let actual = AnEnum::A { field: 123 };
|
||||
|
||||
let result = verify_that!(actual, matches_pattern!(&AnEnum::A { field: eq(234) }));
|
||||
|
||||
const EXPECTED: &str = "Expected: is & AnEnum :: A which has field `field`";
|
||||
verify_that!(result, err(displays_as(contains_substring(EXPECTED))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn includes_enum_variant_in_description_with_two_named_fields() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
enum AnEnum {
|
||||
A { field: u32, another_field: u32 },
|
||||
}
|
||||
let actual = AnEnum::A { field: 123, another_field: 234 };
|
||||
|
||||
let result = verify_that!(
|
||||
actual,
|
||||
matches_pattern!(&AnEnum::A { field: eq(234), another_field: eq(234) })
|
||||
);
|
||||
|
||||
const EXPECTED: &str = "Expected: is & AnEnum :: A which has all the following properties";
|
||||
verify_that!(&result, err(displays_as(contains_substring(EXPECTED))))
|
||||
}
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use googletest::prelude::*;
|
||||
use googletest::Result;
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_a_method_taking_enum_value_parameter_followed_by_field() -> Result<()> {
|
||||
enum AnEnum {
|
||||
AVariant,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AStruct {
|
||||
a_field: u32,
|
||||
another_field: u32,
|
||||
}
|
||||
|
||||
impl AStruct {
|
||||
fn get_field(&self, _value: AnEnum) -> u32 {
|
||||
self.a_field
|
||||
}
|
||||
}
|
||||
let actual = AStruct { a_field: 1, another_field: 2 };
|
||||
|
||||
verify_that!(
|
||||
actual,
|
||||
matches_pattern!(&AStruct { get_field(AnEnum::AVariant): eq(1), another_field: eq(2), .. })
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_a_method_taking_enum_value_param_ret_ref_followed_by_field() -> Result<()> {
|
||||
enum AnEnum {
|
||||
AVariant,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AStruct {
|
||||
a_field: u32,
|
||||
another_field: u32,
|
||||
}
|
||||
|
||||
impl AStruct {
|
||||
fn get_field_ref(&self, _value: AnEnum) -> &u32 {
|
||||
&self.a_field
|
||||
}
|
||||
}
|
||||
let actual = AStruct { a_field: 1, another_field: 2 };
|
||||
|
||||
verify_that!(
|
||||
actual,
|
||||
matches_pattern!(&AStruct {
|
||||
get_field_ref(AnEnum::AVariant): eq(&1),
|
||||
another_field: eq(2),
|
||||
..
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_field_followed_by_method_taking_enum_value_param() -> Result<()> {
|
||||
enum AnEnum {
|
||||
AVariant,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AStruct {
|
||||
a_field: u32,
|
||||
another_field: u32,
|
||||
}
|
||||
|
||||
impl AStruct {
|
||||
fn get_field(&self, _value: AnEnum) -> u32 {
|
||||
self.a_field
|
||||
}
|
||||
}
|
||||
let actual = AStruct { a_field: 1, another_field: 2 };
|
||||
|
||||
verify_that!(
|
||||
actual,
|
||||
matches_pattern!(&AStruct {
|
||||
another_field: eq(2),
|
||||
get_field(AnEnum::AVariant): eq(1),
|
||||
..
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_field_followed_by_method_taking_enum_value_param_ret_ref() -> Result<()> {
|
||||
enum AnEnum {
|
||||
AVariant,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AStruct {
|
||||
a_field: u32,
|
||||
another_field: u32,
|
||||
}
|
||||
|
||||
impl AStruct {
|
||||
fn get_field_ref(&self, _value: AnEnum) -> &u32 {
|
||||
&self.a_field
|
||||
}
|
||||
}
|
||||
let actual = AStruct { a_field: 1, another_field: 2 };
|
||||
|
||||
verify_that!(
|
||||
actual,
|
||||
matches_pattern!(&AStruct {
|
||||
another_field: eq(2),
|
||||
get_field_ref(AnEnum::AVariant): eq(&1),
|
||||
..
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_field_followed_by_method_taking_enum_value_param_followed_by_field(
|
||||
) -> Result<()> {
|
||||
enum AnEnum {
|
||||
AVariant,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AStruct {
|
||||
a_field: u32,
|
||||
another_field: u32,
|
||||
a_third_field: u32,
|
||||
}
|
||||
|
||||
impl AStruct {
|
||||
fn get_field(&self, _value: AnEnum) -> u32 {
|
||||
self.a_field
|
||||
}
|
||||
}
|
||||
let actual = AStruct { a_field: 1, another_field: 2, a_third_field: 3 };
|
||||
|
||||
verify_that!(
|
||||
actual,
|
||||
matches_pattern!(&AStruct {
|
||||
another_field: eq(2),
|
||||
get_field(AnEnum::AVariant): eq(1),
|
||||
a_third_field: eq(3),
|
||||
..
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_field_followed_by_method_taking_enum_value_param_ret_ref_followed_by_field(
|
||||
) -> Result<()> {
|
||||
enum AnEnum {
|
||||
AVariant,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AStruct {
|
||||
a_field: u32,
|
||||
another_field: u32,
|
||||
a_third_field: u32,
|
||||
}
|
||||
|
||||
impl AStruct {
|
||||
fn get_field_ref(&self, _value: AnEnum) -> &u32 {
|
||||
&self.a_field
|
||||
}
|
||||
}
|
||||
let actual = AStruct { a_field: 1, another_field: 2, a_third_field: 3 };
|
||||
|
||||
verify_that!(
|
||||
actual,
|
||||
matches_pattern!(&AStruct {
|
||||
another_field: eq(2),
|
||||
get_field_ref(AnEnum::AVariant): eq(&1),
|
||||
a_third_field: eq(3),
|
||||
..
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_a_method_returning_reference_taking_enum_value_parameter() -> Result<()> {
|
||||
enum AnEnum {
|
||||
AVariant,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AStruct {
|
||||
a_field: u32,
|
||||
}
|
||||
|
||||
impl AStruct {
|
||||
fn get_field_ref(&self, _value: AnEnum) -> &u32 {
|
||||
&self.a_field
|
||||
}
|
||||
}
|
||||
let actual = AStruct { a_field: 1 };
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AStruct { get_field_ref(AnEnum::AVariant): eq(&1) }))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_a_method_taking_enum_value_parameter() -> Result<()> {
|
||||
enum AnEnum {
|
||||
AVariant,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AStruct {
|
||||
a_field: u32,
|
||||
}
|
||||
|
||||
impl AStruct {
|
||||
fn get_a_field(&self, _value: AnEnum) -> u32 {
|
||||
self.a_field
|
||||
}
|
||||
}
|
||||
let actual = AStruct { a_field: 1 };
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AStruct { get_a_field(AnEnum::AVariant): eq(1) }))
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
+237
@@ -0,0 +1,237 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use googletest::prelude::*;
|
||||
use googletest::Result;
|
||||
|
||||
#[test]
|
||||
fn matches_tuple_struct_containing_single_field() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct(u32);
|
||||
let actual = AStruct(123);
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AStruct(eq(123))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_tuple_struct_containing_two_fields() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct(u32, u32);
|
||||
let actual = AStruct(123, 234);
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AStruct(eq(123), eq(234))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_tuple_struct_containing_three_fields() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct(u32, u32, u32);
|
||||
let actual = AStruct(123, 234, 345);
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AStruct(eq(123), eq(234), eq(345))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_tuple_struct_containing_four_fields() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct(u32, u32, u32, u32);
|
||||
let actual = AStruct(123, 234, 345, 456);
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AStruct(eq(123), eq(234), eq(345), eq(456))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_tuple_struct_containing_five_fields() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct(u32, u32, u32, u32, u32);
|
||||
let actual = AStruct(123, 234, 345, 456, 567);
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AStruct(eq(123), eq(234), eq(345), eq(456), eq(567))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_tuple_struct_containing_six_fields() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct(u32, u32, u32, u32, u32, u32);
|
||||
let actual = AStruct(123, 234, 345, 456, 567, 678);
|
||||
|
||||
verify_that!(
|
||||
actual,
|
||||
matches_pattern!(&AStruct(eq(123), eq(234), eq(345), eq(456), eq(567), eq(678)))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_tuple_struct_containing_seven_fields() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct(u32, u32, u32, u32, u32, u32, u32);
|
||||
let actual = AStruct(123, 234, 345, 456, 567, 678, 789);
|
||||
|
||||
verify_that!(
|
||||
actual,
|
||||
matches_pattern!(&AStruct(eq(123), eq(234), eq(345), eq(456), eq(567), eq(678), eq(789)))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_tuple_struct_containing_eight_fields() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct(u32, u32, u32, u32, u32, u32, u32, u32);
|
||||
let actual = AStruct(123, 234, 345, 456, 567, 678, 789, 890);
|
||||
|
||||
verify_that!(
|
||||
actual,
|
||||
matches_pattern!(&AStruct(
|
||||
eq(123),
|
||||
eq(234),
|
||||
eq(345),
|
||||
eq(456),
|
||||
eq(567),
|
||||
eq(678),
|
||||
eq(789),
|
||||
eq(890)
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_tuple_struct_containing_nine_fields() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct(u32, u32, u32, u32, u32, u32, u32, u32, u32);
|
||||
let actual = AStruct(123, 234, 345, 456, 567, 678, 789, 890, 901);
|
||||
|
||||
verify_that!(
|
||||
actual,
|
||||
matches_pattern!(&AStruct(
|
||||
eq(123),
|
||||
eq(234),
|
||||
eq(345),
|
||||
eq(456),
|
||||
eq(567),
|
||||
eq(678),
|
||||
eq(789),
|
||||
eq(890),
|
||||
eq(901)
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_tuple_struct_containing_ten_fields() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct(u32, u32, u32, u32, u32, u32, u32, u32, u32, u32);
|
||||
let actual = AStruct(123, 234, 345, 456, 567, 678, 789, 890, 901, 12);
|
||||
|
||||
verify_that!(
|
||||
actual,
|
||||
matches_pattern!(&AStruct(
|
||||
eq(123),
|
||||
eq(234),
|
||||
eq(345),
|
||||
eq(456),
|
||||
eq(567),
|
||||
eq(678),
|
||||
eq(789),
|
||||
eq(890),
|
||||
eq(901),
|
||||
eq(12)
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_tuple_struct_containing_ten_fields_by_ref() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct(u32, u32, u32, u32, u32, u32, u32, u32, u32, u32);
|
||||
let actual = AStruct(123, 234, 345, 456, 567, 678, 789, 890, 901, 12);
|
||||
|
||||
verify_that!(
|
||||
actual,
|
||||
matches_pattern!(&AStruct(
|
||||
ref eq(&123),
|
||||
ref eq(&234),
|
||||
ref eq(&345),
|
||||
ref eq(&456),
|
||||
ref eq(&567),
|
||||
ref eq(&678),
|
||||
ref eq(&789),
|
||||
ref eq(&890),
|
||||
ref eq(&901),
|
||||
ref eq(&12)
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_tuple_struct_with_trailing_comma() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct(u32);
|
||||
let actual = AStruct(123);
|
||||
|
||||
verify_that!(
|
||||
actual,
|
||||
matches_pattern!(&AStruct(
|
||||
eq(123), // Keep the trailing comma, block reformatting
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_tuple_struct_with_two_fields_and_trailing_comma() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct AStruct(u32, u32);
|
||||
let actual = AStruct(123, 234);
|
||||
|
||||
verify_that!(
|
||||
actual,
|
||||
matches_pattern!(&AStruct(
|
||||
eq(123),
|
||||
eq(234), // Keep the trailing comma, block reformatting
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_tuple_struct_with_interleaved_underscore() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct NonCopy;
|
||||
#[derive(Debug)]
|
||||
struct AStruct(u32, NonCopy, u32);
|
||||
let actual = AStruct(1, NonCopy, 3);
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AStruct(eq(1), _, eq(3))))?;
|
||||
verify_that!(actual, matches_pattern!(AStruct(eq(&1), _, eq(&3))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_tuple_struct_non_exhaustive() -> Result<()> {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
struct AStruct(i32, u32);
|
||||
let actual = AStruct(1, 3);
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AStruct(_, ..)))?;
|
||||
verify_that!(actual, matches_pattern!(AStruct(_, ..)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_generic_tuple_struct_exhaustively() -> Result<()> {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
struct AStruct<T>(T, u32);
|
||||
let actual = AStruct(1, 3);
|
||||
|
||||
verify_that!(actual, matches_pattern!(&AStruct(_, _)))?;
|
||||
verify_that!(actual, matches_pattern!(AStruct(_, _)))
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use googletest::prelude::*;
|
||||
use std::fmt::{Display, Write};
|
||||
|
||||
// Make a long text with each element of the iterator on one line.
|
||||
// `collection` must contains at least one element.
|
||||
fn build_text<T: Display>(mut collection: impl Iterator<Item = T>) -> String {
|
||||
let mut text = String::new();
|
||||
write!(&mut text, "{}", collection.next().expect("Provided collection without elements"))
|
||||
.unwrap();
|
||||
for item in collection {
|
||||
write!(&mut text, "\n{item}").unwrap();
|
||||
}
|
||||
text
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn colors_suppressed_when_both_no_color_and_force_color_are_set() -> googletest::Result<()> {
|
||||
std::env::set_var("NO_COLOR", "1");
|
||||
std::env::set_var("FORCE_COLOR", "1");
|
||||
|
||||
let result = verify_that!(build_text(1..50), eq(&build_text(1..51)));
|
||||
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(
|
||||
"
|
||||
Difference(-actual / +expected):
|
||||
1
|
||||
2
|
||||
<---- 45 common lines omitted ---->
|
||||
48
|
||||
49
|
||||
+50"
|
||||
)))
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2025 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#![no_std]
|
||||
|
||||
/// A simple, no_std function.
|
||||
fn no_std_identity(value: u32) -> u32 {
|
||||
value
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use googletest::prelude::*;
|
||||
|
||||
#[gtest]
|
||||
fn no_std_verify() -> Result<()> {
|
||||
verify_eq!(no_std_identity(42), 42)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[gtest]
|
||||
fn no_std_expect() {
|
||||
expect_eq!(no_std_identity(214), 214)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use googletest::prelude::*;
|
||||
use googletest::Result;
|
||||
use indoc::indoc;
|
||||
|
||||
#[test]
|
||||
fn pointwise_matches_single_element() -> Result<()> {
|
||||
let value = vec![1];
|
||||
verify_that!(value, pointwise!(lt, vec![&2]))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pointwise_matches_two_elements() -> Result<()> {
|
||||
let value = vec![1, 2];
|
||||
verify_that!(value, pointwise!(|x| points_to(lt(x)), vec![2, 3]))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pointwise_matches_iterator_returning_by_value() -> Result<()> {
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
struct Countdown(i32);
|
||||
impl Iterator for Countdown {
|
||||
type Item = i32;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self.0 {
|
||||
0 => None,
|
||||
x => {
|
||||
self.0 -= 1;
|
||||
Some(x)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
verify_that!(Countdown(3), pointwise!(eq, vec![3, 2, 1]))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pointwise_matches_two_elements_with_array() -> Result<()> {
|
||||
let value = vec![1, 2];
|
||||
verify_that!(value, pointwise!(lt, [&2, &3]))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pointwise_matches_two_element_slice() -> Result<()> {
|
||||
let value = vec![1, 2];
|
||||
let slice = value.as_slice();
|
||||
verify_that!(slice, pointwise!(lt, [&2, &3]))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pointwise_does_not_match_value_of_wrong_length() -> Result<()> {
|
||||
let value = vec![1];
|
||||
verify_that!(value, not(pointwise!(lt, vec![&2, &3])))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pointwise_does_not_match_value_not_matching_in_first_position() -> Result<()> {
|
||||
let value = vec![1, 2];
|
||||
verify_that!(value, not(pointwise!(lt, vec![&1, &3])))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pointwise_does_not_match_value_not_matching_in_second_position() -> Result<()> {
|
||||
let value = vec![1, 2];
|
||||
verify_that!(value, not(pointwise!(lt, vec![&2, &2])))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pointwise_allows_qualified_matcher_name() -> Result<()> {
|
||||
mod submodule {
|
||||
pub(super) use super::lt;
|
||||
}
|
||||
let value = vec![1];
|
||||
verify_that!(value, pointwise!(submodule::lt, vec![&2]))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pointwise_returns_mismatch_when_actual_value_has_wrong_length() -> Result<()> {
|
||||
let result = verify_that!(vec![1, 2, 3], pointwise!(eq, vec![&1, &2]));
|
||||
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(indoc!(
|
||||
"
|
||||
Value of: vec![1, 2, 3]
|
||||
Expected: has elements satisfying respectively:
|
||||
0. is equal to 1
|
||||
1. is equal to 2
|
||||
Actual: [1, 2, 3],
|
||||
which has size 3 (expected 2)
|
||||
"
|
||||
))))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pointwise_returns_mismatch_when_actual_value_does_not_match_on_first_item() -> Result<()> {
|
||||
let result = verify_that!(vec![1, 2, 3], pointwise!(eq, vec![&2, &2, &3]));
|
||||
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(indoc!(
|
||||
"
|
||||
Value of: vec![1, 2, 3]
|
||||
Expected: has elements satisfying respectively:
|
||||
0. is equal to 2
|
||||
1. is equal to 2
|
||||
2. is equal to 3
|
||||
Actual: [1, 2, 3],
|
||||
where element #0 is 1, which isn't equal to 2
|
||||
"
|
||||
))))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pointwise_returns_mismatch_when_actual_value_does_not_match_on_second_item() -> Result<()> {
|
||||
let result = verify_that!(vec![1, 2, 3], pointwise!(eq, &vec![1, 3, 3]));
|
||||
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(indoc!(
|
||||
"
|
||||
Value of: vec![1, 2, 3]
|
||||
Expected: has elements satisfying respectively:
|
||||
0. is equal to 1
|
||||
1. is equal to 3
|
||||
2. is equal to 3
|
||||
Actual: [1, 2, 3],
|
||||
where element #1 is 2, which isn't equal to 3
|
||||
"
|
||||
))))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pointwise_returns_mismatch_when_actual_value_does_not_match_on_first_and_second_items(
|
||||
) -> Result<()> {
|
||||
let result = verify_that!(vec![1, 2, 3], pointwise!(eq, &vec![2, 3, 3]));
|
||||
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(indoc!(
|
||||
"
|
||||
Value of: vec![1, 2, 3]
|
||||
Expected: has elements satisfying respectively:
|
||||
0. is equal to 2
|
||||
1. is equal to 3
|
||||
2. is equal to 3
|
||||
Actual: [1, 2, 3],
|
||||
where:
|
||||
* element #0 is 1, which isn't equal to 2
|
||||
* element #1 is 2, which isn't equal to 3"
|
||||
))))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pointwise_matches_single_element_with_lambda_expression_with_extra_value() -> Result<()> {
|
||||
let value = [1.00001f32];
|
||||
verify_that!(value, pointwise!(|v| near(v, 0.0001), vec![1.0]))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pointwise_matches_single_element_with_two_containers() -> Result<()> {
|
||||
let value = [1.00001f32];
|
||||
verify_that!(value, pointwise!(near, vec![1.0], vec![0.0001]))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pointwise_matches_single_element_with_three_containers() -> Result<()> {
|
||||
let value = [1.00001f32];
|
||||
verify_that!(
|
||||
value,
|
||||
pointwise!(|v, t, u| near(v, t + u), vec![1.0f32], vec![0.0001f32], vec![0.5f32])
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,396 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use googletest::matcher::MatcherResult;
|
||||
use googletest::prelude::*;
|
||||
use googletest::Result;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SomeStruct {
|
||||
a_property: u32,
|
||||
}
|
||||
|
||||
impl SomeStruct {
|
||||
fn get_property(&self) -> u32 {
|
||||
self.a_property
|
||||
}
|
||||
|
||||
fn get_property_ref(&self) -> &u32 {
|
||||
&self.a_property
|
||||
}
|
||||
|
||||
fn add_product_to_field(&self, a: u32, b: u32) -> u32 {
|
||||
self.a_property + a * b
|
||||
}
|
||||
|
||||
fn get_property_ref_with_params(&self, _a: u32, _b: u32) -> &u32 {
|
||||
&self.a_property
|
||||
}
|
||||
|
||||
fn generic_method<U, V>(&self, _a: U, _b: V) -> u32 {
|
||||
self.a_property
|
||||
}
|
||||
|
||||
fn generic_method_ref<U, V>(&self, _a: U, _b: V) -> &u32 {
|
||||
&self.a_property
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_matching_property() -> Result<()> {
|
||||
let value = SomeStruct { a_property: 10 };
|
||||
verify_that!(value, property!(&SomeStruct.get_property(), eq(10)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_matching_property_with_parameters() -> Result<()> {
|
||||
let value = SomeStruct { a_property: 10 };
|
||||
verify_that!(value, property!(&SomeStruct.add_product_to_field(2, 3), eq(16)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_matching_property_with_parameters_with_trailing_comma() -> Result<()> {
|
||||
let value = SomeStruct { a_property: 10 };
|
||||
verify_that!(value, property!(&SomeStruct.add_product_to_field(2, 3,), eq(16)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_matching_property_ref() -> Result<()> {
|
||||
let value = SomeStruct { a_property: 10 };
|
||||
verify_that!(value, property!(&SomeStruct.get_property_ref(), eq(&10)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_matching_string_reference_property() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct StructWithString {
|
||||
property: String,
|
||||
}
|
||||
impl StructWithString {
|
||||
fn get_property_ref(&self) -> &String {
|
||||
&self.property
|
||||
}
|
||||
}
|
||||
let value = StructWithString { property: "Something".into() };
|
||||
verify_that!(value, property!(&StructWithString.get_property_ref(), eq("Something")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_matching_slice_property() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct StructWithVec {
|
||||
property: Vec<u32>,
|
||||
}
|
||||
impl StructWithVec {
|
||||
fn get_property_ref(&self) -> &[u32] {
|
||||
&self.property
|
||||
}
|
||||
}
|
||||
let value = StructWithVec { property: vec![1, 2, 3] };
|
||||
verify_that!(value, property!(&StructWithVec.get_property_ref(), eq([1, 2, 3])))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_matching_property_ref_with_parameters() -> Result<()> {
|
||||
let value = SomeStruct { a_property: 10 };
|
||||
verify_that!(value, property!(&SomeStruct.get_property_ref_with_params(2, 3), eq(&10)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_struct_with_matching_property_ref_with_parameters_and_trailing_comma() -> Result<()> {
|
||||
let value = SomeStruct { a_property: 10 };
|
||||
verify_that!(value, property!(&SomeStruct.get_property_ref_with_params(2, 3,), eq(&10)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn does_not_match_struct_with_non_matching_property() -> Result<()> {
|
||||
let value = SomeStruct { a_property: 2 };
|
||||
verify_that!(value, not(property!(&SomeStruct.get_property(), eq(1))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn supports_fully_qualified_struct_path() -> Result<()> {
|
||||
// Ensure that the macro expands to the fully-qualified struct path.
|
||||
mod googletest {}
|
||||
|
||||
let value = ::googletest::internal::test_data::TestStruct { value: 10 };
|
||||
verify_that!(
|
||||
value,
|
||||
property!(::googletest::internal::test_data::TestStruct.get_value(), eq(&10))
|
||||
)?;
|
||||
verify_that!(
|
||||
value,
|
||||
property!(&::googletest::internal::test_data::TestStruct.get_value(), eq(10))
|
||||
)?;
|
||||
verify_that!(
|
||||
value,
|
||||
property!(&::googletest::internal::test_data::TestStruct.get_value(), ref eq(&10))
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn supports_generic_struct_matches() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct GenericStruct<S, T> {
|
||||
#[allow(dead_code)] // The property1 field is used only for adding the type parameter.
|
||||
property1: S,
|
||||
property2: T,
|
||||
}
|
||||
|
||||
impl<S, T: Copy> GenericStruct<S, T> {
|
||||
fn get_property(&self) -> T {
|
||||
self.property2
|
||||
}
|
||||
|
||||
fn get_property_ref(&self) -> &T {
|
||||
&self.property2
|
||||
}
|
||||
}
|
||||
|
||||
let value = GenericStruct { property1: 1, property2: 10 };
|
||||
verify_that!(value, property!(GenericStruct::<i32, u32>.get_property(), eq(&10)))?;
|
||||
verify_that!(value, property!(&GenericStruct::<i32, u32>.get_property(), eq(10)))?;
|
||||
verify_that!(value, property!(&GenericStruct::<i32, u32>.get_property(), ref eq(&10)))?;
|
||||
verify_that!(value, property!(&GenericStruct::<i32, u32>.get_property_ref(), eq(&10)))?;
|
||||
verify_that!(value, property!(&GenericStruct::<i32, u32>.get_property_ref(), ref eq(&&10)))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn supports_generic_method_matches() -> Result<()> {
|
||||
let value = SomeStruct { a_property: 10 };
|
||||
verify_that!(value, property!(SomeStruct.generic_method::<i32, i16>(1, 2), eq(&10)))?;
|
||||
verify_that!(value, property!(&SomeStruct.generic_method::<i32, i16>(1, 2), eq(10)))?;
|
||||
verify_that!(value, property!(&SomeStruct.generic_method::<i32, i16>(1, 2), ref eq(&10)))?;
|
||||
verify_that!(value, property!(&SomeStruct.generic_method_ref::<i32, i16>(1, 2), eq(&10)))?;
|
||||
verify_that!(value, property!(&SomeStruct.generic_method_ref::<i32, i16>(1, 2), ref eq(&&10)))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn supports_fully_qualified_generic_struct_path() -> Result<()> {
|
||||
// Ensure that the macro expands to the fully-qualified struct path.
|
||||
mod googletest {}
|
||||
|
||||
let value = ::googletest::internal::test_data::GenericTestStruct { value: 1 };
|
||||
verify_that!(
|
||||
value,
|
||||
property!(
|
||||
::googletest::internal::test_data::GenericTestStruct::<i32>.get_value::<i16>(10),
|
||||
eq(&10)
|
||||
)
|
||||
)?;
|
||||
verify_that!(
|
||||
value,
|
||||
property!(
|
||||
&::googletest::internal::test_data::GenericTestStruct::<i32>.get_value::<i16>(10),
|
||||
eq(10)
|
||||
)
|
||||
)?;
|
||||
verify_that!(
|
||||
value,
|
||||
property!(
|
||||
&::googletest::internal::test_data::GenericTestStruct::<i32>.get_value::<i16>(10),
|
||||
ref eq(&10))
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn describes_itself_in_matching_case() -> Result<()> {
|
||||
verify_that!(
|
||||
property!(&SomeStruct.get_property(), eq(1)).describe(MatcherResult::Match),
|
||||
displays_as(eq("has property `get_property()`, which is equal to 1"))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn describes_itself_in_not_matching_case() -> Result<()> {
|
||||
verify_that!(
|
||||
property!(&SomeStruct.get_property(), eq(1)).describe(MatcherResult::NoMatch),
|
||||
displays_as(eq("has property `get_property()`, which isn't equal to 1"))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn explains_mismatch_referencing_explanation_of_inner_matcher() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct SomeStruct;
|
||||
|
||||
impl SomeStruct {
|
||||
fn get_a_collection(&self) -> Vec<u32> {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
let value = SomeStruct;
|
||||
let result =
|
||||
verify_that!(value, property!(&SomeStruct.get_a_collection(), ref container_eq([1])));
|
||||
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(
|
||||
"whose property `get_a_collection()` is `[]`, which is missing the element 1"
|
||||
)))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn explains_mismatch_referencing_explanation_of_inner_matcher_binding_mode() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct SomeStruct;
|
||||
impl SomeStruct {
|
||||
fn get_a_collection(&self) -> Vec<u32> {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
let result =
|
||||
verify_that!(SomeStruct, property!(SomeStruct.get_a_collection(), container_eq([1])));
|
||||
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(
|
||||
"whose property `get_a_collection()` is `[]`, which is missing the element 1"
|
||||
)))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn describes_itself_in_matching_case_for_ref() -> Result<()> {
|
||||
verify_that!(
|
||||
property!(&SomeStruct.get_property_ref(), eq(&1)).describe(MatcherResult::Match),
|
||||
displays_as(eq("has property `get_property_ref()`, which is equal to 1"))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn describes_itself_in_not_matching_case_for_ref() -> Result<()> {
|
||||
verify_that!(
|
||||
property!(&SomeStruct.get_property_ref(), eq(&1)).describe(MatcherResult::NoMatch),
|
||||
displays_as(eq("has property `get_property_ref()`, which isn't equal to 1"))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn explains_mismatch_referencing_explanation_of_inner_matcher_for_ref() -> Result<()> {
|
||||
static EMPTY_COLLECTION: Vec<u32> = vec![];
|
||||
#[derive(Debug)]
|
||||
struct SomeStruct;
|
||||
impl SomeStruct {
|
||||
fn get_a_collection_ref(&self) -> &[u32] {
|
||||
&EMPTY_COLLECTION
|
||||
}
|
||||
}
|
||||
let value = SomeStruct;
|
||||
let result =
|
||||
verify_that!(value, property!(&SomeStruct.get_a_collection_ref(), container_eq([1])));
|
||||
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(
|
||||
"whose property `get_a_collection_ref()` is `[]`, which is missing the element 1"
|
||||
)))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_copy_to_copy() -> Result<()> {
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct Struct;
|
||||
impl Struct {
|
||||
fn property(self) -> i32 {
|
||||
32
|
||||
}
|
||||
}
|
||||
|
||||
verify_that!(Struct, property!(Struct.property(), eq(32)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_copy_to_ref() -> Result<()> {
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct Struct;
|
||||
impl Struct {
|
||||
fn property(self) -> String {
|
||||
"something".into()
|
||||
}
|
||||
}
|
||||
|
||||
verify_that!(Struct, property!(Struct.property(), ref eq("something")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_copy_but_by_ref() -> Result<()> {
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct Struct;
|
||||
impl Struct {
|
||||
fn property(&self) -> String {
|
||||
"something".into()
|
||||
}
|
||||
}
|
||||
|
||||
verify_that!(&Struct, property!(&Struct.property(), ref eq("something")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_ref_to_ref() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct Struct;
|
||||
impl Struct {
|
||||
fn property(&self) -> String {
|
||||
"something".into()
|
||||
}
|
||||
}
|
||||
|
||||
verify_that!(Struct, property!(&Struct.property(), ref eq("something")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_ref_to_copy() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct Struct;
|
||||
impl Struct {
|
||||
fn property(&self) -> i32 {
|
||||
32
|
||||
}
|
||||
}
|
||||
|
||||
verify_that!(Struct, property!(&Struct.property(), eq(32)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_ref_to_ref_with_binding_mode() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct Struct;
|
||||
impl Struct {
|
||||
fn property(&self) -> String {
|
||||
"something".into()
|
||||
}
|
||||
}
|
||||
|
||||
verify_that!(Struct, property!(Struct.property(), eq("something")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_property_auto_eq() -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct Struct;
|
||||
impl Struct {
|
||||
fn property(&self) -> String {
|
||||
"something".into()
|
||||
}
|
||||
}
|
||||
|
||||
verify_that!(Struct, property!(Struct.property(), "something"))
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#![cfg(feature = "proptest")]
|
||||
|
||||
use googletest::prelude::*;
|
||||
use proptest::test_runner::{Config, TestRunner};
|
||||
|
||||
#[test]
|
||||
fn numbers_are_greater_than_zero() -> Result<()> {
|
||||
let mut runner = TestRunner::new(Config::default());
|
||||
runner.run(&(1..100i32), |v| Ok(verify_that!(v, gt(0))?)).or_fail()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn strings_are_nonempty() -> Result<()> {
|
||||
let mut runner = TestRunner::new(Config::default());
|
||||
runner.run(&"[a-zA-Z0-9]+", |v| Ok(verify_that!(v, not(eq("")))?)).or_fail()
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright 2025 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ArenaHolder<'a, T: ?Sized> {
|
||||
value: &'a T,
|
||||
}
|
||||
|
||||
impl<'a, T: PartialEq + ?Sized> PartialEq<T> for ArenaHolder<'a, T> {
|
||||
fn eq(&self, other: &T) -> bool {
|
||||
self.value == other
|
||||
}
|
||||
}
|
||||
|
||||
struct Strukt {
|
||||
a_field: String,
|
||||
}
|
||||
|
||||
impl<'a> ArenaHolder<'a, Strukt> {
|
||||
fn get_a_field(&self) -> ArenaHolder<'_, str> {
|
||||
ArenaHolder { value: &self.value.a_field }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use googletest::prelude::*;
|
||||
|
||||
#[gtest]
|
||||
fn test() {
|
||||
let arena = [Strukt { a_field: "hello".into() }];
|
||||
|
||||
let holder = ArenaHolder { value: &arena[0] };
|
||||
|
||||
let inner_holder = holder.get_a_field();
|
||||
|
||||
expect_that!(inner_holder, eq("hello"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
Google Test trace:
|
||||
scoped_trace_panic_test.rs:24: Inner trace
|
||||
scoped_trace_panic_test.rs:22: Outer trace
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2026 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use googletest::internal::test_outcome::TestOutcome;
|
||||
use googletest::prelude::*;
|
||||
|
||||
fn main() {
|
||||
// Initialize the panic hook to capture and print scoped traces on panic.
|
||||
TestOutcome::init_current_test_outcome();
|
||||
|
||||
scoped_trace!("Outer trace");
|
||||
{
|
||||
scoped_trace!("Inner trace");
|
||||
panic!("Intentional panic");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
# fail on error
|
||||
set -e
|
||||
|
||||
# Read binary path from argument
|
||||
BINARY_PATH="$1"
|
||||
|
||||
if [ -z "$BINARY_PATH" ]; then
|
||||
echo "Usage: $0 <binary_path>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Run the binary, capture output, and process with sed
|
||||
# We ignore the failure of the binary as per the original genrule (|| true)
|
||||
( "${BINARY_PATH}" 2>&1 || true ) | \
|
||||
sed -n -e '/^Google Test trace:/p' -e '/^ .*trace/p' | \
|
||||
sed 's#^.*scoped_trace_panic_test.rs# scoped_trace_panic_test.rs#g'
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright 2026 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use googletest::internal::scoped_trace::get_scoped_traces;
|
||||
use googletest::prelude::*;
|
||||
|
||||
#[gtest]
|
||||
fn test_scoped_trace_non_fatal() -> googletest::Result<()> {
|
||||
let result = {
|
||||
scoped_trace!("First trace");
|
||||
verify_eq!(1, 2)
|
||||
};
|
||||
|
||||
verify_that!(result, err(displays_as(contains_substring("First trace"))))?;
|
||||
|
||||
verify_that!(result, err(displays_as(contains_substring("Google Test trace:"))))
|
||||
}
|
||||
|
||||
#[gtest]
|
||||
fn test_scoped_trace_nesting() {
|
||||
scoped_trace!("Outer trace");
|
||||
{
|
||||
scoped_trace!("Inner trace");
|
||||
let traces = get_scoped_traces();
|
||||
assert_eq!(traces.len(), 2);
|
||||
assert_eq!(traces[0].message, "Outer trace");
|
||||
assert_eq!(traces[1].message, "Inner trace");
|
||||
}
|
||||
let traces = get_scoped_traces();
|
||||
assert_eq!(traces.len(), 1);
|
||||
assert_eq!(traces[0].message, "Outer trace");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use googletest::matcher::MatcherResult;
|
||||
use googletest::prelude::*;
|
||||
use googletest::Result;
|
||||
use indoc::indoc;
|
||||
|
||||
#[test]
|
||||
fn empty_matcher_matches_empty_tuple() -> Result<()> {
|
||||
verify_that!((), ())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_matcher_matches_empty_tuple_reference() -> Result<()> {
|
||||
let a_ok: std::result::Result<(), String> = Ok(()); // Non copy
|
||||
verify_that!(a_ok, ok(()))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn singleton_matcher_matches_matching_singleton_tuple() -> Result<()> {
|
||||
verify_that!((123,), (eq(123),))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn singleton_matcher_does_not_match_non_matching_singleton_tuple() -> Result<()> {
|
||||
verify_that!((123,), not((eq(456),)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pair_matcher_matches_matching_pair_tuple() -> Result<()> {
|
||||
verify_that!((123, 456), (eq(123), eq(456)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pair_matcher_matches_matching_pair_tuple_with_different_types() -> Result<()> {
|
||||
verify_that!((123, "A string"), (eq(123), eq("A string")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pair_matcher_with_trailing_comma_matches_matching_pair_tuple() -> Result<()> {
|
||||
verify_that!((123, 456), (eq(123), eq(456),))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_matches_matching_3_tuple() -> Result<()> {
|
||||
verify_that!((1, 2, 3), (eq(1), eq(2), eq(3)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_matches_matching_4_tuple() -> Result<()> {
|
||||
verify_that!((1, 2, 3, 4), (eq(1), eq(2), eq(3), eq(4)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_matches_matching_5_tuple() -> Result<()> {
|
||||
verify_that!((1, 2, 3, 4, 5), (eq(1), eq(2), eq(3), eq(4), eq(5)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_matches_matching_6_tuple() -> Result<()> {
|
||||
verify_that!((1, 2, 3, 4, 5, 6), (eq(1), eq(2), eq(3), eq(4), eq(5), eq(6)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_matches_matching_7_tuple() -> Result<()> {
|
||||
verify_that!((1, 2, 3, 4, 5, 6, 7), (eq(1), eq(2), eq(3), eq(4), eq(5), eq(6), eq(7)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_matches_matching_8_tuple() -> Result<()> {
|
||||
verify_that!((1, 2, 3, 4, 5, 6, 7, 8), (eq(1), eq(2), eq(3), eq(4), eq(5), eq(6), eq(7), eq(8)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_matches_matching_9_tuple() -> Result<()> {
|
||||
verify_that!(
|
||||
(1, 2, 3, 4, 5, 6, 7, 8, 9),
|
||||
(eq(1), eq(2), eq(3), eq(4), eq(5), eq(6), eq(7), eq(8), eq(9))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_matches_matching_10_tuple() -> Result<()> {
|
||||
verify_that!(
|
||||
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
|
||||
(eq(1), eq(2), eq(3), eq(4), eq(5), eq(6), eq(7), eq(8), eq(9), eq(10))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_matches_matching_11_tuple() -> Result<()> {
|
||||
verify_that!(
|
||||
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11),
|
||||
(eq(1), eq(2), eq(3), eq(4), eq(5), eq(6), eq(7), eq(8), eq(9), eq(10), eq(11))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_matches_matching_12_tuple() -> Result<()> {
|
||||
verify_that!(
|
||||
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12),
|
||||
(eq(1), eq(2), eq(3), eq(4), eq(5), eq(6), eq(7), eq(8), eq(9), eq(10), eq(11), eq(12))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_with_trailing_comma_matches_matching_3_tuple() -> Result<()> {
|
||||
verify_that!((1, 2, 3), (eq(1), eq(2), eq(3),))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_with_trailing_comma_matches_matching_4_tuple() -> Result<()> {
|
||||
verify_that!((1, 2, 3, 4), (eq(1), eq(2), eq(3), eq(4),))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_with_trailing_comma_matches_matching_5_tuple() -> Result<()> {
|
||||
verify_that!((1, 2, 3, 4, 5), (eq(1), eq(2), eq(3), eq(4), eq(5),))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_with_trailing_comma_matches_matching_6_tuple() -> Result<()> {
|
||||
verify_that!((1, 2, 3, 4, 5, 6), (eq(1), eq(2), eq(3), eq(4), eq(5), eq(6),))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_with_trailing_comma_matches_matching_7_tuple() -> Result<()> {
|
||||
verify_that!((1, 2, 3, 4, 5, 6, 7), (eq(1), eq(2), eq(3), eq(4), eq(5), eq(6), eq(7),))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_with_trailing_comma_matches_matching_8_tuple() -> Result<()> {
|
||||
verify_that!(
|
||||
(1, 2, 3, 4, 5, 6, 7, 8),
|
||||
(eq(1), eq(2), eq(3), eq(4), eq(5), eq(6), eq(7), eq(8),)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_with_trailing_comma_matches_matching_9_tuple() -> Result<()> {
|
||||
verify_that!(
|
||||
(1, 2, 3, 4, 5, 6, 7, 8, 9),
|
||||
(eq(1), eq(2), eq(3), eq(4), eq(5), eq(6), eq(7), eq(8), eq(9),)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_with_trailing_comma_matches_matching_10_tuple() -> Result<()> {
|
||||
verify_that!(
|
||||
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
|
||||
(eq(1), eq(2), eq(3), eq(4), eq(5), eq(6), eq(7), eq(8), eq(9), eq(10),)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_with_trailing_comma_matches_matching_11_tuple() -> Result<()> {
|
||||
verify_that!(
|
||||
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11),
|
||||
(eq(1), eq(2), eq(3), eq(4), eq(5), eq(6), eq(7), eq(8), eq(9), eq(10), eq(11),)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_with_trailing_comma_matches_matching_12_tuple() -> Result<()> {
|
||||
verify_that!(
|
||||
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12),
|
||||
(eq(1), eq(2), eq(3), eq(4), eq(5), eq(6), eq(7), eq(8), eq(9), eq(10), eq(11), eq(12),)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_1_has_correct_description_for_match() -> Result<()> {
|
||||
verify_that!(
|
||||
Matcher::<(i32,)>::describe(&(eq(1),), MatcherResult::Match),
|
||||
displays_as(eq(indoc!(
|
||||
"
|
||||
is a tuple whose values respectively match:
|
||||
is equal to 1"
|
||||
)))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_1_has_correct_description_for_mismatch() -> Result<()> {
|
||||
verify_that!(
|
||||
Matcher::<(i32,)>::describe(&(eq(1),), MatcherResult::NoMatch),
|
||||
displays_as(eq(indoc!(
|
||||
"
|
||||
is a tuple whose values do not respectively match:
|
||||
is equal to 1"
|
||||
)))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_2_has_correct_description_for_match() -> Result<()> {
|
||||
verify_that!(
|
||||
Matcher::<(i32, i32)>::describe(&(eq(1), eq(2)), MatcherResult::Match),
|
||||
displays_as(eq(indoc!(
|
||||
"
|
||||
is a tuple whose values respectively match:
|
||||
is equal to 1
|
||||
is equal to 2"
|
||||
)))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_matcher_2_has_correct_description_for_mismatch() -> Result<()> {
|
||||
verify_that!(
|
||||
Matcher::<(i32, i32)>::describe(&(eq(1), eq(2)), MatcherResult::NoMatch),
|
||||
displays_as(eq(indoc!(
|
||||
"
|
||||
is a tuple whose values do not respectively match:
|
||||
is equal to 1
|
||||
is equal to 2"
|
||||
)))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn describe_match_shows_which_tuple_element_did_not_match() -> Result<()> {
|
||||
verify_that!(
|
||||
(eq(1), eq(2)).explain_match((1, 3)),
|
||||
displays_as(eq(indoc!(
|
||||
"
|
||||
which
|
||||
is a tuple whose values do not respectively match:
|
||||
is equal to 1
|
||||
is equal to 2
|
||||
Element #1 is 3,
|
||||
which isn't equal to 2"
|
||||
)))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn describe_match_shows_which_two_tuple_elements_did_not_match() -> Result<()> {
|
||||
verify_that!(
|
||||
(eq(1), eq(2)).explain_match((2, 3)),
|
||||
displays_as(eq(indoc!(
|
||||
"
|
||||
which
|
||||
is a tuple whose values do not respectively match:
|
||||
is equal to 1
|
||||
is equal to 2
|
||||
Element #0 is 2,
|
||||
which isn't equal to 1
|
||||
Element #1 is 3,
|
||||
which isn't equal to 2"
|
||||
)))
|
||||
)
|
||||
}
|
||||
+466
@@ -0,0 +1,466 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use googletest::prelude::*;
|
||||
use googletest::Result;
|
||||
use indoc::indoc;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_matches_empty_vector() -> Result<()> {
|
||||
let value: Vec<u32> = vec![];
|
||||
verify_that!(value, unordered_elements_are![])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_matches_empty_vector_with_trailing_comma() -> Result<()> {
|
||||
let value: Vec<u32> = vec![];
|
||||
verify_that!(value, unordered_elements_are![,])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_matches_vector() -> Result<()> {
|
||||
let value = vec![1, 2, 3];
|
||||
verify_that!(value, unordered_elements_are![eq(&1), eq(&2), eq(&3)])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_matches_iterator_returning_by_value() -> Result<()> {
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
struct Countdown(i32);
|
||||
impl Iterator for Countdown {
|
||||
type Item = i32;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self.0 {
|
||||
0 => None,
|
||||
x => {
|
||||
self.0 -= 1;
|
||||
Some(x)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
verify_that!(Countdown(3), unordered_elements_are![eq(1), eq(2), eq(3)])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_omitted() -> Result<()> {
|
||||
let value = vec![1, 2, 3];
|
||||
verify_that!(value, {eq(&3), eq(&2), eq(&1)})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_matches_slice() -> Result<()> {
|
||||
let value = vec![1, 2, 3];
|
||||
let slice = value.as_slice();
|
||||
verify_that!(slice, unordered_elements_are![eq(&1), eq(&2), eq(&3)])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_matches_hash_map() -> Result<()> {
|
||||
let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two"), (3, "Three")]);
|
||||
verify_that!(
|
||||
value,
|
||||
unordered_elements_are![(eq(&2), eq(&"Two")), (eq(&1), eq(&"One")), (eq(&3), eq(&"Three"))]
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_matches_hash_map_with_trailing_comma() -> Result<()> {
|
||||
let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two"), (3, "Three")]);
|
||||
verify_that!(
|
||||
value,
|
||||
unordered_elements_are![(eq(&2), eq(&"Two")), (eq(&1), eq(&"One")), (eq(&3), eq(&"Three")),]
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_does_not_match_hash_map_with_wrong_key() -> Result<()> {
|
||||
let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two"), (4, "Three")]);
|
||||
verify_that!(
|
||||
value,
|
||||
not(unordered_elements_are![
|
||||
(eq(&2), eq(&"Two")),
|
||||
(eq(&1), eq(&"One")),
|
||||
(eq(&3), eq(&"Three"))
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_does_not_match_hash_map_with_wrong_value() -> Result<()> {
|
||||
let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two"), (3, "Four")]);
|
||||
verify_that!(
|
||||
value,
|
||||
not(unordered_elements_are![
|
||||
(eq(&2), eq(&"Two")),
|
||||
(eq(&1), eq(&"One")),
|
||||
(eq(&3), eq(&"Three"))
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_does_not_match_hash_map_missing_element() -> Result<()> {
|
||||
let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two")]);
|
||||
verify_that!(
|
||||
value,
|
||||
not(unordered_elements_are![
|
||||
(eq(&2), eq(&"Two")),
|
||||
(eq(&1), eq(&"One")),
|
||||
(eq(&3), eq(&"Three"))
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_does_not_match_hash_map_with_extra_element() -> Result<()> {
|
||||
let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two"), (3, "Three")]);
|
||||
verify_that!(value, not(unordered_elements_are![(eq(&2), eq(&"Two")), (eq(&1), eq(&"One"))]))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_does_not_match_hash_map_with_mismatched_key_and_value() -> Result<()> {
|
||||
let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Three"), (3, "Two")]);
|
||||
verify_that!(
|
||||
value,
|
||||
not(unordered_elements_are![
|
||||
(eq(&2), eq(&"Two")),
|
||||
(eq(&1), eq(&"One")),
|
||||
(eq(&3), eq(&"Three"))
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_matches_vector_with_trailing_comma() -> Result<()> {
|
||||
let value = vec![1, 2, 3];
|
||||
verify_that!(value, unordered_elements_are![eq(&1), eq(&2), eq(&3),])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_matches_size() -> Result<()> {
|
||||
let value = vec![1, 2];
|
||||
verify_that!(value, not(unordered_elements_are![eq(&1), eq(&2), eq(&3)]))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_admits_matchers_without_static_lifetime() -> Result<()> {
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct AStruct(i32);
|
||||
let expected_value = AStruct(123);
|
||||
verify_that!(vec![AStruct(123)], unordered_elements_are![eq(&expected_value)])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_with_map_admits_matchers_without_static_lifetime() -> Result<()> {
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct AStruct(i32);
|
||||
let expected_value = AStruct(123);
|
||||
verify_that!(
|
||||
HashMap::from([(1, AStruct(123))]),
|
||||
unordered_elements_are![(eq(&1), eq(&expected_value))]
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_description_mismatch() -> Result<()> {
|
||||
let result = verify_that!(vec![1, 4, 3], unordered_elements_are![eq(&1), eq(&2), eq(&3)]);
|
||||
verify_that!(
|
||||
result,
|
||||
err(displays_as(contains_substring(indoc!(
|
||||
"
|
||||
Value of: vec![1, 4, 3]
|
||||
Expected: contains elements matching in any order:
|
||||
0. is equal to 1
|
||||
1. is equal to 2
|
||||
2. is equal to 3
|
||||
Actual: [1, 4, 3],
|
||||
whose element #1 does not match any expected elements and no elements match the expected element #1"
|
||||
))))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_matches_unordered() -> Result<()> {
|
||||
let value = vec![1, 2];
|
||||
verify_that!(value, unordered_elements_are![eq(&2), eq(&1)])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_matches_unordered_with_repetition() -> Result<()> {
|
||||
let value = vec![1, 2, 1, 2, 1];
|
||||
verify_that!(value, unordered_elements_are![eq(&1), eq(&1), eq(&1), eq(&2), eq(&2)])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_explains_mismatch_due_to_wrong_size() -> Result<()> {
|
||||
let matcher = unordered_elements_are![eq(&2), eq(&3), eq(&4)];
|
||||
verify_that!(
|
||||
matcher.explain_match(&vec![2, 3]),
|
||||
displays_as(eq("which has size 2 (expected 3)"))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_description_no_full_match() -> Result<()> {
|
||||
let matcher = unordered_elements_are![eq(&1), eq(&2), eq(&2)];
|
||||
verify_that!(
|
||||
matcher.explain_match(&vec![1, 1, 2]),
|
||||
displays_as(eq(indoc!(
|
||||
"
|
||||
which does not have a perfect match with the expected elements. The best match found was:
|
||||
Actual element 1 at index 0 matched expected element `is equal to 1` at index 0.
|
||||
Actual element 2 at index 2 matched expected element `is equal to 2` at index 1.
|
||||
Actual element 1 at index 1 did not match any remaining expected element.
|
||||
Expected element `is equal to 2` at index 2 did not match any remaining actual element."
|
||||
)))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_unmatchable_expected_description_mismatch() -> Result<()> {
|
||||
let matcher = unordered_elements_are![eq(&1), eq(&2), eq(&3)];
|
||||
verify_that!(
|
||||
matcher.explain_match(&vec![1, 1, 3]),
|
||||
displays_as(eq("which has no element matching the expected element #1"))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_unmatchable_actual_description_mismatch() -> Result<()> {
|
||||
let matcher = unordered_elements_are![eq(&1), eq(&1), eq(&3)];
|
||||
verify_that!(
|
||||
matcher.explain_match(&vec![1, 2, 3]),
|
||||
displays_as(eq("whose element #1 does not match any expected elements"))
|
||||
)
|
||||
}
|
||||
|
||||
fn create_matcher<'a>() -> impl Matcher<&'a Vec<i32>> {
|
||||
unordered_elements_are![eq(&1)]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_works_when_matcher_is_created_in_subroutine() -> Result<()> {
|
||||
verify_that!(vec![1], create_matcher())
|
||||
}
|
||||
|
||||
fn create_matcher_for_map<'a>() -> impl Matcher<&'a HashMap<i32, i32>> {
|
||||
unordered_elements_are![(eq(&1), eq(&1))]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_works_when_matcher_for_maps_is_created_in_subroutine() -> Result<()> {
|
||||
verify_that!(HashMap::from([(1, 1)]), create_matcher_for_map())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_each_matches_when_one_to_one_correspondence_present() -> Result<()> {
|
||||
verify_that!(vec![2, 3, 4], contains_each!(eq(&2), eq(&3), eq(&4)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_each_supports_trailing_comma() -> Result<()> {
|
||||
verify_that!(vec![2, 3, 4], contains_each!(eq(&2), eq(&3), eq(&4),))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_each_matches_hash_map() -> Result<()> {
|
||||
let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two"), (3, "Three")]);
|
||||
verify_that!(value, contains_each![(eq(&2), eq(&"Two")), (eq(&1), eq(&"One"))])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_each_matches_hash_map_with_trailing_comma() -> Result<()> {
|
||||
let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two"), (3, "Three")]);
|
||||
verify_that!(value, contains_each![(eq(&2), eq(&"Two")), (eq(&1), eq(&"One")),])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_each_matches_when_no_matchers_present() -> Result<()> {
|
||||
verify_that!(vec![2, 3, 4], contains_each!())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_each_matches_when_no_matchers_present_and_trailing_comma() -> Result<()> {
|
||||
verify_that!(vec![2, 3, 4], contains_each!(,))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_each_matches_when_list_is_empty_and_no_matchers_present() -> Result<()> {
|
||||
verify_that!(Vec::<u32>::new(), contains_each!())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_each_matches_when_excess_elements_present() -> Result<()> {
|
||||
verify_that!(vec![1, 2, 3, 4], contains_each!(eq(&2), eq(&3), eq(&4)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_each_does_not_match_when_matchers_are_unmatched() -> Result<()> {
|
||||
verify_that!(vec![1, 2, 3], not(contains_each!(eq(&2), eq(&3), eq(&4))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_each_explains_mismatch_due_to_wrong_size() -> Result<()> {
|
||||
let matcher = contains_each![eq(&2), eq(&3), eq(&4)];
|
||||
verify_that!(
|
||||
matcher.explain_match(&vec![2, 3]),
|
||||
displays_as(eq("which has size 2 (expected at least 3)"))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_each_explains_missing_element_in_mismatch() -> Result<()> {
|
||||
let matcher = contains_each![eq(&2), eq(&3), eq(&4)];
|
||||
verify_that!(
|
||||
matcher.explain_match(&vec![1, 2, 3]),
|
||||
displays_as(eq("which has no element matching the expected element #2"))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_each_explains_missing_elements_in_mismatch() -> Result<()> {
|
||||
let matcher = contains_each![eq(&2), eq(&3), eq(&4), eq(&5)];
|
||||
verify_that!(
|
||||
matcher.explain_match(&vec![0, 1, 2, 3]),
|
||||
displays_as(eq("which has no elements matching the expected elements #2, #3"))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_each_explains_mismatch_due_to_no_graph_matching_found() -> Result<()> {
|
||||
let matcher = contains_each![ge(&2), ge(&2)];
|
||||
verify_that!(
|
||||
matcher .explain_match(&vec![1, 2]),
|
||||
displays_as(eq(indoc!(
|
||||
"
|
||||
which does not have a superset match with the expected elements. The best match found was:
|
||||
Actual element 2 at index 1 matched expected element `is greater than or equal to 2` at index 0.
|
||||
Actual element 1 at index 0 did not match any remaining expected element.
|
||||
Expected element `is greater than or equal to 2` at index 1 did not match any remaining actual element."))
|
||||
))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_contained_in_matches_with_empty_vector() -> Result<()> {
|
||||
let value: Vec<u32> = vec![];
|
||||
verify_that!(value, is_contained_in!())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_contained_in_matches_with_empty_vector_and_trailing_comma() -> Result<()> {
|
||||
let value: Vec<u32> = vec![];
|
||||
verify_that!(value, is_contained_in!(,))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_contained_in_matches_when_one_to_one_correspondence_present() -> Result<()> {
|
||||
verify_that!(vec![2, 3, 4], is_contained_in!(eq(&2), eq(&3), eq(&4)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_contained_supports_trailing_comma() -> Result<()> {
|
||||
verify_that!(vec![2, 3, 4], is_contained_in!(eq(&2), eq(&3), eq(&4),))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_contained_in_matches_hash_map() -> Result<()> {
|
||||
let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two")]);
|
||||
verify_that!(
|
||||
value,
|
||||
is_contained_in![(eq(&2), eq(&"Two")), (eq(&1), eq(&"One")), (eq(&3), eq(&"Three"))]
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_contained_in_matches_hash_map_with_trailing_comma() -> Result<()> {
|
||||
let value: HashMap<u32, &'static str> = HashMap::from([(1, "One"), (2, "Two")]);
|
||||
verify_that!(
|
||||
value,
|
||||
is_contained_in![(eq(&2), eq(&"Two")), (eq(&1), eq(&"One")), (eq(&3), eq(&"Three")),]
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_contained_in_matches_when_container_is_empty() -> Result<()> {
|
||||
verify_that!(vec![1; 0], is_contained_in!(eq(&2), eq(&3), eq(&4)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_contained_in_matches_when_excess_matchers_present() -> Result<()> {
|
||||
verify_that!(vec![3, 4], is_contained_in!(eq(&2), eq(&3), eq(&4)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_contained_in_does_not_match_when_elements_are_unmatched() -> Result<()> {
|
||||
verify_that!(vec![1, 2, 3], not(is_contained_in!(eq(&2), eq(&3), eq(&4))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_contained_in_explains_mismatch_due_to_wrong_size() -> Result<()> {
|
||||
let matcher = is_contained_in![eq(&2), eq(&3)];
|
||||
verify_that!(
|
||||
matcher.explain_match(&vec![2, 3, 4]),
|
||||
displays_as(eq("which has size 3 (expected at most 2)"))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_contained_in_explains_missing_element_in_mismatch() -> Result<()> {
|
||||
let matcher = is_contained_in![eq(&2), eq(&3), eq(&4)];
|
||||
verify_that!(
|
||||
matcher.explain_match(&vec![1, 2, 3]),
|
||||
displays_as(eq("whose element #0 does not match any expected elements"))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_contained_in_explains_missing_elements_in_mismatch() -> Result<()> {
|
||||
let matcher = is_contained_in![eq(&2), eq(&3), eq(&4), eq(&5)];
|
||||
verify_that!(
|
||||
matcher.explain_match(&vec![0, 1, 2, 3]),
|
||||
displays_as(eq("whose elements #0, #1 do not match any expected elements"))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_contained_in_explains_mismatch_due_to_no_graph_matching_found() -> Result<()> {
|
||||
let matcher = is_contained_in![ge(&1), ge(&3)];
|
||||
verify_that!(
|
||||
matcher.explain_match(&vec![1, 2]),
|
||||
displays_as(eq(indoc!(
|
||||
"
|
||||
which does not have a subset match with the expected elements. The best match found was:
|
||||
Actual element 1 at index 0 matched expected element `is greater than or equal to 1` at index 0.
|
||||
Actual element 2 at index 1 did not match any remaining expected element.
|
||||
Expected element `is greater than or equal to 3` at index 1 did not match any remaining actual element."))
|
||||
))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unordered_elements_are_with_auto_eq() -> Result<()> {
|
||||
verify_that!(vec![3, 4, 2], unordered_elements_are![&2, &3, &4])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn contains_each_with_auto_eq() -> Result<()> {
|
||||
verify_that!(vec![3, 4, 2], contains_each![&2, &4])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_contained_in_with_auto_eq() -> Result<()> {
|
||||
verify_that!(vec![3, 4, 2], is_contained_in![&1, &2, &3, &4])
|
||||
}
|
||||
Reference in new issue
Block a user