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