assertor/assertions/
vec.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::assertions::iterator::{
19    check_has_length, check_is_empty, check_is_not_empty, IteratorAssertion,
20};
21use crate::base::{AssertionApi, AssertionResult, AssertionStrategy, Subject};
22
23/// Trait for vector assertion.
24///
25/// Compared to [`crate::IteratorAssertion`], [`VecAssertion`] simplifies code because it is not
26/// needed to take reference of the expected value and to call `vec.iter()` in the actual value.
27///
28/// ```
29/// use assertor::*;
30/// assert_that!(vec![1,2,3].iter()).contains(&2);  // IteratorAssertion
31/// assert_that!(vec![1,2,3]).contains(2); // VecAssertion
32/// ```
33///
34/// # Example
35/// ```
36/// use assertor::*;
37/// use assertor::VecAssertion;
38///
39/// assert_that!(Vec::<usize>::new()).is_empty();
40/// assert_that!(vec![1,2,3]).has_length(3);
41/// assert_that!(vec![1,2,3]).contains(2);
42/// assert_that!(vec![1,2,3]).contains_exactly(vec![3,2,1]);
43/// assert_that!(vec![1,2,3]).contains_exactly_in_order(vec![1,2,3]);
44/// ```
45pub trait VecAssertion<'a, S, T, R>
46where
47    AssertionResult: AssertionStrategy<R>,
48    Self: Sized,
49{
50    /// Checks that the subject contains the element `expected`.
51    ///
52    /// # Example
53    /// ```
54    /// use assertor::*;
55    /// assert_that!(vec![1, 2, 3]).contains(2);
56    /// ```
57    #[track_caller]
58    fn contains<B>(&self, element: B) -> R
59    where
60        B: Borrow<T>,
61        T: PartialEq + Debug;
62
63    /// Checks that the subject does not contains the `element`.
64    ///
65    /// # Example
66    /// ```
67    /// use assertor::*;
68    /// assert_that!(vec![1, 2, 3]).does_not_contain(5);
69    /// ```
70    #[track_caller]
71    fn does_not_contain<B>(&self, element: B) -> R
72    where
73        B: Borrow<T>,
74        T: PartialEq + Debug;
75
76    /// Checks that the subject exactly contains elements of `expected_vec`.
77    ///
78    /// This method doesn't take care of the order. Use
79    /// [contains_exactly_in_order](`VecAssertion::contains_exactly_in_order`) to check
80    /// elements are in the same order.
81    ///
82    /// # Example
83    /// ```
84    /// use assertor::*;
85    /// assert_that!(vec![1, 2, 3]).contains_exactly(vec![3, 2, 1]);
86    /// ```
87    /// ```should_panic
88    /// use assertor::*;
89    /// assert_that!(vec![1]).contains_exactly(vec![1,2]);
90    /// assert_that!(vec![1,2]).contains_exactly(vec![1]);
91    /// ```
92    #[track_caller]
93    fn contains_exactly<B: Borrow<Vec<T>>>(self, expected_vec: B) -> R
94    where
95        T: PartialEq + Debug;
96
97    /// Checks that the subject exactly contains `expected_vec` in the same order.
98    ///
99    /// # Example
100    /// ```
101    /// use assertor::*;
102    /// assert_that!(vec![1, 2, 3]).contains_exactly_in_order(vec![1, 2, 3]);
103    /// ```
104    /// ```should_panic
105    /// use assertor::*;
106    /// assert_that!(vec![1]).contains_exactly_in_order(vec![1,2]);
107    /// assert_that!(vec![1,2]).contains_exactly_in_order(vec![1]);
108    /// ```
109    #[track_caller]
110    fn contains_exactly_in_order<B: Borrow<Vec<T>>>(self, expected_vec: B) -> R
111    where
112        T: PartialEq + Debug;
113
114    /// Checks that the subject does not contain any element of `elements`.
115    ///
116    /// # Example
117    /// ```
118    /// use assertor::*;
119    /// assert_that!(vec![1, 2, 3]).does_not_contain_any(vec![0, -5]);
120    /// ```
121    /// ```should_panic
122    /// use assertor::*;
123    /// assert_that!(vec![1,2]).does_not_contain_any(vec![1]);
124    /// ```
125    #[track_caller]
126    fn does_not_contain_any<B: Borrow<Vec<T>>>(&self, elements: B) -> R
127    where
128        T: PartialEq + Debug;
129
130    /// Checks that the subject is empty.
131    ///
132    /// # Example
133    /// ```
134    /// use assertor::*;
135    /// assert_that!(Vec::<usize>::new()).is_empty();
136    /// ```
137    #[track_caller]
138    fn is_empty(&self) -> R
139    where
140        T: Debug;
141
142    /// Checks that the subject is not empty.
143    ///
144    /// # Example
145    /// ```
146    /// use assertor::*;
147    /// assert_that!(vec![1]).is_not_empty();
148    /// ```
149    #[track_caller]
150    fn is_not_empty(&self) -> R
151    where
152        T: Debug;
153
154    /// Checks that the subject is the given length.
155    ///
156    /// # Example
157    /// ```
158    /// use assertor::*;
159    /// assert_that!(vec![1, 2, 3]).has_length(3);
160    /// ```
161    #[track_caller]
162    fn has_length(&self, length: usize) -> R;
163}
164
165impl<'a, T, R> VecAssertion<'a, Vec<T>, T, R> for Subject<'a, Vec<T>, (), R>
166where
167    AssertionResult: AssertionStrategy<R>,
168{
169    fn contains<B>(&self, element: B) -> R
170    where
171        B: Borrow<T>,
172        T: PartialEq + Debug,
173    {
174        self.new_subject(&self.actual().iter(), None, ())
175            .contains(element.borrow())
176    }
177
178    fn does_not_contain<B>(&self, element: B) -> R
179    where
180        B: Borrow<T>,
181        T: PartialEq + Debug,
182    {
183        self.new_owned_subject(self.actual().iter(), None, ())
184            .does_not_contain(element.borrow())
185    }
186
187    fn contains_exactly<B: Borrow<Vec<T>>>(self, expected_iter: B) -> R
188    where
189        T: PartialEq + Debug,
190    {
191        self.new_owned_subject(self.actual().iter(), None, ())
192            .contains_exactly(expected_iter.borrow().iter())
193    }
194
195    fn contains_exactly_in_order<B: Borrow<Vec<T>>>(self, expected_iter: B) -> R
196    where
197        T: PartialEq + Debug,
198    {
199        self.new_owned_subject(self.actual().iter(), None, ())
200            .contains_exactly_in_order(expected_iter.borrow().iter())
201    }
202
203    fn does_not_contain_any<B: Borrow<Vec<T>>>(&self, elements: B) -> R
204    where
205        T: PartialEq + Debug,
206    {
207        self.new_owned_subject(self.actual().iter(), None, ())
208            .does_not_contain_any(elements.borrow().iter())
209    }
210
211    fn is_empty(&self) -> R
212    where
213        T: Debug,
214    {
215        check_is_empty(self.new_result(), self.actual().iter())
216    }
217
218    fn is_not_empty(&self) -> R
219    where
220        T: Debug,
221    {
222        check_is_not_empty(self.new_result(), self.actual().iter())
223    }
224
225    fn has_length(&self, length: usize) -> R {
226        check_has_length(self.new_result(), self.actual().iter(), self.expr(), length)
227    }
228}
229
230#[cfg(test)]
231mod tests {
232    use crate::testing::*;
233
234    use super::*;
235
236    #[test]
237    fn contains() {
238        assert_that!(vec![1, 2, 3]).contains(&3);
239
240        // Failures
241        assert_that!(check_that!(vec![1, 2, 3]).contains(&10)).facts_are(vec![
242            Fact::new("expected to contain", "10"),
243            Fact::new_simple_fact("but did not"),
244            Fact::new_multi_value_fact("though it did contain", vec!["1", "2", "3"]),
245        ]);
246    }
247
248    #[test]
249    fn contains_exactly() {
250        assert_that!(vec![1, 2, 3]).contains_exactly(vec![1, 2, 3]);
251        assert_that!(vec![2, 1, 3]).contains_exactly(vec![1, 2, 3]);
252    }
253
254    #[test]
255    fn contains_exactly_in_order() {
256        assert_that!(vec![1, 2, 3]).contains_exactly_in_order(vec![1, 2, 3]);
257        assert_that!(check_that!(vec![2, 1, 3]).contains_exactly_in_order(vec![1, 2, 3])).facts_are(
258            vec![
259                Fact::new_simple_fact("contents match, but order was wrong"),
260                Fact::new_splitter(),
261                Fact::new_multi_value_fact("expected", vec!["1", "2", "3"]),
262                Fact::new_multi_value_fact("actual", vec!["2", "1", "3"]),
263            ],
264        )
265    }
266
267    #[test]
268    fn is_empty() {
269        assert_that!(Vec::<usize>::new()).is_empty();
270
271        // Failures
272        assert_that!(check_that!(vec![1]).is_empty()).facts_are(vec![
273            Fact::new_simple_fact("expected to be empty"),
274            Fact::new_splitter(),
275            Fact::new_multi_value_fact("actual", vec!["1"]),
276        ])
277    }
278
279    #[test]
280    fn is_not_empty() {
281        assert_that!(Vec::<usize>::from([1])).is_not_empty();
282
283        // Failures
284        assert_that!(check_that!(Vec::<usize>::new()).is_not_empty()).facts_are(vec![
285            Fact::new_simple_fact("expected to be non-empty"),
286            Fact::new_splitter(),
287            Fact::new("actual", "[]"),
288        ])
289    }
290
291    #[test]
292    fn has_size() {
293        assert_that!(vec![1, 2, 3]).has_length(3);
294        assert_that!(Vec::<usize>::new()).has_length(0);
295
296        // Failures
297        assert_that!(check_that!(Vec::<usize>::new()).has_length(3)).facts_are(vec![
298            Fact::new("value of", "Vec::<usize>::new().size()"),
299            Fact::new("expected", "3"),
300            Fact::new("actual", "0"),
301        ]);
302    }
303}