assertor/assertions/
basic.rs

1// Copyright 2021 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 std::borrow::Borrow;
16use std::fmt::Debug;
17
18use crate::base::{AssertionApi, AssertionResult, AssertionStrategy, Subject};
19
20/// Trait for equality assertion.
21/// # Example
22/// ```
23/// use assertor::*;
24/// assert_that!(1).is_equal_to(1);
25/// assert_that!(1).is_not_equal_to(2);
26/// ```
27pub trait EqualityAssertion<S, R> {
28    /// Checks if the subject is equal to `expected`.
29    #[track_caller]
30    fn is_equal_to<B: Borrow<S>>(&self, expected: B) -> R;
31
32    /// Checks if the subject value is NOT equal to `expected`.
33    #[track_caller]
34    fn is_not_equal_to<B: Borrow<S>>(&self, expected: B) -> R;
35}
36
37impl<S: PartialEq + Debug, R> EqualityAssertion<S, R> for Subject<'_, S, (), R>
38where
39    AssertionResult: AssertionStrategy<R>,
40{
41    fn is_equal_to<B: Borrow<S>>(&self, expected: B) -> R {
42        if self.actual().eq(expected.borrow()) {
43            self.new_result().do_ok()
44        } else {
45            self.new_result()
46                .add_fact("expected", format!("{:?}", expected.borrow()))
47                .add_fact("actual", format!("{:?}", self.actual()))
48                .do_fail()
49        }
50    }
51    fn is_not_equal_to<B: Borrow<S>>(&self, expected: B) -> R {
52        if !self.actual().ne(expected.borrow()) {
53            self.new_result().do_fail()
54        } else {
55            self.new_result().do_ok()
56        }
57    }
58}
59
60/// Trait for comparison assertions.
61pub trait ComparableAssertion<S, R> {
62    /// Checks that the subject is greater than or equal to `expected`.
63    #[track_caller]
64    fn is_at_least<B: Borrow<S>>(&self, expected: B) -> R;
65
66    /// Checks that the subject is less than or equal to `expected`.
67    #[track_caller]
68    fn is_at_most<B: Borrow<S>>(&self, expected: B) -> R;
69
70    /// Checks that the subject is greater than `expected`.
71    #[track_caller]
72    fn is_greater_than<B: Borrow<S>>(&self, expected: B) -> R;
73
74    /// Checks that the subject is less than `expected`.
75    #[track_caller]
76    fn is_less_than<B: Borrow<S>>(&self, expected: B) -> R;
77}
78
79impl<S: PartialOrd + Debug, R> ComparableAssertion<S, R> for Subject<'_, S, (), R>
80where
81    AssertionResult: AssertionStrategy<R>,
82{
83    fn is_at_least<B: Borrow<S>>(&self, expected: B) -> R {
84        if self.actual().ge(expected.borrow()) {
85            self.new_result().do_ok()
86        } else {
87            self.new_result()
88                .add_fact("expected", format!("{:?}", self.actual()))
89                .add_fact("to be at least", format!("{:?}", expected.borrow()))
90                .do_fail()
91        }
92    }
93
94    fn is_at_most<B: Borrow<S>>(&self, expected: B) -> R {
95        if self.actual().le(expected.borrow()) {
96            self.new_result().do_ok()
97        } else {
98            self.new_result()
99                .add_fact("expected", format!("{:?}", self.actual()))
100                .add_fact("to be at most", format!("{:?}", expected.borrow()))
101                .do_fail()
102        }
103    }
104
105    fn is_greater_than<B: Borrow<S>>(&self, expected: B) -> R {
106        if self.actual().gt(expected.borrow()) {
107            self.new_result().do_ok()
108        } else {
109            self.new_result()
110                .add_fact("expected", format!("{:?}", self.actual()))
111                .add_fact("to be greater than", format!("{:?}", expected.borrow()))
112                .do_fail()
113        }
114    }
115
116    fn is_less_than<B: Borrow<S>>(&self, expected: B) -> R {
117        if self.actual().lt(expected.borrow()) {
118            self.new_result().do_ok()
119        } else {
120            self.new_result()
121                .add_fact("expected", format!("{:?}", self.actual()))
122                .add_fact("to be less than", format!("{:?}", expected.borrow()))
123                .do_fail()
124        }
125    }
126}
127
128#[cfg(test)]
129mod tests {
130    use crate::testing::*;
131
132    use super::*;
133
134    #[test]
135    fn is_equal_to() {
136        assert_that!(1).is_equal_to(1);
137        assert_that!(2).is_equal_to(2);
138        assert_that!(vec![1]).is_equal_to(vec![1]);
139
140        // failures
141    }
142
143    #[test]
144    fn is_equal_to_error_message() {
145        let result = check_that!(1).is_equal_to(3);
146
147        assert_that!(result).facts_are(vec![Fact::new("expected", "3"), Fact::new("actual", "1")])
148    }
149
150    #[test]
151    fn is_not_equal_to() {
152        assert_that!(1).is_not_equal_to(2);
153        assert_that!(2).is_not_equal_to(1);
154        assert_that!(vec![1]).is_not_equal_to(vec![]);
155        assert_that!(vec![1]).is_not_equal_to(vec![2]);
156    }
157
158    #[test]
159    fn is_at_least() {
160        assert_that!(2).is_at_least(1);
161        assert_that!(2).is_at_least(2);
162        assert_that!(2_f32).is_at_least(1.);
163
164        assert_that!(check_that!(2).is_at_least(3)).facts_are(vec![
165            Fact::new("expected", "2"),
166            Fact::new("to be at least", "3"),
167        ]);
168        assert_that!(check_that!(2).is_at_most(1)).facts_are(vec![
169            Fact::new("expected", "2"),
170            Fact::new("to be at most", "1"),
171        ]);
172    }
173}