Skip to main content

googletest/matchers/
derefs_to_matcher.rs

1// Copyright 2024 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
15use crate::{
16    description::Description,
17    matcher::{Matcher, MatcherBase, MatcherResult},
18};
19use std::{fmt::Debug, ops::Deref};
20
21/// Dereferences the `actual` value and verifies that the returned reference
22/// matches the `inner` matcher.
23///
24/// ```
25/// # use googletest::{matchers::{derefs_to, eq}, verify_that};
26/// verify_that!(Box::new(123), derefs_to(eq(&123)))
27/// #    .unwrap()
28/// ```
29pub fn derefs_to<Inner>(inner: Inner) -> DerefsTo<Inner> {
30    DerefsTo { inner }
31}
32
33/// A matcher which derefs a value and verifies that the result matches the
34/// `inner` matcher.
35///
36/// See [`derefs_to`].
37#[derive(MatcherBase)]
38pub struct DerefsTo<InnerT> {
39    pub(crate) inner: InnerT,
40}
41
42impl<'a, ActualT, ExpectedT, Inner> Matcher<&'a ActualT> for DerefsTo<Inner>
43where
44    ActualT: Deref<Target = ExpectedT> + Debug,
45    ExpectedT: Copy + Debug + 'a,
46    Inner: Matcher<&'a ExpectedT>,
47{
48    fn matches(&self, actual: &'a ActualT) -> MatcherResult {
49        self.inner.matches(actual.deref())
50    }
51
52    fn describe(&self, matcher_result: MatcherResult) -> Description {
53        self.inner.describe(matcher_result)
54    }
55
56    fn explain_match(&self, actual: &'a ActualT) -> Description {
57        self.inner.explain_match(actual.deref())
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use std::rc::Rc;
64
65    use crate::prelude::*;
66    use crate::Result;
67    use indoc::indoc;
68
69    #[test]
70    fn deref_to_matches_box_of_int_with_int() -> Result<()> {
71        let actual = Box::new(123);
72        verify_that!(actual, derefs_to(eq(&123)))
73    }
74
75    #[test]
76    fn deref_to_matches_rc_of_int_with_int() -> Result<()> {
77        verify_that!(Rc::new(123), derefs_to(eq(&123)))
78    }
79
80    #[test]
81    fn deref_to_combines_with_points_to_for_copy() -> Result<()> {
82        verify_that!(Rc::new(123), derefs_to(points_to(eq(123))))
83    }
84
85    #[test]
86    fn match_explanation_references_actual_value() -> Result<()> {
87        let actual = Box::new(1);
88        let result = verify_that!(actual, derefs_to(eq(&0)));
89
90        verify_that!(
91            result,
92            err(displays_as(contains_substring(indoc!(
93                "
94                    Actual: 1,
95                      which isn't equal to 0
96                "
97            ))))
98        )
99    }
100}