1#![cfg_attr(not(test), no_std)]
8
9#[cfg(test)]
11extern crate self as unittest;
12
13use core::ffi::{CStr, c_char};
14use core::slice;
15
16#[doc(hidden)]
17pub use zx_status::Status as __Status;
18#[doc(hidden)]
19pub use zx_status::sys as __sys;
20
21pub use unittest_macro::suite;
69
70use kprint::kprintln;
71
72#[doc(hidden)]
73#[derive(Debug, Clone, Copy)]
74pub struct ComparisonFailure<'a> {
75 pub file: &'a str,
76 pub line: u32,
77 pub expected: &'a str,
78 pub expected_val: isize,
79 pub op: &'a str,
80 pub actual: &'a str,
81 pub actual_val: isize,
82 pub msg: &'a str,
83}
84
85#[doc(hidden)]
86pub fn print_comparison_failure(failure: &ComparisonFailure<'_>) {
87 kprintln!(
88 "\n [FAILED]\n {:s}:{}:\n expected {:s} ({}) {:s} {:s} ({})\n {:s}",
89 failure.file,
90 failure.line,
91 failure.expected,
92 failure.expected_val,
93 failure.op,
94 failure.actual,
95 failure.actual_val,
96 failure.msg,
97 );
98}
99
100#[doc(hidden)]
101pub fn print_condition_failure(file: &str, line: u32, desc: &str, actual: &str, msg: &str) {
102 kprintln!(
103 "\n [FAILED]\n {:s}:{}:\n {:s} {:s}\n {:s}",
104 file,
105 line,
106 actual,
107 desc,
108 msg,
109 );
110}
111
112#[macro_export]
113#[doc(hidden)]
114macro_rules! check_comparison {
115 ($cond:expr, $early_return:expr, $op:literal, $expected:expr, $expected_val:expr, $actual:expr, $actual_val:expr, $msg:expr) => {
116 if !$cond {
117 record_failure!();
118 $crate::print_comparison_failure(&$crate::ComparisonFailure {
119 file: file!(),
120 line: line!(),
121 expected: stringify!($expected),
122 expected_val: $expected_val as isize,
123 op: $op,
124 actual: stringify!($actual),
125 actual_val: $actual_val as isize,
126 msg: $msg,
127 });
128 if $early_return {
129 return false;
130 }
131 }
132 };
133}
134
135#[macro_export]
136#[doc(hidden)]
137macro_rules! check_condition {
138 ($cond:expr, $early_return:expr, $desc:literal, $actual:expr, $msg:expr) => {
139 if !$cond {
140 record_failure!();
141 $crate::print_condition_failure(file!(), line!(), $desc, stringify!($actual), $msg);
142 if $early_return {
143 return false;
144 }
145 }
146 };
147}
148
149#[doc(hidden)]
153#[repr(C)]
154#[derive(Clone, Copy)]
155pub struct TestSuiteRegistration {
156 pub name: *const c_char,
157 pub desc: *const c_char,
158 pub tests: *const TestCaseRegistration,
159 pub test_cnt: usize,
160}
161
162unsafe impl Sync for TestSuiteRegistration {}
163
164impl TestSuiteRegistration {
165 pub fn name(&self) -> &'_ str {
170 assert!(!self.name.is_null(), "test suite registration has no name");
171 unsafe { CStr::from_ptr(self.name) }.to_str().expect("test suite name is not valid UTF-8")
173 }
174
175 pub fn desc(&self) -> Option<&'_ str> {
177 if self.desc.is_null() {
178 return None;
179 }
180 let desc = unsafe { CStr::from_ptr(self.desc) };
182 Some(desc.to_str().expect("test suite description is not valid UTF-8"))
183 }
184
185 pub fn cases(&self) -> &'_ [TestCaseRegistration] {
187 if self.test_cnt == 0 {
188 return &[];
189 }
190 assert!(!self.tests.is_null(), "test suite registration has tests but no test array");
191 unsafe { slice::from_raw_parts(self.tests, self.test_cnt) }
193 }
194}
195
196#[doc(hidden)]
200#[repr(C)]
201#[derive(Clone, Copy)]
202pub struct TestCaseRegistration {
203 pub name: *const c_char,
204 pub fn_: extern "C" fn() -> bool,
205}
206
207unsafe impl Sync for TestCaseRegistration {}
208
209impl TestCaseRegistration {
210 pub fn name(&self) -> &'_ str {
215 assert!(!self.name.is_null(), "test case registration has no name");
216 unsafe { CStr::from_ptr(self.name) }.to_str().expect("test case name is not valid UTF-8")
218 }
219}
220
221#[macro_export]
223macro_rules! expect_eq {
224 ($expected:expr, $actual:expr) => {
225 $crate::expect_eq!($expected, $actual, "")
226 };
227 ($expected:expr, $actual:expr, $msg:expr) => {
228 let e = $expected;
229 let a = $actual;
230 $crate::check_comparison!(e == a, false, "==", $expected, e, $actual, a, $msg);
231 };
232}
233
234#[macro_export]
236macro_rules! assert_eq {
237 ($expected:expr, $actual:expr) => {
238 $crate::assert_eq!($expected, $actual, "")
239 };
240 ($expected:expr, $actual:expr, $msg:expr) => {
241 let e = $expected;
242 let a = $actual;
243 $crate::check_comparison!(e == a, true, "==", $expected, e, $actual, a, $msg);
244 };
245}
246
247#[macro_export]
249macro_rules! expect_ne {
250 ($expected:expr, $actual:expr) => {
251 $crate::expect_ne!($expected, $actual, "")
252 };
253 ($expected:expr, $actual:expr, $msg:expr) => {
254 let e = $expected;
255 let a = $actual;
256 $crate::check_comparison!(e != a, false, "!=", $expected, e, $actual, a, $msg);
257 };
258}
259
260#[macro_export]
262macro_rules! assert_ne {
263 ($expected:expr, $actual:expr) => {
264 $crate::assert_ne!($expected, $actual, "")
265 };
266 ($expected:expr, $actual:expr, $msg:expr) => {
267 let e = $expected;
268 let a = $actual;
269 $crate::check_comparison!(e != a, true, "!=", $expected, e, $actual, a, $msg);
270 };
271}
272
273#[macro_export]
275macro_rules! expect_lt {
276 ($expected:expr, $actual:expr) => {
277 $crate::expect_lt!($expected, $actual, "")
278 };
279 ($expected:expr, $actual:expr, $msg:expr) => {
280 let e = $expected;
281 let a = $actual;
282 $crate::check_comparison!(e < a, false, "<", $expected, e, $actual, a, $msg);
283 };
284}
285
286#[macro_export]
288macro_rules! assert_lt {
289 ($expected:expr, $actual:expr) => {
290 $crate::assert_lt!($expected, $actual, "")
291 };
292 ($expected:expr, $actual:expr, $msg:expr) => {
293 let e = $expected;
294 let a = $actual;
295 $crate::check_comparison!(e < a, true, "<", $expected, e, $actual, a, $msg);
296 };
297}
298
299#[macro_export]
301macro_rules! expect_le {
302 ($expected:expr, $actual:expr) => {
303 $crate::expect_le!($expected, $actual, "")
304 };
305 ($expected:expr, $actual:expr, $msg:expr) => {
306 let e = $expected;
307 let a = $actual;
308 $crate::check_comparison!(e <= a, false, "<=", $expected, e, $actual, a, $msg);
309 };
310}
311
312#[macro_export]
314macro_rules! assert_le {
315 ($expected:expr, $actual:expr) => {
316 $crate::assert_le!($expected, $actual, "")
317 };
318 ($expected:expr, $actual:expr, $msg:expr) => {
319 let e = $expected;
320 let a = $actual;
321 $crate::check_comparison!(e <= a, true, "<=", $expected, e, $actual, a, $msg);
322 };
323}
324
325#[macro_export]
327macro_rules! expect_gt {
328 ($expected:expr, $actual:expr) => {
329 $crate::expect_gt!($expected, $actual, "")
330 };
331 ($expected:expr, $actual:expr, $msg:expr) => {
332 let e = $expected;
333 let a = $actual;
334 $crate::check_comparison!(e > a, false, ">", $expected, e, $actual, a, $msg);
335 };
336}
337
338#[macro_export]
340macro_rules! assert_gt {
341 ($expected:expr, $actual:expr) => {
342 $crate::assert_gt!($expected, $actual, "")
343 };
344 ($expected:expr, $actual:expr, $msg:expr) => {
345 let e = $expected;
346 let a = $actual;
347 $crate::check_comparison!(e > a, true, ">", $expected, e, $actual, a, $msg);
348 };
349}
350
351#[macro_export]
353macro_rules! expect_ge {
354 ($expected:expr, $actual:expr) => {
355 $crate::expect_ge!($expected, $actual, "")
356 };
357 ($expected:expr, $actual:expr, $msg:expr) => {
358 let e = $expected;
359 let a = $actual;
360 $crate::check_comparison!(e >= a, false, ">=", $expected, e, $actual, a, $msg);
361 };
362}
363
364#[macro_export]
366macro_rules! assert_ge {
367 ($expected:expr, $actual:expr) => {
368 $crate::assert_ge!($expected, $actual, "")
369 };
370 ($expected:expr, $actual:expr, $msg:expr) => {
371 let e = $expected;
372 let a = $actual;
373 $crate::check_comparison!(e >= a, true, ">=", $expected, e, $actual, a, $msg);
374 };
375}
376
377#[macro_export]
379macro_rules! expect_true {
380 ($actual:expr) => {
381 $crate::expect_true!($actual, "")
382 };
383 ($actual:expr, $msg:expr) => {
384 let a = $actual;
385 $crate::check_condition!(a, false, "is false", $actual, $msg);
386 };
387}
388
389#[macro_export]
391macro_rules! assert_true {
392 ($actual:expr) => {
393 $crate::assert_true!($actual, "")
394 };
395 ($actual:expr, $msg:expr) => {
396 let a = $actual;
397 $crate::check_condition!(a, true, "is false", $actual, $msg);
398 };
399}
400
401#[macro_export]
403macro_rules! expect_false {
404 ($actual:expr) => {
405 $crate::expect_false!($actual, "")
406 };
407 ($actual:expr, $msg:expr) => {
408 let a = $actual;
409 $crate::check_condition!(!a, false, "is true", $actual, $msg);
410 };
411}
412
413#[macro_export]
415macro_rules! assert_false {
416 ($actual:expr) => {
417 $crate::assert_false!($actual, "")
418 };
419 ($actual:expr, $msg:expr) => {
420 let a = $actual;
421 $crate::check_condition!(!a, true, "is true", $actual, $msg);
422 };
423}
424
425#[macro_export]
427macro_rules! expect_null {
428 ($actual:expr) => {
429 $crate::expect_null!($actual, "")
430 };
431 ($actual:expr, $msg:expr) => {
432 let a = $actual;
433 $crate::check_condition!(a.is_null(), false, "is non-null!", $actual, $msg);
434 };
435}
436
437#[macro_export]
439macro_rules! assert_null {
440 ($actual:expr) => {
441 $crate::assert_null!($actual, "")
442 };
443 ($actual:expr, $msg:expr) => {
444 let a = $actual;
445 $crate::check_condition!(a.is_null(), true, "is non-null!", $actual, $msg);
446 };
447}
448
449#[macro_export]
451macro_rules! expect_nonnull {
452 ($actual:expr) => {
453 $crate::expect_nonnull!($actual, "")
454 };
455 ($actual:expr, $msg:expr) => {
456 let a = $actual;
457 $crate::check_condition!(!a.is_null(), false, "is null!", $actual, $msg);
458 };
459}
460
461#[macro_export]
463macro_rules! assert_nonnull {
464 ($actual:expr) => {
465 $crate::assert_nonnull!($actual, "")
466 };
467 ($actual:expr, $msg:expr) => {
468 let a = $actual;
469 $crate::check_condition!(!a.is_null(), true, "is null!", $actual, $msg);
470 };
471}
472
473#[doc(hidden)]
474pub fn status_name_and_raw<T>(res: Result<T, __Status>) -> (&'static str, core::ffi::c_int) {
475 match res {
476 Ok(_) => ("OK", __sys::ZX_OK),
477 Err(err) => (err.as_str(), err.into_raw()),
478 }
479}
480
481#[doc(hidden)]
482pub fn print_status_comparison_failure<T>(
483 file: &str,
484 line: u32,
485 expected: &str,
486 expected_status: Result<T, __Status>,
487 actual: &str,
488 actual_status: Result<T, __Status>,
489 msg: &str,
490) {
491 let (expected_name, expected_raw) = status_name_and_raw(expected_status);
492 let (actual_name, actual_raw) = status_name_and_raw(actual_status);
493 kprintln!(
494 "\n [FAILED]\n {:s}:{}:\n expected {:s} ({:s}, {}) == {:s} ({:s}, {})\n {:s}",
495 file,
496 line,
497 expected,
498 expected_name,
499 expected_raw,
500 actual,
501 actual_name,
502 actual_raw,
503 msg,
504 );
505}
506
507#[macro_export]
508#[doc(hidden)]
509macro_rules! check_status_comparison {
510 (
511 $cond:expr,
512 $early_return:expr,
513 $expected_expr:expr,
514 $expected_status:expr,
515 $actual_expr:expr,
516 $actual_status:expr,
517 $msg:expr
518 ) => {
519 if !$cond {
520 record_failure!();
521 $crate::print_status_comparison_failure(
522 file!(),
523 line!(),
524 stringify!($expected_expr),
525 $expected_status,
526 stringify!($actual_expr),
527 $actual_status,
528 $msg,
529 );
530 if $early_return {
531 return false;
532 }
533 }
534 };
535}
536
537#[macro_export]
539macro_rules! expect_ok {
540 ($actual:expr) => {
541 $crate::expect_ok!($actual, "")
542 };
543 ($actual:expr, $msg:expr) => {
544 let a: Result<(), ::unittest::__Status> = $actual.into();
545 $crate::check_status_comparison!(a.is_ok(), false, "Ok(())", Ok(()), $actual, a, $msg);
546 };
547}
548
549#[macro_export]
551macro_rules! assert_ok {
552 ($actual:expr) => {
553 $crate::assert_ok!($actual, "")
554 };
555 ($actual:expr, $msg:expr) => {
556 let a: Result<(), ::unittest::__Status> = $actual.into();
557 $crate::check_status_comparison!(a.is_ok(), true, "Ok(())", Ok(()), $actual, a, $msg);
558 };
559}
560
561#[macro_export]
564macro_rules! expect_err {
565 ($actual:expr, $expected_err:expr) => {
566 $crate::expect_err!($actual, $expected_err, "")
567 };
568 ($actual:expr, $expected_err:expr, $msg:expr) => {
569 let a: Result<_, ::unittest::__Status> = $actual.into();
570 let e: ::unittest::__Status = $expected_err.into();
571 $crate::check_status_comparison!(
572 a.as_ref().is_err_and(|err| *err == e),
573 false,
574 $expected_err,
575 Err(e),
576 $actual,
577 a,
578 $msg
579 );
580 };
581}
582
583#[macro_export]
586macro_rules! assert_err {
587 ($actual:expr, $expected_err:expr) => {
588 $crate::assert_err!($actual, $expected_err, "")
589 };
590 ($actual:expr, $expected_err:expr, $msg:expr) => {
591 let a: Result<_, ::unittest::__Status> = $actual.into();
592 let e: ::unittest::__Status = $expected_err.into();
593 $crate::check_status_comparison!(
594 a.as_ref().is_err_and(|err| *err == e),
595 true,
596 $expected_err,
597 Err(e),
598 $actual,
599 a,
600 $msg
601 );
602 };
603}
604
605#[macro_export]
608macro_rules! unwrap_ok {
609 ($actual:expr) => {
610 $crate::unwrap_ok!($actual, "")
611 };
612 ($actual:expr, $msg:expr) => {
613 match ($actual) {
614 Ok(r) => r,
615 Err(err) => {
616 let err: ::unittest::__Status = err.into();
617 $crate::check_status_comparison!(
618 false,
619 true,
620 "Ok(())",
621 Ok(()),
622 $actual,
623 Err(err),
624 $msg
625 );
626 return false;
627 }
628 }
629 };
630}
631
632#[macro_export]
635macro_rules! unwrap_some {
636 ($actual:expr) => {
637 $crate::unwrap_some!($actual, "")
638 };
639 ($actual:expr, $msg:expr) => {
640 match ($actual) {
641 Option::Some(val) => val,
642 Option::None => {
643 $crate::check_condition!(false, true, "is None!", $actual, $msg);
644 return false;
645 }
646 }
647 };
648}
649
650#[macro_export]
658macro_rules! subtest {
659 (|$($param:ident : $ty:ty),* $(,)?| $body:block) => {
660 |$($param : $ty),*| -> bool {
661 #[allow(unused_mut)]
663 let mut all_ok = true;
664 macro_rules! record_failure {
665 () => {
666 #[allow(unused_assignments)]
668 {
669 all_ok = false;
670 }
671 };
672 }
673 $body
674 all_ok
675 }
676 };
677}
678
679#[cfg(test)]
682mod tests {
683 use core::ffi::CStr;
684 use core::{ptr, slice};
685 use std::cell::Cell;
686 use std::vec::Vec;
687
688 use super::{TestSuiteRegistration, suite};
689
690 unsafe extern "C" {
691 static __start_unittest_testcases: TestSuiteRegistration;
692 static __stop_unittest_testcases: TestSuiteRegistration;
693 }
694
695 thread_local! {
697 static END_REACHED: Cell<bool> = Cell::new(false);
698 }
699
700 fn mark_end_as_reached() {
701 END_REACHED.with(|cell| cell.set(true));
702 }
703
704 fn mark_end_as_not_reached() {
705 END_REACHED.with(|cell| cell.set(false));
706 }
707
708 fn expect_end_reached() {
709 std::assert_eq!(END_REACHED.with(|cell| cell.get()), true);
710 }
711
712 fn expect_end_not_reached() {
713 std::assert_eq!(END_REACHED.with(|cell| cell.get()), false);
714 }
715
716 fn get_suites() -> Vec<TestSuiteRegistration> {
717 let start = unsafe { &__start_unittest_testcases as *const TestSuiteRegistration };
718 let stop = unsafe { &__stop_unittest_testcases as *const TestSuiteRegistration };
719
720 let count = unsafe { stop.offset_from(start) } as usize;
721
722 let suites_rodata = unsafe { slice::from_raw_parts(start, count) };
723
724 let mut suites = Vec::from(suites_rodata);
725
726 suites.sort_by(|a, b| {
727 let a_name = unsafe { CStr::from_ptr(a.name) };
728 let b_name = unsafe { CStr::from_ptr(b.name) };
729 a_name.cmp(b_name)
730 });
731 suites
732 }
733
734 #[suite(name = "one_function")]
736 mod suite_with_one_function {
737 #[test]
739 fn empty() {}
740 }
741
742 #[suite]
744 mod suite_with_other_items {
745 use std::vec;
746
747 trait Countable {
748 fn count(&self) -> usize;
749 }
750
751 impl<T> Countable for Vec<T> {
752 fn count(&self) -> usize {
753 self.len()
754 }
755 }
756
757 fn get_count<T: Countable>(countable: T) -> usize {
758 countable.count()
759 }
760
761 #[test]
763 fn check_other_items() {
764 let v = vec![1, 2, 3];
765 expect_eq!(get_count(v), 3);
766 }
767 }
768
769 #[suite(name = "with_ignored")]
771 mod suite_with_ignored {
772 #[ignore]
774 #[test]
775 fn ignored_test() {
776 assert_true!(false);
777 }
778
779 #[test]
781 fn normal_test() {}
782 }
783
784 #[suite]
786 mod assertions {
787 #[test]
789 fn test_success() {
790 assert_eq!(1, 1);
791 assert_ne!(1, 2);
792 assert_lt!(1, 2);
793 assert_le!(1, 1);
794 assert_gt!(2, 1);
795 assert_ge!(2, 2);
796
797 assert_true!(true);
798 assert_false!(false);
799
800 let null_ptr: *const i32 = ptr::null();
801 let nonnull_ptr: *const i32 = &42 as *const i32;
802 assert_null!(null_ptr);
803 assert_nonnull!(nonnull_ptr);
804
805 assert_ok!(Ok::<(), zx_status::Status>(()));
806 assert_err!(
807 Err::<(), _>(zx_status::Status::INVALID_ARGS),
808 zx_status::Status::INVALID_ARGS
809 );
810 assert_err!(zx_status::Status::INVALID_ARGS, zx_status::Status::INVALID_ARGS);
811
812 let _ = unwrap_ok!(Ok::<(), zx_status::Status>(()));
813 let _ = unwrap_some!(Some(42));
814
815 mark_end_as_reached();
816 }
817
818 #[test]
820 fn fail_assert_eq() {
821 assert_eq!(1, 2);
822 mark_end_as_reached();
823 }
824
825 #[test]
827 fn fail_assert_ne() {
828 assert_ne!(1, 1);
829 mark_end_as_reached();
830 }
831
832 #[test]
834 fn fail_assert_lt() {
835 assert_lt!(2, 1);
836 mark_end_as_reached();
837 }
838
839 #[test]
841 fn fail_assert_le() {
842 assert_le!(2, 1);
843 mark_end_as_reached();
844 }
845
846 #[test]
848 fn fail_assert_gt() {
849 assert_gt!(1, 2);
850 mark_end_as_reached();
851 }
852
853 #[test]
855 fn fail_assert_ge() {
856 assert_ge!(1, 2);
857 mark_end_as_reached();
858 }
859
860 #[test]
862 fn fail_assert_true() {
863 assert_true!(false);
864 mark_end_as_reached();
865 }
866
867 #[test]
869 fn fail_assert_false() {
870 assert_false!(true);
871 mark_end_as_reached();
872 }
873
874 #[test]
876 fn fail_assert_null() {
877 assert_null!(&42 as *const i32);
878 mark_end_as_reached();
879 }
880
881 #[test]
883 fn fail_assert_nonnull() {
884 assert_nonnull!(ptr::null::<i32>());
885 mark_end_as_reached();
886 }
887
888 #[test]
890 fn fail_assert_ok() {
891 assert_ok!(Err::<(), _>(zx_status::Status::INTERNAL));
892 mark_end_as_reached();
893 }
894
895 #[test]
897 fn fail_assert_err() {
898 assert_err!(Ok::<(), _>(()), zx_status::Status::INTERNAL);
899 mark_end_as_reached();
900 }
901
902 #[test]
904 fn test_unwrap_ok() {
905 let _: () = unwrap_ok!(Err(zx_status::Status::INTERNAL));
906 mark_end_as_reached();
907 }
908
909 #[test]
911 fn test_unwrap_some() {
912 let _: () = unwrap_some!(None::<()>);
913 mark_end_as_reached();
914 }
915 }
916
917 #[suite]
919 mod expectations {
920 #[test]
922 fn test_success() {
923 expect_eq!(1, 1);
924 expect_eq!(1, 1, "one should be one");
925 expect_ne!(1, 2);
926 expect_ne!(1, 2, "one should not be two");
927 expect_lt!(1, 2);
928 expect_lt!(1, 2, "one should be less than two");
929 expect_le!(1, 1);
930 expect_le!(1, 2);
931 expect_gt!(2, 1);
932 expect_ge!(2, 2);
933
934 expect_true!(true);
935 expect_true!(true, "should be true");
936 expect_false!(false);
937 expect_false!(false, "should be false");
938
939 let null_ptr: *const i32 = ptr::null();
940 let nonnull_ptr: *const i32 = &42 as *const i32;
941 expect_null!(null_ptr);
942 expect_null!(null_ptr, "should be null");
943 expect_nonnull!(nonnull_ptr);
944 expect_nonnull!(nonnull_ptr, "should be non-null");
945
946 expect_ok!(Ok::<(), zx_status::Status>(()));
947 expect_ok!(Ok::<(), zx_status::Status>(()), "should be OK");
948 expect_err!(
949 Err::<(), _>(zx_status::Status::INVALID_ARGS),
950 zx_status::Status::INVALID_ARGS
951 );
952 expect_err!(
953 zx_status::Status::INVALID_ARGS,
954 zx_status::Status::INVALID_ARGS,
955 "should be INVALID_ARGS"
956 );
957
958 mark_end_as_reached();
959 }
960
961 #[test]
963 fn fail_expect_eq() {
964 expect_eq!(1, 2);
965 mark_end_as_reached();
966 }
967
968 #[test]
970 fn fail_expect_ne() {
971 expect_ne!(1, 1);
972 mark_end_as_reached();
973 }
974
975 #[test]
977 fn fail_expect_lt() {
978 expect_lt!(2, 1);
979 mark_end_as_reached();
980 }
981
982 #[test]
984 fn fail_expect_le() {
985 expect_le!(2, 1);
986 mark_end_as_reached();
987 }
988
989 #[test]
991 fn fail_expect_gt() {
992 expect_gt!(1, 2);
993 mark_end_as_reached();
994 }
995
996 #[test]
998 fn fail_expect_ge() {
999 expect_ge!(1, 2);
1000 mark_end_as_reached();
1001 }
1002
1003 #[test]
1005 fn fail_expect_true() {
1006 expect_true!(false);
1007 mark_end_as_reached();
1008 }
1009
1010 #[test]
1012 fn fail_expect_false() {
1013 expect_false!(true);
1014 mark_end_as_reached();
1015 }
1016
1017 #[test]
1019 fn fail_expect_null() {
1020 expect_null!(&42 as *const i32);
1021 mark_end_as_reached();
1022 }
1023
1024 #[test]
1026 fn fail_expect_nonnull() {
1027 expect_nonnull!(ptr::null::<i32>());
1028 mark_end_as_reached();
1029 }
1030
1031 #[test]
1033 fn fail_expect_ok() {
1034 expect_ok!(zx_status::Status::INTERNAL);
1035 mark_end_as_reached();
1036 }
1037
1038 #[test]
1040 fn fail_expect_err() {
1041 expect_err!(Ok::<(), _>(()), zx_status::Status::INTERNAL);
1042 mark_end_as_reached();
1043 }
1044 }
1045
1046 #[suite(name = "subtests")]
1048 mod subtests {
1049 #[test]
1051 fn test_shadowing() {
1052 let failing = subtest!(|should_fail: bool| {
1053 if should_fail {
1054 record_failure!();
1055 }
1056 });
1057 expect_false!(failing(true));
1058 expect_true!(failing(false));
1059 }
1060 }
1061
1062 #[test]
1063 fn check_suite_count() {
1064 let suites = get_suites();
1065 std::assert_eq!(suites.len(), 6);
1066 }
1067
1068 #[test]
1069 fn check_suite_assertions() {
1070 let suites = get_suites();
1071 std::assert!(suites.len() > 0);
1072 let suite = &suites[0];
1073
1074 std::assert_eq!(unsafe { CStr::from_ptr(suite.name) }.to_bytes(), b"assertions");
1075 std::assert_eq!(suite.test_cnt, 15);
1076
1077 let cases_rodata = unsafe { slice::from_raw_parts(suite.tests, suite.test_cnt) };
1078 for case in cases_rodata {
1079 mark_end_as_not_reached();
1080 let name = unsafe { CStr::from_ptr(case.name) }.to_str().unwrap();
1081 let res = (case.fn_)();
1082 if name == "test_success" {
1083 std::assert_eq!(res, true, "assertions::test_success should pass");
1084 expect_end_reached();
1085 } else {
1086 std::assert_eq!(res, false, "assertions::{} should fail", name);
1087 expect_end_not_reached();
1088 }
1089 }
1090 }
1091
1092 #[test]
1093 fn check_suite_expectations() {
1094 let suites = get_suites();
1095 std::assert!(suites.len() > 1);
1096 let suite = &suites[1];
1097
1098 std::assert_eq!(unsafe { CStr::from_ptr(suite.name) }.to_bytes(), b"expectations");
1099 std::assert_eq!(suite.test_cnt, 13);
1100
1101 let cases = unsafe { slice::from_raw_parts(suite.tests, suite.test_cnt) };
1102 for case in cases {
1103 mark_end_as_not_reached();
1104 let name = unsafe { CStr::from_ptr(case.name) }.to_str().unwrap();
1105 let res = (case.fn_)();
1106 if name == "test_success" {
1107 std::assert_eq!(res, true, "expectations::test_success should pass");
1108 } else {
1109 std::assert_eq!(res, false, "expectations::{} should fail", name);
1110 }
1111 expect_end_reached();
1112 }
1113 }
1114
1115 #[test]
1116 fn check_suite_with_one_function() {
1117 let suites = get_suites();
1118 std::assert!(suites.len() > 2);
1119 let suite = &suites[2];
1120
1121 std::assert_eq!(unsafe { CStr::from_ptr(suite.name) }.to_bytes(), b"one_function");
1122 std::assert_eq!(
1123 unsafe { CStr::from_ptr(suite.desc) }.to_str().unwrap(),
1124 "Suite with one function description."
1125 );
1126 std::assert_eq!(suite.test_cnt, 1);
1127 let case = unsafe { &*suite.tests };
1128 std::assert_eq!(unsafe { CStr::from_ptr(case.name) }.to_bytes(), b"empty");
1129 assert!((case.fn_)());
1130 }
1131
1132 #[test]
1133 fn check_suite_subtests() {
1134 let suites = get_suites();
1135 std::assert!(suites.len() > 3);
1136 let suite = &suites[3];
1137
1138 std::assert_eq!(unsafe { CStr::from_ptr(suite.name) }.to_bytes(), b"subtests");
1139 std::assert_eq!(
1140 unsafe { CStr::from_ptr(suite.desc) }.to_str().unwrap(),
1141 "Subtests description."
1142 );
1143 std::assert_eq!(suite.test_cnt, 1);
1144 let case = unsafe { &*suite.tests };
1145 std::assert_eq!(unsafe { CStr::from_ptr(case.name) }.to_bytes(), b"test_shadowing");
1146 assert!((case.fn_)());
1147 }
1148
1149 #[test]
1150 fn check_suite_with_other_items() {
1151 let suites = get_suites();
1152 std::assert!(suites.len() > 4);
1153 let suite = &suites[4];
1154
1155 std::assert_eq!(
1156 unsafe { CStr::from_ptr(suite.name) }.to_bytes(),
1157 b"suite_with_other_items"
1158 );
1159 std::assert_eq!(
1160 unsafe { CStr::from_ptr(suite.desc) }.to_str().unwrap(),
1161 "Suite with non-test items."
1162 );
1163 std::assert_eq!(suite.test_cnt, 1);
1164 let case = unsafe { &*suite.tests };
1165 std::assert_eq!(unsafe { CStr::from_ptr(case.name) }.to_bytes(), b"check_other_items");
1166 assert!((case.fn_)());
1167 }
1168
1169 #[test]
1170 fn check_suite_with_ignored() {
1171 let suites = get_suites();
1172 std::assert!(suites.len() > 5);
1173 let suite = &suites[5];
1174
1175 std::assert_eq!(unsafe { CStr::from_ptr(suite.name) }.to_bytes(), b"with_ignored");
1176 std::assert_eq!(suite.test_cnt, 1);
1177 let case = unsafe { &*suite.tests };
1178 std::assert_eq!(unsafe { CStr::from_ptr(case.name) }.to_bytes(), b"normal_test");
1179 }
1180}