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 value greater (in the sense of `>`) than `expected`.
22 ///
23 /// The types of `ActualT` of `actual` and `ExpectedT` of `expected` must be
24 /// comparable via the `PartialOrd` trait. Namely, `ActualT` must implement
25 /// `PartialOrd<ExpectedT>`.
26 ///
27 /// ```
28 /// # use googletest::prelude::*;
29 /// # fn should_pass() -> Result<()> {
30 /// verify_that!(38, gt(1))?; // Passes
31 /// #     Ok(())
32 /// # }
33 /// # fn should_fail() -> Result<()> {
34 /// verify_that!(234, gt(234))?; // Fails
35 /// #     Ok(())
36 /// # }
37 /// # should_pass().unwrap();
38 /// # should_fail().unwrap_err();
39 /// ```
40 ///
41 /// In most cases the params neeed to be the same type or they need to be cast
42 /// explicitly. This can be surprising when comparing integer types or
43 /// references:
44 ///
45 /// ```compile_fail
46 /// # use googletest::prelude::*;
47 /// # fn should_not_compile() -> Result<()> {
48 /// verify_that!(123u32, gt(0u64))?; // Does not compile
49 /// verify_that!(123u32 as u64, gt(0u64))?; // Passes
50 /// #     Ok(())
51 /// # }
52 /// ```
53 ///
54 /// ```compile_fail
55 /// # use googletest::prelude::*;
56 /// # fn should_not_compile() -> Result<()> {
57 /// let actual: &u32 = &2;
58 /// let expected: u32 = 1;
59 /// verify_that!(actual, gt(expected))?; // Does not compile
60 /// #     Ok(())
61 /// # }
62 /// ```
63 ///
64 /// ```
65 /// # use googletest::prelude::*;
66 /// # fn should_pass() -> Result<()> {
67 /// let actual: &u32 = &2;
68 /// let expected: u32 = 1;
69 /// verify_that!(actual, gt(&expected))?; // Compiles and passes
70 /// #     Ok(())
71 /// # }
72 /// # should_pass().unwrap();
73 /// ```
74 ///
75 /// You can find the standard library `PartialOrd` implementation in
76 /// <https://doc.rust-lang.org/core/cmp/trait.PartialOrd.html#implementors>
gt<ActualT: Debug + PartialOrd<ExpectedT>, ExpectedT: Debug>( expected: ExpectedT, ) -> impl Matcher<ActualT = ActualT>77 pub fn gt<ActualT: Debug + PartialOrd<ExpectedT>, ExpectedT: Debug>(
78     expected: ExpectedT,
79 ) -> impl Matcher<ActualT = ActualT> {
80     GtMatcher::<ActualT, _> { expected, phantom: Default::default() }
81 }
82 
83 struct GtMatcher<ActualT, ExpectedT> {
84     expected: ExpectedT,
85     phantom: PhantomData<ActualT>,
86 }
87 
88 impl<ActualT: Debug + PartialOrd<ExpectedT>, ExpectedT: Debug> Matcher
89     for GtMatcher<ActualT, ExpectedT>
90 {
91     type ActualT = ActualT;
92 
matches(&self, actual: &ActualT) -> MatcherResult93     fn matches(&self, actual: &ActualT) -> MatcherResult {
94         (*actual > self.expected).into()
95     }
96 
describe(&self, matcher_result: MatcherResult) -> Description97     fn describe(&self, matcher_result: MatcherResult) -> Description {
98         match matcher_result {
99             MatcherResult::Match => format!("is greater than {:?}", self.expected).into(),
100             MatcherResult::NoMatch => {
101                 format!("is less than or equal to {:?}", self.expected).into()
102             }
103         }
104     }
105 }
106 
107 #[cfg(test)]
108 mod tests {
109     use super::gt;
110     use crate::matcher::{Matcher, MatcherResult};
111     use crate::prelude::*;
112     use indoc::indoc;
113     use std::ffi::OsString;
114 
115     #[test]
gt_matches_i32_with_i32() -> Result<()>116     fn gt_matches_i32_with_i32() -> Result<()> {
117         let actual: i32 = 321;
118         let expected: i32 = 123;
119         verify_that!(actual, gt(expected))
120     }
121 
122     #[test]
gt_does_not_match_equal_i32() -> Result<()>123     fn gt_does_not_match_equal_i32() -> Result<()> {
124         let matcher = gt(10);
125         let result = matcher.matches(&10);
126         verify_that!(result, eq(MatcherResult::NoMatch))
127     }
128 
129     #[test]
gt_does_not_match_lower_i32() -> Result<()>130     fn gt_does_not_match_lower_i32() -> Result<()> {
131         let matcher = gt(-50);
132         let result = matcher.matches(&-51);
133         verify_that!(result, eq(MatcherResult::NoMatch))
134     }
135 
136     #[test]
gt_matches_greater_str() -> Result<()>137     fn gt_matches_greater_str() -> Result<()> {
138         verify_that!("B", gt("A"))
139     }
140 
141     #[test]
gt_does_not_match_lesser_str() -> Result<()>142     fn gt_does_not_match_lesser_str() -> Result<()> {
143         let matcher = gt("B");
144         let result = matcher.matches(&"A");
145         verify_that!(result, eq(MatcherResult::NoMatch))
146     }
147 
148     #[test]
gt_mismatch_contains_actual_and_expected() -> Result<()>149     fn gt_mismatch_contains_actual_and_expected() -> Result<()> {
150         let result = verify_that!(481, gt(632));
151 
152         verify_that!(
153             result,
154             err(displays_as(contains_substring(indoc!(
155                 "
156                 Value of: 481
157                 Expected: is greater than 632
158                 Actual: 481,
159                 "
160             ))))
161         )
162     }
163 
164     #[test]
gt_mismatch_combined_with_each() -> Result<()>165     fn gt_mismatch_combined_with_each() -> Result<()> {
166         let result = verify_that!(vec![19, 23, 11], each(gt(15)));
167 
168         verify_that!(
169             result,
170             err(displays_as(contains_substring(indoc!(
171                 "
172                 Value of: vec![19, 23, 11]
173                 Expected: only contains elements that is greater than 15
174                 Actual: [19, 23, 11],
175                   whose element #2 is 11, which is less than or equal to 15
176                 "
177             ))))
178         )
179     }
180 
181     #[test]
gt_describe_matches() -> Result<()>182     fn gt_describe_matches() -> Result<()> {
183         verify_that!(
184             gt::<i32, i32>(232).describe(MatcherResult::Match),
185             displays_as(eq("is greater than 232"))
186         )
187     }
188 
189     #[test]
gt_describe_does_not_match() -> Result<()>190     fn gt_describe_does_not_match() -> Result<()> {
191         verify_that!(
192             gt::<i32, i32>(232).describe(MatcherResult::NoMatch),
193             displays_as(eq("is less than or equal to 232"))
194         )
195     }
196 
197     // Test `gt` matcher where actual is `&OsString` and expected is `&str`.
198     // Note that stdlib is a little bit inconsistent: `PartialOrd` exists for
199     // `OsString` and `str`, but only in one direction: it's only possible to
200     // compare `OsString` with `str` if `OsString` is on the left side of the
201     // ">" operator (`impl PartialOrd<str> for OsString`).
202     //
203     // The comparison in the other direction is not defined.
204     //
205     // This means that the test case bellow effectively ensures that
206     // `verify_that(actual, gt(expected))` works if `actual > expected` works
207     // (regardless whether the `expected > actual` works`).
208     #[test]
gt_matches_owned_osstring_reference_with_string_reference() -> Result<()>209     fn gt_matches_owned_osstring_reference_with_string_reference() -> Result<()> {
210         let expected = "A";
211         let actual: OsString = "B".to_string().into();
212         verify_that!(&actual, gt(expected))
213     }
214 
215     #[test]
gt_matches_ipv6addr_with_ipaddr() -> Result<()>216     fn gt_matches_ipv6addr_with_ipaddr() -> Result<()> {
217         use std::net::IpAddr;
218         use std::net::Ipv6Addr;
219         let actual: Ipv6Addr = "2001:4860:4860::8888".parse().unwrap();
220         let expected: IpAddr = "127.0.0.1".parse().unwrap();
221         verify_that!(actual, gt(expected))
222     }
223 
224     #[test]
gt_matches_with_custom_partial_ord() -> Result<()>225     fn gt_matches_with_custom_partial_ord() -> Result<()> {
226         /// A custom "number" that is smaller than all other numbers. The only
227         /// things we define about this "special" number is `PartialOrd` and
228         /// `PartialEq` against `u32`.
229         #[derive(Debug)]
230         struct VeryLowNumber {}
231 
232         impl std::cmp::PartialEq<u32> for VeryLowNumber {
233             fn eq(&self, _other: &u32) -> bool {
234                 false
235             }
236         }
237 
238         // PartialOrd (required for >) requires PartialEq.
239         impl std::cmp::PartialOrd<u32> for VeryLowNumber {
240             fn partial_cmp(&self, _other: &u32) -> Option<std::cmp::Ordering> {
241                 Some(std::cmp::Ordering::Less)
242             }
243         }
244 
245         impl std::cmp::PartialEq<VeryLowNumber> for u32 {
246             fn eq(&self, _other: &VeryLowNumber) -> bool {
247                 false
248             }
249         }
250 
251         impl std::cmp::PartialOrd<VeryLowNumber> for u32 {
252             fn partial_cmp(&self, _other: &VeryLowNumber) -> Option<std::cmp::Ordering> {
253                 Some(std::cmp::Ordering::Greater)
254             }
255         }
256 
257         let actual: u32 = 42;
258         let expected = VeryLowNumber {};
259 
260         verify_that!(actual, gt(expected))
261     }
262 }
263