googletest/matchers/
none_matcher.rs

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
15use crate::description::Description;
16use crate::matcher::{Matcher, MatcherBase, MatcherResult};
17use std::fmt::Debug;
18
19/// Matches an `Option` containing `None`.
20///
21/// ```
22/// # use googletest::prelude::*;
23/// # fn should_pass() -> Result<()> {
24/// verify_that!(None::<()>, none())?;   // Passes
25/// #     Ok(())
26/// # }
27/// # fn should_fail() -> Result<()> {
28/// verify_that!(Some("Some value"), none())?;  // Fails
29/// #     Ok(())
30/// # }
31/// # should_pass().unwrap();
32/// # should_fail().unwrap_err();
33/// ```
34pub fn none() -> NoneMatcher {
35    NoneMatcher
36}
37
38#[derive(MatcherBase)]
39pub struct NoneMatcher;
40
41impl<T: Debug + Copy> Matcher<Option<T>> for NoneMatcher {
42    fn matches(&self, actual: Option<T>) -> MatcherResult {
43        actual.is_none().into()
44    }
45
46    fn describe(&self, matcher_result: MatcherResult) -> Description {
47        match matcher_result {
48            MatcherResult::Match => "is none".into(),
49            MatcherResult::NoMatch => "is some(_)".into(),
50        }
51    }
52}
53
54impl<'a, T: Debug> Matcher<&'a Option<T>> for NoneMatcher {
55    fn matches(&self, actual: &'a Option<T>) -> MatcherResult {
56        actual.is_none().into()
57    }
58
59    fn describe(&self, matcher_result: MatcherResult) -> Description {
60        match matcher_result {
61            MatcherResult::Match => "is none".into(),
62            MatcherResult::NoMatch => "is some(_)".into(),
63        }
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use crate::matcher::MatcherResult;
70    use crate::prelude::*;
71    use crate::Result;
72
73    #[test]
74    fn none_matches_option_with_none() -> Result<()> {
75        let matcher = none();
76
77        let result = matcher.matches(None::<i32>);
78
79        verify_that!(result, eq(MatcherResult::Match))
80    }
81
82    #[test]
83    fn none_does_not_match_option_with_value() -> Result<()> {
84        let matcher = none();
85
86        let result = matcher.matches(Some(0));
87
88        verify_that!(result, eq(MatcherResult::NoMatch))
89    }
90
91    #[test]
92    fn none_matches_option_by_ref() -> Result<()> {
93        verify_that!(None::<String>, none())
94    }
95    #[test]
96    fn none_does_not_match_option_with_value_by_ref() -> Result<()> {
97        verify_that!(Some("123".to_string()), not(none()))
98    }
99
100    #[test]
101    fn none_describe_match_option_by_ref() -> Result<()> {
102        verify_that!(
103            Matcher::<&Option<String>>::describe(&none(), MatcherResult::Match),
104            displays_as(eq("is none"))
105        )
106    }
107    #[test]
108    fn none_describe_no_match_option_by_ref() -> Result<()> {
109        verify_that!(
110            Matcher::<&Option<String>>::describe(&none(), MatcherResult::NoMatch),
111            displays_as(eq("is some(_)"))
112        )
113    }
114
115    #[test]
116    fn none_describe_match_option() -> Result<()> {
117        verify_that!(
118            Matcher::<Option<i32>>::describe(&none(), MatcherResult::Match),
119            displays_as(eq("is none"))
120        )
121    }
122    #[test]
123    fn none_describe_no_match_option() -> Result<()> {
124        verify_that!(
125            Matcher::<Option<i32>>::describe(&none(), MatcherResult::NoMatch),
126            displays_as(eq("is some(_)"))
127        )
128    }
129}