googletest_predicates/
lib.rs1use googletest::matcher::{Matcher, MatcherResult};
2use predicates::{reflection::PredicateReflection, Predicate};
3use std::{
4 fmt::{Debug, Display},
5 marker::PhantomData,
6};
7
8pub fn matcher<M: ToPredicate<T, P>, T: Debug, P: Predicate<T>>(matcher: M) -> impl Predicate<T> {
10 matcher.to_predicate()
11}
12
13pub trait ToPredicate<T, P: Predicate<T>> {
15 fn to_predicate(self) -> P;
17}
18
19impl<M, T> ToPredicate<T, MatcherPredicate<M, T>> for M
21where
22 M: Matcher<ActualT = T>,
23 T: Debug,
24{
25 fn to_predicate(self) -> MatcherPredicate<M, T> {
26 MatcherPredicate {
27 matcher: self,
28 _phantom_data_t: Default::default(),
29 }
30 }
31}
32
33struct MatcherPredicate<M, T>
34where
35 M: Matcher<ActualT = T>,
36 T: Debug,
37{
38 matcher: M,
39 _phantom_data_t: PhantomData<T>,
40}
41
42impl<M, T> Predicate<T> for MatcherPredicate<M, T>
43where
44 M: Matcher<ActualT = T>,
45 T: Debug,
46{
47 fn eval(&self, variable: &T) -> bool {
48 match self.matcher.matches(variable) {
49 MatcherResult::Match => true,
50 MatcherResult::NoMatch => false,
51 }
52 }
53}
54
55impl<M, T> PredicateReflection for MatcherPredicate<M, T>
56where
57 M: Matcher<ActualT = T>,
58 T: Debug,
59{
60}
61
62impl<M, T> Display for MatcherPredicate<M, T>
63where
64 M: Matcher<ActualT = T>,
65 T: Debug,
66{
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 f.write_str(&self.matcher.describe(MatcherResult::Match))
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75 use googletest::{expect_that, matchers::*};
76 use mockall::automock;
77
78 #[cfg_attr(test, automock)]
79 trait MyTrait {
80 fn foo(&self, x: u32) -> u32;
81 }
82
83 #[googletest::test]
84 fn test_matcher_eq_1_to_string() {
85 expect_that!(matcher(eq(1)).to_string(), eq("is equal to 1"));
86 }
87
88 #[googletest::test]
89 fn test_matcher_eq_1_eval_returns_true() {
90 expect_that!(matcher(eq(1)).eval(&1), eq(true));
91 }
92
93 #[googletest::test]
94 fn test_matcher_eq_1_eval_returns_false() {
95 expect_that!(matcher(eq(1)).eval(&2), eq(false));
96 }
97
98 #[googletest::test]
99 fn test_mockall_with_matcher_fn() {
100 let mut mock = MockMyTrait::new();
101 mock.expect_foo()
102 .with(matcher(eq(1)))
103 .times(1)
104 .returning(|x| x + 1);
105 expect_that!(mock.foo(1), eq(2))
106 }
107}