assertables/assert_io_read_to_string/assert_io_read_to_string_ge_x.rs
1//! Assert a ::std::io::Read read_to_string() value is greater than or equal to an expression.
2//!
3//! Pseudocode:<br>
4//! (reader.read_to_string(a_string) ⇒ a_string) ≥ (expr ⇒ b_string)
5//!
6//! # Example
7//!
8//! ```rust
9//! use assertables::*;
10//! use std::io::Read;
11//!
12//! let reader = "alfa".as_bytes();
13//! let x = String::from("aa");
14//! assert_io_read_to_string_ge_x!(reader, x);
15//! ```
16//!
17//! # Module macros
18//!
19//! * [`assert_io_read_to_string_ge_x`](macro@crate::assert_io_read_to_string_ge_x)
20//! * [`assert_io_read_to_string_ge_x_as_result`](macro@crate::assert_io_read_to_string_ge_x_as_result)
21//! * [`debug_assert_io_read_to_string_ge_x`](macro@crate::debug_assert_io_read_to_string_ge_x)
22
23/// Assert a ::std::io::Read read_to_string() value is greater than or equal to an expression.
24///
25/// Pseudocode:<br>
26/// (reader.read_to_string(a_string) ⇒ a_string) ≥ (expr ⇒ b_string)
27///
28/// * If true, return Result `Ok(a_string)`.
29///
30/// * Otherwise, return Result `Err(message)`.
31///
32/// This macro is useful for runtime checks, such as checking parameters,
33/// or sanitizing inputs, or handling different results in different ways.
34///
35/// # Module macros
36///
37/// * [`assert_io_read_to_string_ge_x`](macro@crate::assert_io_read_to_string_ge_x)
38/// * [`assert_io_read_to_string_ge_x_as_result`](macro@crate::assert_io_read_to_string_ge_x_as_result)
39/// * [`debug_assert_io_read_to_string_ge_x`](macro@crate::debug_assert_io_read_to_string_ge_x)
40///
41#[macro_export]
42macro_rules! assert_io_read_to_string_ge_x_as_result {
43 ($a_reader:expr, $b_expr:expr $(,)?) => {
44 match (&$b_expr) {
45 b_expr => {
46 match (std::io::read_to_string($a_reader)) {
47 Ok(a_string) => {
48 if (a_string >= *b_expr) {
49 Ok(a_string)
50 } else {
51 Err(
52 format!(
53 concat!(
54 "assertion failed: `assert_io_read_to_string_ge_x!(a_reader, b_expr)`\n",
55 "https://docs.rs/assertables/9.8.2/assertables/macro.assert_io_read_to_string_ge_x.html\n",
56 " a_reader label: `{}`,\n",
57 " a_reader debug: `{:?}`,\n",
58 " b_expr label: `{}`,\n",
59 " b_expr debug: `{:?}`,\n",
60 " a: `{:?}`,\n",
61 " b: `{:?}`",
62 ),
63 stringify!($a_reader),
64 $a_reader,
65 stringify!($b_expr),
66 b_expr,
67 a_string,
68 b_expr
69 )
70 )
71 }
72 },
73 Err(err) => {
74 Err(
75 format!(
76 concat!(
77 "assertion failed: `assert_io_read_to_string_ge_x!(a_reader, b_expr)`\n",
78 "https://docs.rs/assertables/9.8.2/assertables/macro.assert_io_read_to_string_ge_x.html\n",
79 " a_reader label: `{}`,\n",
80 " a_reader debug: `{:?}`,\n",
81 " b_expr label: `{}`,\n",
82 " b_expr debug: `{:?}`,\n",
83 " err: `{:?}`"
84 ),
85 stringify!($a_reader),
86 $a_reader,
87 stringify!($b_expr),
88 b_expr,
89 err
90 )
91 )
92 }
93 }
94 }
95 }
96 };
97}
98
99#[cfg(test)]
100mod test_assert_io_read_to_string_ge_x_as_result {
101 #[allow(unused_imports)]
102 use std::io::Read;
103 use std::sync::Once;
104
105 #[test]
106 fn gt() {
107 let reader = "alfa".as_bytes();
108 let x = String::from("aa");
109 for _ in 0..1 {
110 let actual = assert_io_read_to_string_ge_x_as_result!(reader, x);
111 assert_eq!(actual.unwrap(), String::from("alfa"));
112 }
113 }
114
115 #[test]
116 fn gt_once() {
117 static A: Once = Once::new();
118 fn a() -> &'static [u8] {
119 if A.is_completed() {
120 panic!("A.is_completed()")
121 } else {
122 A.call_once(|| {})
123 }
124 "alfa".as_bytes()
125 }
126
127 static B: Once = Once::new();
128 fn b() -> String {
129 if B.is_completed() {
130 panic!("B.is_completed()")
131 } else {
132 B.call_once(|| {})
133 }
134 String::from("aa")
135 }
136
137 assert_eq!(A.is_completed(), false);
138 assert_eq!(B.is_completed(), false);
139 let result = assert_io_read_to_string_ge_x_as_result!(a(), b());
140 assert!(result.is_ok());
141 assert_eq!(A.is_completed(), true);
142 assert_eq!(B.is_completed(), true);
143 }
144
145 #[test]
146 fn eq() {
147 let reader = "alfa".as_bytes();
148 let x = String::from("alfa");
149 for _ in 0..1 {
150 let actual = assert_io_read_to_string_ge_x_as_result!(reader, x);
151 assert_eq!(actual.unwrap(), String::from("alfa"));
152 }
153 }
154
155 #[test]
156 fn eq_once() {
157 static A: Once = Once::new();
158 fn a() -> &'static [u8] {
159 if A.is_completed() {
160 panic!("A.is_completed()")
161 } else {
162 A.call_once(|| {})
163 }
164 "alfa".as_bytes()
165 }
166
167 static B: Once = Once::new();
168 fn b() -> String {
169 if B.is_completed() {
170 panic!("B.is_completed()")
171 } else {
172 B.call_once(|| {})
173 }
174 String::from("alfa")
175 }
176
177 assert_eq!(A.is_completed(), false);
178 assert_eq!(B.is_completed(), false);
179 let result = assert_io_read_to_string_ge_x_as_result!(a(), b());
180 assert!(result.is_ok());
181 assert_eq!(A.is_completed(), true);
182 assert_eq!(B.is_completed(), true);
183 }
184
185 #[test]
186 fn lt() {
187 let reader = "alfa".as_bytes();
188 let x = String::from("zz");
189 let actual = assert_io_read_to_string_ge_x_as_result!(reader, x);
190 let message = concat!(
191 "assertion failed: `assert_io_read_to_string_ge_x!(a_reader, b_expr)`\n",
192 "https://docs.rs/assertables/9.8.2/assertables/macro.assert_io_read_to_string_ge_x.html\n",
193 " a_reader label: `reader`,\n",
194 " a_reader debug: `[97, 108, 102, 97]`,\n",
195 " b_expr label: `x`,\n",
196 " b_expr debug: `\"zz\"`,\n",
197 " a: `\"alfa\"`,\n",
198 " b: `\"zz\"`"
199 );
200 assert_eq!(actual.unwrap_err(), message);
201 }
202}
203
204/// Assert a ::std::io::Read read_to_string() value is greater than or equal to an expression.
205///
206/// Pseudocode:<br>
207/// (reader.read_to_string(a_string) ⇒ a_string) ≥ (expr ⇒ b_string)
208///
209/// * If true, return `a_string`.
210///
211/// * Otherwise, call [`panic!`] with a message and the values of the
212/// expressions with their debug representations.
213///
214/// # Examples
215///
216/// ```rust
217/// use assertables::*;
218/// # use std::panic;
219/// use std::io::Read;
220///
221/// # fn main() {
222/// let reader = "alfa".as_bytes();
223/// let x = String::from("aa");
224/// assert_io_read_to_string_ge_x!(reader, x);
225///
226/// # let result = panic::catch_unwind(|| {
227/// // This will panic
228/// let reader = "alfa".as_bytes();
229/// let x = String::from("zz");
230/// assert_io_read_to_string_ge_x!(reader, x);
231/// # });
232/// // assertion failed: `assert_io_read_to_string_ge_x!(a_reader, b_expr)`
233/// // https://docs.rs/assertables/…/assertables/macro.assert_io_read_to_string_ge_x.html
234/// // a_reader label: `reader`,
235/// // a_reader debug: `[97, 108, 102, 97]`,
236/// // b_expr label: `x`,
237/// // b_expr debug: `\"zz\"`,
238/// // a: `\"alfa\"`,
239/// // b: `\"zz\"`
240/// # let actual = result.unwrap_err().downcast::<String>().unwrap().to_string();
241/// # let message = concat!(
242/// # "assertion failed: `assert_io_read_to_string_ge_x!(a_reader, b_expr)`\n",
243/// # "https://docs.rs/assertables/9.8.2/assertables/macro.assert_io_read_to_string_ge_x.html\n",
244/// # " a_reader label: `reader`,\n",
245/// # " a_reader debug: `[97, 108, 102, 97]`,\n",
246/// # " b_expr label: `x`,\n",
247/// # " b_expr debug: `\"zz\"`,\n",
248/// # " a: `\"alfa\"`,\n",
249/// # " b: `\"zz\"`"
250/// # );
251/// # assert_eq!(actual, message);
252/// # }
253/// ```
254///
255/// # Module macros
256///
257/// * [`assert_io_read_to_string_ge_x`](macro@crate::assert_io_read_to_string_ge_x)
258/// * [`assert_io_read_to_string_ge_x_as_result`](macro@crate::assert_io_read_to_string_ge_x_as_result)
259/// * [`debug_assert_io_read_to_string_ge_x`](macro@crate::debug_assert_io_read_to_string_ge_x)
260///
261#[macro_export]
262macro_rules! assert_io_read_to_string_ge_x {
263 ($a_reader:expr, $b_expr:expr $(,)?) => {
264 match $crate::assert_io_read_to_string_ge_x_as_result!($a_reader, $b_expr) {
265 Ok(x) => x,
266 Err(err) => panic!("{}", err),
267 }
268 };
269 ($a_reader:expr, $b_expr:expr, $($message:tt)+) => {
270 match $crate::assert_io_read_to_string_ge_x_as_result!($a_reader, $b_expr) {
271 Ok(x) => x,
272 Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
273 }
274 };
275}
276
277#[cfg(test)]
278mod test_assert_io_read_to_string_ge_x {
279 #[allow(unused_imports)]
280 use std::panic;
281
282 #[test]
283 fn gt() {
284 let reader = "alfa".as_bytes();
285 let x = String::from("aa");
286 for _ in 0..1 {
287 let actual = assert_io_read_to_string_ge_x!(reader, x);
288 assert_eq!(actual, String::from("alfa"));
289 }
290 }
291
292 #[test]
293 fn eq() {
294 let reader = "alfa".as_bytes();
295 let x = String::from("alfa");
296 for _ in 0..1 {
297 let actual = assert_io_read_to_string_ge_x!(reader, x);
298 assert_eq!(actual, String::from("alfa"));
299 }
300 }
301
302 #[test]
303 fn lt() {
304 let result = panic::catch_unwind(|| {
305 let reader = "alfa".as_bytes();
306 let x = String::from("zz");
307 let _actual = assert_io_read_to_string_ge_x!(reader, x);
308 });
309 let message = concat!(
310 "assertion failed: `assert_io_read_to_string_ge_x!(a_reader, b_expr)`\n",
311 "https://docs.rs/assertables/9.8.2/assertables/macro.assert_io_read_to_string_ge_x.html\n",
312 " a_reader label: `reader`,\n",
313 " a_reader debug: `[97, 108, 102, 97]`,\n",
314 " b_expr label: `x`,\n",
315 " b_expr debug: `\"zz\"`,\n",
316 " a: `\"alfa\"`,\n",
317 " b: `\"zz\"`"
318 );
319 assert_eq!(
320 result
321 .unwrap_err()
322 .downcast::<String>()
323 .unwrap()
324 .to_string(),
325 message
326 );
327 }
328}
329
330/// Assert zzz.
331///
332/// Pseudocode:<br>
333/// (reader.read_to_string(a_string) ⇒ a_string) ≥ (expr ⇒ b_string)
334///
335/// This macro provides the same statements as [`assert_io_read_to_string_ge_x`](macro.assert_io_read_to_string_ge_x.html),
336/// except this macro's statements are only enabled in non-optimized
337/// builds by default. An optimized build will not execute this macro's
338/// statements unless `-C debug-assertions` is passed to the compiler.
339///
340/// This macro is useful for checks that are too expensive to be present
341/// in a release build but may be helpful during development.
342///
343/// The result of expanding this macro is always type checked.
344///
345/// An unchecked assertion allows a program in an inconsistent state to
346/// keep running, which might have unexpected consequences but does not
347/// introduce unsafety as long as this only happens in safe code. The
348/// performance cost of assertions, however, is not measurable in general.
349/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
350/// after thorough profiling, and more importantly, only in safe code!
351///
352/// This macro is intended to work in a similar way to
353/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
354///
355/// # Module macros
356///
357/// * [`assert_io_read_to_string_ge_x`](macro@crate::assert_io_read_to_string_ge_x)
358/// * [`assert_io_read_to_string_ge_x`](macro@crate::assert_io_read_to_string_ge_x)
359/// * [`debug_assert_io_read_to_string_ge_x`](macro@crate::debug_assert_io_read_to_string_ge_x)
360///
361#[macro_export]
362macro_rules! debug_assert_io_read_to_string_ge_x {
363 ($($arg:tt)*) => {
364 if $crate::cfg!(debug_assertions) {
365 $crate::assert_io_read_to_string_ge_x!($($arg)*);
366 }
367 };
368}