1use std::borrow::Borrow;
5use std::fmt::Debug;
6
7use crate::{AssertThat, Failure};
8use crate::collections::{Collection, CollectionDebug, HighlightedCollectionDebug};
9
10pub trait CollectionOrdAssertions<'collection, C: Collection<'collection>> {
22
23 fn has_maximum<M: Borrow<C::Item>>(self, max: M) -> Self;
26
27 fn does_not_have_maximum<M: Borrow<C::Item>>(self, max: M) -> Self;
30
31 fn has_minimum<M: Borrow<C::Item>>(self, min: M) -> Self;
34
35 fn does_not_have_minimum<M: Borrow<C::Item>>(self, min: M) -> Self;
38}
39
40fn verify_has_extreme<'collection, C, M>(assert_that: &AssertThat<C>, expected_extreme: M,
41 actual_extreme: Option<&C::Item>, extreme_name: &str)
42where
43 C: Collection<'collection>,
44 C::Item: Debug + Ord,
45 M: Borrow<C::Item>
46{
47 let expected_extreme = expected_extreme.borrow();
48 let failure = Failure::new(assert_that)
49 .expected_it(format!("to have the {} <{:?}>", extreme_name, expected_extreme));
50
51 match actual_extreme {
52 Some(extreme) if extreme == expected_extreme => { }
53 Some(extreme) => {
54 let collection_debug = CollectionDebug { collection: &assert_that.data };
55
56 failure
57 .but_it(format!(
58 "was <{:?}>, which has the {} <{:?}>", collection_debug, extreme_name, extreme))
59 .fail()
60 }
61 None => failure.but_it("was empty").fail()
62 }
63}
64
65fn verify_does_not_have_extreme<'collection, C, M>(assert_that: &AssertThat<C>,
66 unexpected_extreme: M, actual_extreme: Option<&C::Item>, extreme_name: &str)
67where
68 C: Collection<'collection>,
69 C::Item: Debug + Ord,
70 M: Borrow<C::Item>
71{
72 let unexpected_extreme = unexpected_extreme.borrow();
73
74 if actual_extreme == Some(unexpected_extreme) {
75 let actual_extreme = actual_extreme.unwrap();
76 let actual_extreme_index = assert_that.data.iterator().enumerate()
77 .find(|&(_, item)| item == actual_extreme)
78 .map(|(index, _)| index)
79 .unwrap();
80 let highlighted_collection_debug =
81 HighlightedCollectionDebug::with_single_highlighted_element(
82 &assert_that.data, actual_extreme_index);
83
84 Failure::new(assert_that)
85 .expected_it(format!("not to have the {} <{:?}>", extreme_name, unexpected_extreme))
86 .but_it(format!("was <{:?}>", highlighted_collection_debug))
87 .fail()
88 }
89}
90
91impl<'collection, C> CollectionOrdAssertions<'collection, C> for AssertThat<C>
92where
93 C: Collection<'collection>,
94 C::Item: Debug + Ord
95{
96 fn has_maximum<M: Borrow<C::Item>>(self, max: M) -> Self {
97 verify_has_extreme(&self, max, self.data.iterator().max(), "maximum");
98
99 self
100 }
101
102 fn does_not_have_maximum<M: Borrow<C::Item>>(self, max: M) -> Self {
103 verify_does_not_have_extreme(&self, max, self.data.iterator().max(), "maximum");
104
105 self
106 }
107
108 fn has_minimum<M: Borrow<C::Item>>(self, min: M) -> Self {
109 verify_has_extreme(&self, min, self.data.iterator().min(), "minimum");
110
111 self
112 }
113
114 fn does_not_have_minimum<M: Borrow<C::Item>>(self, min: M) -> Self {
115 verify_does_not_have_extreme(&self, min, self.data.iterator().min(), "minimum");
116
117 self
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use crate::{assert_fails, assert_that};
124
125 use super::*;
126
127 #[test]
128 fn has_maximum_passes_for_correct_maximum() {
129 assert_that!(&[5, 1, 6, 2]).has_maximum(6);
130 }
131
132 #[test]
133 fn has_maximum_fails_for_empty_collection() {
134 assert_fails!((&[] as &[i32]).has_maximum(0),
135 expected it "to have the maximum <0>"
136 but it "was empty");
137 }
138
139 #[test]
140 fn has_maximum_fails_for_lower_maximum() {
141 assert_fails!((&[3, 1, 4, 2]).has_maximum(5),
142 expected it "to have the maximum <5>"
143 but it "was <[ 3, 1, 4, 2 ]>, which has the maximum <4>");
144 }
145
146 #[test]
147 fn has_maximum_fails_for_higher_maximum() {
148 assert_fails!((&[5, 7, 4, 1]).has_maximum(5),
149 expected it "to have the maximum <5>"
150 but it "was <[ 5, 7, 4, 1 ]>, which has the maximum <7>");
151 }
152
153 #[test]
154 fn does_not_have_maximum_passes_for_empty_collection() {
155 assert_that!(&[] as &[i32]).does_not_have_maximum(0);
156 }
157
158 #[test]
159 fn does_not_have_maximum_passes_for_lower_maximum() {
160 assert_that!(&[3, 1, 4, 2]).does_not_have_maximum(5);
161 }
162
163 #[test]
164 fn does_not_have_maximum_passes_for_higher_maximum() {
165 assert_that!(&[5, 7, 4, 1]).does_not_have_maximum(5);
166 }
167
168 #[test]
169 fn does_not_have_maximum_fails_for_correct_maximum() {
170 assert_fails!((&[5, 1, 6, 2]).does_not_have_maximum(6),
171 expected it "not to have the maximum <6>"
172 but it "was <[ 5, 1, [6], 2 ]>");
173 }
174
175 #[test]
176 fn has_minimum_passes_for_correct_minimum() {
177 assert_that!(&[5, 1, 6, 2]).has_minimum(1);
178 }
179
180 #[test]
181 fn has_minimum_fails_for_empty_collection() {
182 assert_fails!((&[] as &[i32]).has_minimum(0),
183 expected it "to have the minimum <0>"
184 but it "was empty");
185 }
186
187 #[test]
188 fn has_minimum_fails_for_higher_minimum() {
189 assert_fails!((&[3, 1, 4, 2]).has_minimum(0),
190 expected it "to have the minimum <0>"
191 but it "was <[ 3, 1, 4, 2 ]>, which has the minimum <1>");
192 }
193
194 #[test]
195 fn has_minimum_fails_for_lower_minimum() {
196 assert_fails!((&[5, 7, 4, 1]).has_minimum(4),
197 expected it "to have the minimum <4>"
198 but it "was <[ 5, 7, 4, 1 ]>, which has the minimum <1>");
199 }
200
201 #[test]
202 fn does_not_have_minimum_passes_for_empty_collection() {
203 assert_that!(&[] as &[i32]).does_not_have_minimum(0);
204 }
205
206 #[test]
207 fn does_not_have_minimum_passes_for_higher_minimum() {
208 assert_that!(&[3, 1, 4, 2]).does_not_have_minimum(0);
209 }
210
211 #[test]
212 fn does_not_have_minimum_passes_for_lower_minimum() {
213 assert_that!(&[5, 7, 4, 1]).does_not_have_minimum(4);
214 }
215
216 #[test]
217 fn does_not_have_minimum_fails_for_correct_minimum() {
218 assert_fails!((&[5, 1, 6, 2]).does_not_have_minimum(1),
219 expected it "not to have the minimum <1>"
220 but it "was <[ 5, [1], 6, 2 ]>");
221 }
222}