galvanic_assert/matchers/variant.rs
1/* Copyright 2017 Christopher Bacher
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
16//! The variant module contains matchers for asserting properties of enums and convienience functions for Option and Result.
17
18use super::super::*;
19
20/// Matches if the asserted value's variant matches the expected variant.
21///
22/// # Examples
23/// If the enum's variants are already imported one can write:
24///
25/// ```
26/// # #[macro_use] extern crate galvanic_assert;
27/// # fn main() {
28/// let ok: Result<i32, ()> = Ok(4);
29/// assert_that!(&ok, is_variant!(Ok));
30/// # }
31/// ```
32/// If not then the full path of the variant has to be used:
33///
34/// ```
35/// # #[macro_use] extern crate galvanic_assert;
36/// # fn main() {
37/// enum MyEnum { Foo, Bar(i32), Baz{x: i32} }
38/// assert_that!(&MyEnum::Baz{x: 2}, is_variant!(MyEnum::Baz));
39/// # }
40/// ```
41#[macro_export]
42macro_rules! is_variant {
43 ( $variant: path ) => {
44 Box::new(|actual: &_| {
45 use galvanic_assert::MatchResultBuilder;
46 let builder = MatchResultBuilder::for_("is_variant");
47 match actual {
48 &$variant {..} => builder.matched(),
49 _ => builder.failed_because(
50 &format!("passed variant does not match '{}'", stringify!($variant))
51 )
52 }
53 })
54 }
55}
56
57/// Matches the contents of an `Option` againts a passed `Matcher`.
58///
59/// #Examples
60/// ```rust
61/// # #[macro_use] extern crate galvanic_assert;
62/// use galvanic_assert::matchers::*;
63/// use galvanic_assert::matchers::variant::*;
64/// # fn main() {
65/// assert_that!(&Some(32), maybe_some(eq(32)));
66/// # }
67pub fn maybe_some<'a, T: 'a>(matcher: Box<Matcher<'a,T> + 'a>) -> Box<Matcher<'a,Option<T>> + 'a> {
68 Box::new(move |maybe_actual: &'a Option<T>| {
69 maybe_actual.as_ref()
70 .map_or(MatchResultBuilder::for_("maybe_some")
71 .failed_because("passed Option is None; cannot evaluate nested matcher"),
72 |actual| matcher.check(actual)
73 )
74 })
75}
76
77/// Matches the contents of a `Result` if it is `Ok` againts a passed `Matcher`.
78///
79/// #Examples
80/// ```rust
81/// # #[macro_use] extern crate galvanic_assert;
82/// use galvanic_assert::matchers::*;
83/// use galvanic_assert::matchers::variant::*;
84/// # fn main() {
85/// let ok: Result<i32,()> = Ok(32);
86/// assert_that!(&ok, maybe_ok(eq(32)));
87/// # }
88pub fn maybe_ok<'a, T: 'a, E: 'a>(matcher: Box<Matcher<'a,T> + 'a>) -> Box<Matcher<'a,Result<T,E>> + 'a> {
89 Box::new(move |maybe_actual: &'a Result<T,E>| {
90 match maybe_actual.as_ref() {
91 Ok(actual) => matcher.check(actual),
92 Err(_) => MatchResultBuilder::for_("maybe_ok")
93 .failed_because("passed Result is Err; cannot evaluate nested matcher")
94 }
95 })
96}
97
98/// Matches the contents of a `Result` if it is `Err` againts a passed `Matcher`.
99///
100/// #Examples
101/// ```rust
102/// # #[macro_use] extern crate galvanic_assert;
103/// use galvanic_assert::matchers::*;
104/// use galvanic_assert::matchers::variant::*;
105/// # fn main() {
106/// let err: Result<i32,i32> = Err(32);
107/// assert_that!(&err, maybe_err(eq(32)));
108/// # }
109pub fn maybe_err<'a, T: 'a, E: 'a>(matcher: Box<Matcher<'a,E> + 'a>) -> Box<Matcher<'a,Result<T,E>> + 'a> {
110 Box::new(move |maybe_actual: &'a Result<T,E>| {
111 match maybe_actual.as_ref() {
112 Err(actual) => matcher.check(actual),
113 Ok(_) => MatchResultBuilder::for_("maybe_err")
114 .failed_because("passed Result is Ok; cannot evaluate nested matcher")
115 }
116 })
117}