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