1 // Copyright 2022 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use crate::description::Description;
16 use crate::matcher::{Matcher, MatcherResult};
17 use std::fmt::Debug;
18 use std::marker::PhantomData;
19 use std::ops::Deref;
20 
21 /// Matches a (smart) pointer pointing to a value matched by the [`Matcher`]
22 /// `expected`.
23 ///
24 /// This allows easily matching smart pointers such as `Box`, `Rc`, and `Arc`.
25 /// For example:
26 ///
27 /// ```
28 /// # use googletest::prelude::*;
29 /// # fn should_pass() -> Result<()> {
30 /// verify_that!(Box::new(123), points_to(eq(123)))?;
31 /// #     Ok(())
32 /// # }
33 /// # should_pass().unwrap();
34 /// ```
points_to<ExpectedT, MatcherT, ActualT>( expected: MatcherT, ) -> impl Matcher<ActualT = ActualT> where ExpectedT: Debug, MatcherT: Matcher<ActualT = ExpectedT>, ActualT: Deref<Target = ExpectedT> + Debug + ?Sized,35 pub fn points_to<ExpectedT, MatcherT, ActualT>(
36     expected: MatcherT,
37 ) -> impl Matcher<ActualT = ActualT>
38 where
39     ExpectedT: Debug,
40     MatcherT: Matcher<ActualT = ExpectedT>,
41     ActualT: Deref<Target = ExpectedT> + Debug + ?Sized,
42 {
43     PointsToMatcher { expected, phantom: Default::default() }
44 }
45 
46 struct PointsToMatcher<ActualT: ?Sized, MatcherT> {
47     expected: MatcherT,
48     phantom: PhantomData<ActualT>,
49 }
50 
51 impl<ExpectedT, MatcherT, ActualT> Matcher for PointsToMatcher<ActualT, MatcherT>
52 where
53     ExpectedT: Debug,
54     MatcherT: Matcher<ActualT = ExpectedT>,
55     ActualT: Deref<Target = ExpectedT> + Debug + ?Sized,
56 {
57     type ActualT = ActualT;
58 
matches(&self, actual: &ActualT) -> MatcherResult59     fn matches(&self, actual: &ActualT) -> MatcherResult {
60         self.expected.matches(actual.deref())
61     }
62 
explain_match(&self, actual: &ActualT) -> Description63     fn explain_match(&self, actual: &ActualT) -> Description {
64         self.expected.explain_match(actual.deref())
65     }
66 
describe(&self, matcher_result: MatcherResult) -> Description67     fn describe(&self, matcher_result: MatcherResult) -> Description {
68         self.expected.describe(matcher_result)
69     }
70 }
71 
72 #[cfg(test)]
73 mod tests {
74     use super::points_to;
75     use crate::prelude::*;
76     use indoc::indoc;
77     use std::rc::Rc;
78 
79     #[test]
points_to_matches_box_of_int_with_int() -> Result<()>80     fn points_to_matches_box_of_int_with_int() -> Result<()> {
81         verify_that!(Box::new(123), points_to(eq(123)))
82     }
83 
84     #[test]
points_to_matches_rc_of_int_with_int() -> Result<()>85     fn points_to_matches_rc_of_int_with_int() -> Result<()> {
86         verify_that!(Rc::new(123), points_to(eq(123)))
87     }
88 
89     #[test]
points_to_matches_box_of_owned_string_with_string_reference() -> Result<()>90     fn points_to_matches_box_of_owned_string_with_string_reference() -> Result<()> {
91         verify_that!(Rc::new("A string".to_string()), points_to(eq("A string")))
92     }
93 
94     #[test]
match_explanation_references_actual_value() -> Result<()>95     fn match_explanation_references_actual_value() -> Result<()> {
96         let result = verify_that!(&vec![1], points_to(container_eq([])));
97 
98         verify_that!(
99             result,
100             err(displays_as(contains_substring(indoc!(
101                 "
102                     Actual: [1],
103                       which contains the unexpected element 1
104                 "
105             ))))
106         )
107     }
108 }
109