// Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use crate::{ description::Description, matcher::{Matcher, MatcherResult}, }; use std::{fmt::Debug, marker::PhantomData}; /// Matches a value greater (in the sense of `>`) than `expected`. /// /// The types of `ActualT` of `actual` and `ExpectedT` of `expected` must be /// comparable via the `PartialOrd` trait. Namely, `ActualT` must implement /// `PartialOrd`. /// /// ``` /// # use googletest::prelude::*; /// # fn should_pass() -> Result<()> { /// verify_that!(38, gt(1))?; // Passes /// # Ok(()) /// # } /// # fn should_fail() -> Result<()> { /// verify_that!(234, gt(234))?; // Fails /// # Ok(()) /// # } /// # should_pass().unwrap(); /// # should_fail().unwrap_err(); /// ``` /// /// In most cases the params neeed to be the same type or they need to be cast /// explicitly. This can be surprising when comparing integer types or /// references: /// /// ```compile_fail /// # use googletest::prelude::*; /// # fn should_not_compile() -> Result<()> { /// verify_that!(123u32, gt(0u64))?; // Does not compile /// verify_that!(123u32 as u64, gt(0u64))?; // Passes /// # Ok(()) /// # } /// ``` /// /// ```compile_fail /// # use googletest::prelude::*; /// # fn should_not_compile() -> Result<()> { /// let actual: &u32 = &2; /// let expected: u32 = 1; /// verify_that!(actual, gt(expected))?; // Does not compile /// # Ok(()) /// # } /// ``` /// /// ``` /// # use googletest::prelude::*; /// # fn should_pass() -> Result<()> { /// let actual: &u32 = &2; /// let expected: u32 = 1; /// verify_that!(actual, gt(&expected))?; // Compiles and passes /// # Ok(()) /// # } /// # should_pass().unwrap(); /// ``` /// /// You can find the standard library `PartialOrd` implementation in /// pub fn gt, ExpectedT: Debug>( expected: ExpectedT, ) -> impl Matcher { GtMatcher:: { expected, phantom: Default::default() } } struct GtMatcher { expected: ExpectedT, phantom: PhantomData, } impl, ExpectedT: Debug> Matcher for GtMatcher { type ActualT = ActualT; fn matches(&self, actual: &ActualT) -> MatcherResult { (*actual > self.expected).into() } fn describe(&self, matcher_result: MatcherResult) -> Description { match matcher_result { MatcherResult::Match => format!("is greater than {:?}", self.expected).into(), MatcherResult::NoMatch => { format!("is less than or equal to {:?}", self.expected).into() } } } } #[cfg(test)] mod tests { use super::gt; use crate::matcher::{Matcher, MatcherResult}; use crate::prelude::*; use indoc::indoc; use std::ffi::OsString; #[test] fn gt_matches_i32_with_i32() -> Result<()> { let actual: i32 = 321; let expected: i32 = 123; verify_that!(actual, gt(expected)) } #[test] fn gt_does_not_match_equal_i32() -> Result<()> { let matcher = gt(10); let result = matcher.matches(&10); verify_that!(result, eq(MatcherResult::NoMatch)) } #[test] fn gt_does_not_match_lower_i32() -> Result<()> { let matcher = gt(-50); let result = matcher.matches(&-51); verify_that!(result, eq(MatcherResult::NoMatch)) } #[test] fn gt_matches_greater_str() -> Result<()> { verify_that!("B", gt("A")) } #[test] fn gt_does_not_match_lesser_str() -> Result<()> { let matcher = gt("B"); let result = matcher.matches(&"A"); verify_that!(result, eq(MatcherResult::NoMatch)) } #[test] fn gt_mismatch_contains_actual_and_expected() -> Result<()> { let result = verify_that!(481, gt(632)); verify_that!( result, err(displays_as(contains_substring(indoc!( " Value of: 481 Expected: is greater than 632 Actual: 481, " )))) ) } #[test] fn gt_mismatch_combined_with_each() -> Result<()> { let result = verify_that!(vec![19, 23, 11], each(gt(15))); verify_that!( result, err(displays_as(contains_substring(indoc!( " Value of: vec![19, 23, 11] Expected: only contains elements that is greater than 15 Actual: [19, 23, 11], whose element #2 is 11, which is less than or equal to 15 " )))) ) } #[test] fn gt_describe_matches() -> Result<()> { verify_that!( gt::(232).describe(MatcherResult::Match), displays_as(eq("is greater than 232")) ) } #[test] fn gt_describe_does_not_match() -> Result<()> { verify_that!( gt::(232).describe(MatcherResult::NoMatch), displays_as(eq("is less than or equal to 232")) ) } // Test `gt` matcher where actual is `&OsString` and expected is `&str`. // Note that stdlib is a little bit inconsistent: `PartialOrd` exists for // `OsString` and `str`, but only in one direction: it's only possible to // compare `OsString` with `str` if `OsString` is on the left side of the // ">" operator (`impl PartialOrd for OsString`). // // The comparison in the other direction is not defined. // // This means that the test case bellow effectively ensures that // `verify_that(actual, gt(expected))` works if `actual > expected` works // (regardless whether the `expected > actual` works`). #[test] fn gt_matches_owned_osstring_reference_with_string_reference() -> Result<()> { let expected = "A"; let actual: OsString = "B".to_string().into(); verify_that!(&actual, gt(expected)) } #[test] fn gt_matches_ipv6addr_with_ipaddr() -> Result<()> { use std::net::IpAddr; use std::net::Ipv6Addr; let actual: Ipv6Addr = "2001:4860:4860::8888".parse().unwrap(); let expected: IpAddr = "127.0.0.1".parse().unwrap(); verify_that!(actual, gt(expected)) } #[test] fn gt_matches_with_custom_partial_ord() -> Result<()> { /// A custom "number" that is smaller than all other numbers. The only /// things we define about this "special" number is `PartialOrd` and /// `PartialEq` against `u32`. #[derive(Debug)] struct VeryLowNumber {} impl std::cmp::PartialEq for VeryLowNumber { fn eq(&self, _other: &u32) -> bool { false } } // PartialOrd (required for >) requires PartialEq. impl std::cmp::PartialOrd for VeryLowNumber { fn partial_cmp(&self, _other: &u32) -> Option { Some(std::cmp::Ordering::Less) } } impl std::cmp::PartialEq for u32 { fn eq(&self, _other: &VeryLowNumber) -> bool { false } } impl std::cmp::PartialOrd for u32 { fn partial_cmp(&self, _other: &VeryLowNumber) -> Option { Some(std::cmp::Ordering::Greater) } } let actual: u32 = 42; let expected = VeryLowNumber {}; verify_that!(actual, gt(expected)) } }