build(rust): vendor googletest crate
This commit was merged in pull request #76.
This commit is contained in:
1 parent
a6fe84190e
commit
6887b104d6
576 files changed
+284290
-2
No files matched your search
@@ -0,0 +1,215 @@
|
||||
// Copyright 2023 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, MatcherBase, MatcherResult},
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
|
||||
/// Creates a matcher based on the predicate provided.
|
||||
///
|
||||
/// ```
|
||||
/// # use googletest::prelude::*;
|
||||
/// # fn should_pass() -> Result<()> {
|
||||
/// verify_that!(3, predicate(|x: i32| x % 2 == 1))?; // Passes
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// # should_pass().unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// The predicate should take the subject type and return a
|
||||
/// boolean.
|
||||
///
|
||||
/// Note: even if the Rust compiler should be able to infer the type of
|
||||
/// the closure argument, it is likely that it won't.
|
||||
/// See <https://github.com/rust-lang/rust/issues/12679> for update on this issue.
|
||||
/// This is easily fixed by explicitly declaring the type of the argument
|
||||
pub fn predicate<P>(predicate: P) -> PredicateMatcher<P, NoDescription, NoDescription> {
|
||||
PredicateMatcher {
|
||||
predicate,
|
||||
positive_description: NoDescription,
|
||||
negative_description: NoDescription,
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> PredicateMatcher<P, NoDescription, NoDescription> {
|
||||
/// Configures this instance to provide a more meaningful description.
|
||||
///
|
||||
/// For example, to make sure the error message is more useful
|
||||
///
|
||||
/// ```
|
||||
/// # use googletest::matchers::{predicate, PredicateMatcher};
|
||||
/// # let _ =
|
||||
/// predicate(|x: i32| x % 2 == 1)
|
||||
/// .with_description("is odd", "is even")
|
||||
/// # ;
|
||||
/// ```
|
||||
///
|
||||
/// This is optional as it only provides value when the test fails.
|
||||
///
|
||||
/// Description can be passed by `&str`, `String` or `Fn() -> Into<String>`.
|
||||
pub fn with_description<D1: PredicateDescription, D2: PredicateDescription>(
|
||||
self,
|
||||
positive_description: D1,
|
||||
negative_description: D2,
|
||||
) -> PredicateMatcher<P, D1, D2> {
|
||||
PredicateMatcher { predicate: self.predicate, positive_description, negative_description }
|
||||
}
|
||||
}
|
||||
|
||||
/// A matcher which applies `predicate` on the value.
|
||||
///
|
||||
/// See [`predicate`].
|
||||
#[derive(MatcherBase)]
|
||||
pub struct PredicateMatcher<P, D1, D2> {
|
||||
predicate: P,
|
||||
positive_description: D1,
|
||||
negative_description: D2,
|
||||
}
|
||||
|
||||
/// A trait to allow [`PredicateMatcher::with_description`] to accept multiple
|
||||
/// types.
|
||||
///
|
||||
/// See [`PredicateMatcher::with_description`]
|
||||
pub trait PredicateDescription {
|
||||
fn to_description(&self) -> Description;
|
||||
}
|
||||
|
||||
impl PredicateDescription for &str {
|
||||
fn to_description(&self) -> Description {
|
||||
self.to_string().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl PredicateDescription for String {
|
||||
fn to_description(&self) -> Description {
|
||||
self.to_string().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S> PredicateDescription for T
|
||||
where
|
||||
T: Fn() -> S,
|
||||
S: Into<String>,
|
||||
{
|
||||
fn to_description(&self) -> Description {
|
||||
self().into().into()
|
||||
}
|
||||
}
|
||||
|
||||
// Sentinel type to tag a MatcherBuilder as without a description.
|
||||
#[doc(hidden)]
|
||||
pub struct NoDescription;
|
||||
|
||||
impl<T: Debug + Copy, P> Matcher<T> for PredicateMatcher<P, NoDescription, NoDescription>
|
||||
where
|
||||
P: Fn(T) -> bool,
|
||||
{
|
||||
fn matches(&self, actual: T) -> MatcherResult {
|
||||
(self.predicate)(actual).into()
|
||||
}
|
||||
|
||||
fn describe(&self, result: MatcherResult) -> Description {
|
||||
match result {
|
||||
MatcherResult::Match => "matches".into(),
|
||||
MatcherResult::NoMatch => "does not match".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Debug + Copy, P, D1: PredicateDescription, D2: PredicateDescription> Matcher<T>
|
||||
for PredicateMatcher<P, D1, D2>
|
||||
where
|
||||
P: Fn(T) -> bool,
|
||||
{
|
||||
fn matches(&self, actual: T) -> MatcherResult {
|
||||
(self.predicate)(actual).into()
|
||||
}
|
||||
|
||||
fn describe(&self, result: MatcherResult) -> Description {
|
||||
match result {
|
||||
MatcherResult::Match => self.positive_description.to_description(),
|
||||
MatcherResult::NoMatch => self.negative_description.to_description(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::prelude::*;
|
||||
use crate::Result;
|
||||
|
||||
// Simple matcher with a description
|
||||
fn is_odd() -> impl Matcher<i32> {
|
||||
predicate(|x| x % 2 == 1).with_description("is odd", "is even")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn predicate_matcher_odd() -> Result<()> {
|
||||
verify_that!(1, is_odd())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn predicate_matcher_odd_explain_match_matches() -> Result<()> {
|
||||
verify_that!(is_odd().explain_match(1), displays_as(eq("which is odd")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn predicate_matcher_odd_explain_match_does_not_match() -> Result<()> {
|
||||
verify_that!(is_odd().explain_match(2), displays_as(eq("which is even")))
|
||||
}
|
||||
|
||||
// Simple Matcher without description
|
||||
fn is_even() -> impl Matcher<i32> {
|
||||
predicate(|x| x % 2 == 0)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn predicate_matcher_even() -> Result<()> {
|
||||
verify_that!(2, is_even())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn predicate_matcher_even_explain_match_matches() -> Result<()> {
|
||||
verify_that!(is_even().explain_match(2), displays_as(eq("which matches")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn predicate_matcher_even_explain_match_does_not_match() -> Result<()> {
|
||||
verify_that!(is_even().explain_match(1), displays_as(eq("which does not match")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn predicate_matcher_generator_lambda() -> Result<()> {
|
||||
let is_divisible_by = |quotient| {
|
||||
predicate(move |x: i32| x % quotient == 0).with_description(
|
||||
move || format!("is divisible by {quotient}"),
|
||||
move || format!("is not divisible by {quotient}"),
|
||||
)
|
||||
};
|
||||
verify_that!(49, is_divisible_by(7))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn predicate_matcher_inline() -> Result<()> {
|
||||
verify_that!(2048, predicate(|x: i32| x.count_ones() == 1))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn predicate_matcher_function_pointer() -> Result<()> {
|
||||
use std::time::Duration;
|
||||
verify_that!(&Duration::new(0, 0), predicate(Duration::is_zero))
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user