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