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 the actual value exactly when the inner matcher does _not_ match.
22 ///
23 /// ```
24 /// # use googletest::prelude::*;
25 /// # fn should_pass() -> Result<()> {
26 /// verify_that!(0, not(eq(1)))?; // Passes
27 /// #     Ok(())
28 /// # }
29 /// # fn should_fail() -> Result<()> {
30 /// verify_that!(0, not(eq(0)))?; // Fails
31 /// #     Ok(())
32 /// # }
33 /// # should_pass().unwrap();
34 /// # should_fail().unwrap_err();
35 /// ```
not<T: Debug, InnerMatcherT: Matcher<ActualT = T>>( inner: InnerMatcherT, ) -> impl Matcher<ActualT = T>36 pub fn not<T: Debug, InnerMatcherT: Matcher<ActualT = T>>(
37     inner: InnerMatcherT,
38 ) -> impl Matcher<ActualT = T> {
39     NotMatcher::<T, _> { inner, phantom: Default::default() }
40 }
41 
42 struct NotMatcher<T, InnerMatcherT> {
43     inner: InnerMatcherT,
44     phantom: PhantomData<T>,
45 }
46 
47 impl<T: Debug, InnerMatcherT: Matcher<ActualT = T>> Matcher for NotMatcher<T, InnerMatcherT> {
48     type ActualT = T;
49 
matches(&self, actual: &T) -> MatcherResult50     fn matches(&self, actual: &T) -> MatcherResult {
51         match self.inner.matches(actual) {
52             MatcherResult::Match => MatcherResult::NoMatch,
53             MatcherResult::NoMatch => MatcherResult::Match,
54         }
55     }
56 
explain_match(&self, actual: &T) -> Description57     fn explain_match(&self, actual: &T) -> Description {
58         self.inner.explain_match(actual)
59     }
60 
describe(&self, matcher_result: MatcherResult) -> Description61     fn describe(&self, matcher_result: MatcherResult) -> Description {
62         self.inner.describe(if matcher_result.into() {
63             MatcherResult::NoMatch
64         } else {
65             MatcherResult::Match
66         })
67     }
68 }
69 
70 #[cfg(test)]
71 mod tests {
72     use super::not;
73     use crate::matcher::{Matcher, MatcherResult};
74     use crate::prelude::*;
75     use indoc::indoc;
76 
77     #[test]
matches_when_inner_matcher_does_not_match() -> Result<()>78     fn matches_when_inner_matcher_does_not_match() -> Result<()> {
79         let matcher = not(eq(1));
80 
81         let result = matcher.matches(&0);
82 
83         verify_that!(result, eq(MatcherResult::Match))
84     }
85 
86     #[test]
does_not_match_when_inner_matcher_matches() -> Result<()>87     fn does_not_match_when_inner_matcher_matches() -> Result<()> {
88         let matcher = not(eq(1));
89 
90         let result = matcher.matches(&1);
91 
92         verify_that!(result, eq(MatcherResult::NoMatch))
93     }
94 
95     #[test]
match_explanation_references_actual_value() -> Result<()>96     fn match_explanation_references_actual_value() -> Result<()> {
97         let result = verify_that!([1], not(container_eq([1])));
98 
99         verify_that!(
100             result,
101             err(displays_as(contains_substring(indoc!(
102                 "
103                 Actual: [1],
104                   which contains all the elements
105                 "
106             ))))
107         )
108     }
109 }
110