1extern crate ntest_test_cases;
5extern crate ntest_timeout;
6
7#[doc(inline)]
8pub use ntest_test_cases::test_case;
9
10#[doc(inline)]
11pub use ntest_timeout::timeout;
12
13use std::sync::mpsc;
14use std::thread;
15use std::time::Duration;
16
17mod traits;
19#[doc(inline)]
20pub use crate::traits::MaxDifference;
21
22#[doc(hidden)]
23pub fn execute_with_timeout<T: Send>(
25 code: &'static (dyn Fn() -> T + Sync + 'static),
26 timeout_ms: u64,
27) -> Option<T> {
28 let (sender, receiver) = mpsc::channel();
29 thread::spawn(move || if let Ok(()) = sender.send(code()) {});
30 match receiver.recv_timeout(Duration::from_millis(timeout_ms)) {
31 Ok(t) => Some(t),
32 Err(_) => None,
33 }
34}
35
36#[doc(hidden)]
37pub fn about_eq<T: MaxDifference>(a: T, b: T, eps: f64) -> bool {
39 a.max_diff(b) < eps
40}
41
42#[macro_export]
81macro_rules! assert_about_eq {
82 ($a:expr, $b:expr, $eps:expr) => {
83 let eps = $eps;
84 assert!(
85 $crate::about_eq($a, $b, eps),
86 "assertion failed: `(left !== right)` \
87 (left: `{:?}`, right: `{:?}`, epsilon: `{:?}`)",
88 $a,
89 $b,
90 eps
91 );
92 };
93 ($a:expr, $b:expr,$eps:expr,) => {
94 assert_about_eq!($a, $b, $eps);
95 };
96 ($a:expr, $b:expr) => {
97 assert_about_eq!($a, $b, 1.0e-6);
98 };
99 ($a:expr, $b:expr,) => {
100 assert_about_eq!($a, $b, 1.0e-6);
101 };
102}
103
104#[macro_export]
126macro_rules! assert_true {
127 ($x:expr) => {
128 if !$x {
129 panic!("assertion failed: Expected 'true', but was 'false'");
130 }
131 };
132 ($x:expr,) => {
133 assert_true!($x);
134 };
135}
136
137#[macro_export]
157macro_rules! assert_false {
158 ($x:expr) => {{
159 if $x {
160 panic!("assertion failed: Expected 'false', but was 'true'");
161 }
162 }};
163 ($x:expr,) => {{
164 assert_false!($x);
165 }};
166}
167
168#[macro_export]
192macro_rules! assert_panics {
193 ($x:block) => {{
194 let result = std::panic::catch_unwind(|| $x);
195 if !result.is_err() {
196 panic!("assertion failed: code in block did not panic");
197 }
198 }};
199 ($x:block,) => {{
200 assert_panics!($x);
201 }};
202}
203
204#[cfg(test)]
205mod tests {
206 use super::*;
207 #[test]
208 fn assert_true() {
209 assert_true!(true);
210 }
211 #[test]
212 #[should_panic]
213 fn assert_true_fails() {
214 assert_true!(false);
215 }
216 #[test]
217 fn assert_true_trailing_comma() {
218 assert_true!(true,);
219 }
220 #[test]
221 fn assert_false() {
222 assert_false!(false);
223 }
224 #[test]
225 #[should_panic]
226 fn assert_false_fails() {
227 assert_false!(true);
228 }
229 #[test]
230 fn assert_false_trailing_comma() {
231 assert_false!(false,);
232 }
233 #[test]
234 fn assert_panics() {
235 assert_panics!({ panic!("I am panicing!") },);
236 }
237 #[test]
238 #[should_panic]
239 fn assert_panics_fails() {
240 assert_panics!({ println!("I am not panicing!") },);
241 }
242 #[test]
243 fn assert_panics_trailing_comma() {
244 assert_panics!({ panic!("I am panicing!") },);
245 }
246
247 #[test]
248 fn vector() {
249 assert_about_eq!(vec![1.1, 2.1], vec![1.1, 2.1]);
250 }
251
252 #[test]
253 #[should_panic]
254 fn vector_fails() {
255 assert_about_eq!(vec![1.2, 2.1], vec![1.1, 2.1]);
256 }
257
258 #[test]
259 fn vector_trailing_comma() {
260 assert_about_eq!(vec![1.2, 2.1], vec![1.2, 2.1],);
261 }
262
263 #[test]
264 fn vector_trailing_comma_with_epsilon() {
265 assert_about_eq!(vec![1.100000001, 2.1], vec![1.1, 2.1], 0.001f64,);
266 }
267
268 #[test]
269 fn it_should_not_panic_if_values_are_approx_equal() {
270 assert_about_eq!(64f32.sqrt(), 8f32);
271 }
272
273 #[test]
274 fn about_equal_f32() {
275 assert_about_eq!(3f32, 3f32, 1f64);
276 }
277
278 #[test]
279 fn about_equal_f64() {
280 assert_about_eq!(3f64, 3f64);
281 }
282
283 #[test]
284 fn compare_with_epsilon() {
285 assert_about_eq!(42f64, 43f64, 2f64);
286 }
287
288 #[test]
289 #[should_panic]
290 fn fail_with_epsilon() {
291 assert_about_eq!(3f64, 4f64, 1e-8f64);
292 }
293}