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::{
16     description::Description,
17     matcher::{Matcher, MatcherResult},
18 };
19 use std::{fmt::Debug, marker::PhantomData};
20 
21 /// Matches a `Result` containing `Err` with a value matched by `inner`.
22 ///
23 /// ```
24 /// # use googletest::prelude::*;
25 /// # fn should_pass() -> googletest::Result<()> {
26 /// verify_that!(Err::<(), _>("Some error"), err(eq("Some error")))?;  // Passes
27 /// #     Ok(())
28 /// # }
29 /// # fn should_fail_1() -> googletest::Result<()> {
30 /// verify_that!(Ok::<_, &str>("A value"), err(eq("A value")))?;   // Fails
31 /// #     Ok(())
32 /// # }
33 /// # fn should_fail_2() -> googletest::Result<()> {
34 /// verify_that!(Err::<(), _>("Some error"), err(eq("Some other error")))?;   // Fails
35 /// #     Ok(())
36 /// # }
37 /// # should_pass().unwrap();
38 /// # should_fail_1().unwrap_err();
39 /// # should_fail_2().unwrap_err();
40 /// ```
err<T: Debug, E: Debug>( inner: impl Matcher<ActualT = E>, ) -> impl Matcher<ActualT = std::result::Result<T, E>>41 pub fn err<T: Debug, E: Debug>(
42     inner: impl Matcher<ActualT = E>,
43 ) -> impl Matcher<ActualT = std::result::Result<T, E>> {
44     ErrMatcher::<T, E, _> { inner, phantom_t: Default::default(), phantom_e: Default::default() }
45 }
46 
47 struct ErrMatcher<T, E, InnerMatcherT> {
48     inner: InnerMatcherT,
49     phantom_t: PhantomData<T>,
50     phantom_e: PhantomData<E>,
51 }
52 
53 impl<T: Debug, E: Debug, InnerMatcherT: Matcher<ActualT = E>> Matcher
54     for ErrMatcher<T, E, InnerMatcherT>
55 {
56     type ActualT = std::result::Result<T, E>;
57 
matches(&self, actual: &Self::ActualT) -> MatcherResult58     fn matches(&self, actual: &Self::ActualT) -> MatcherResult {
59         actual.as_ref().err().map(|v| self.inner.matches(v)).unwrap_or(MatcherResult::NoMatch)
60     }
61 
explain_match(&self, actual: &Self::ActualT) -> Description62     fn explain_match(&self, actual: &Self::ActualT) -> Description {
63         match actual {
64             Err(e) => {
65                 Description::new().text("which is an error").nested(self.inner.explain_match(e))
66             }
67             Ok(_) => "which is a success".into(),
68         }
69     }
70 
describe(&self, matcher_result: MatcherResult) -> Description71     fn describe(&self, matcher_result: MatcherResult) -> Description {
72         match matcher_result {
73             MatcherResult::Match => {
74                 format!("is an error which {}", self.inner.describe(MatcherResult::Match)).into()
75             }
76             MatcherResult::NoMatch => format!(
77                 "is a success or is an error containing a value which {}",
78                 self.inner.describe(MatcherResult::NoMatch)
79             )
80             .into(),
81         }
82     }
83 }
84 
85 #[cfg(test)]
86 mod tests {
87     use super::err;
88     use crate::matcher::{Matcher, MatcherResult};
89     use crate::prelude::*;
90     use indoc::indoc;
91 
92     #[test]
err_matches_result_with_err_value() -> Result<()>93     fn err_matches_result_with_err_value() -> Result<()> {
94         let matcher = err(eq(1));
95         let value: std::result::Result<i32, i32> = Err(1);
96 
97         let result = matcher.matches(&value);
98 
99         verify_that!(result, eq(MatcherResult::Match))
100     }
101 
102     #[test]
err_does_not_match_result_with_wrong_err_value() -> Result<()>103     fn err_does_not_match_result_with_wrong_err_value() -> Result<()> {
104         let matcher = err(eq(1));
105         let value: std::result::Result<i32, i32> = Err(0);
106 
107         let result = matcher.matches(&value);
108 
109         verify_that!(result, eq(MatcherResult::NoMatch))
110     }
111 
112     #[test]
err_does_not_match_result_with_ok() -> Result<()>113     fn err_does_not_match_result_with_ok() -> Result<()> {
114         let matcher = err(eq(1));
115         let value: std::result::Result<i32, i32> = Ok(1);
116 
117         let result = matcher.matches(&value);
118 
119         verify_that!(result, eq(MatcherResult::NoMatch))
120     }
121 
122     #[test]
err_full_error_message() -> Result<()>123     fn err_full_error_message() -> Result<()> {
124         let result = verify_that!(Err::<i32, i32>(1), err(eq(2)));
125 
126         verify_that!(
127             result,
128             err(displays_as(contains_substring(indoc!(
129                 "
130                     Value of: Err::<i32, i32>(1)
131                     Expected: is an error which is equal to 2
132                     Actual: Err(1),
133                       which is an error
134                         which isn't equal to 2
135                 "
136             ))))
137         )
138     }
139 
140     #[test]
err_describe_matches() -> Result<()>141     fn err_describe_matches() -> Result<()> {
142         let matcher = super::ErrMatcher::<i32, i32, _> {
143             inner: eq(1),
144             phantom_t: Default::default(),
145             phantom_e: Default::default(),
146         };
147         verify_that!(
148             matcher.describe(MatcherResult::Match),
149             displays_as(eq("is an error which is equal to 1"))
150         )
151     }
152 }
153