Skip to main content

unittest/
lib.rs

1// Copyright 2026 The Fuchsia Authors
2//
3// Use of this source code is governed by a MIT-style
4// license that can be found in the LICENSE file or at
5// https://opensource.org/licenses/MIT
6
7#![cfg_attr(not(test), no_std)]
8
9// Allows for the test_suite macro to work within this crate's test module.
10#[cfg(test)]
11extern crate self as unittest;
12
13#[cfg(feature = "kernel")]
14mod user_memory;
15#[cfg(feature = "kernel")]
16pub use user_memory::UserMemory;
17
18use core::ffi::c_char;
19
20#[doc(hidden)]
21pub use zx_status::Status as __Status;
22
23/// Attribute macro defining suite of unit tests defined as module. The
24/// attribute may only be used in a cfg(ktest) context.
25///
26/// Tests are idiomatically modeled as functions, and so modules of such
27/// functions make for a natural representation as a test suite.
28///
29/// Tests defined through this attribute are available to be run via `k ut`.
30///
31/// A test suite module must meet the following criteria:
32/// * It must have a one-line docstring. This line becomes the description of
33///   the suite on the kernel command-line.
34/// * It must contain at least one test function; it may contain any other items.
35///
36/// A test function must meet the following criteria:
37/// * It must be annotated with #[test].
38/// * It too must have a one-line docstring. This line becomes the description
39///   of the test on the kernel command-line.
40/// * It must have a () -> () signature.
41///
42/// A test function should make assertions only using the declarative
43/// assert_*/expect_* macros defined in the unittest module.
44///
45/// Disabling a test can be done with a further annotation of #[ignore]. Such a
46/// test will still be compiled; it just will not contribute test metadata.
47///
48/// # Example
49/// ```rust
50/// /// Brief test suite description.
51/// #[cfg(ktest)]
52/// #[test_suite(name = "optional_name")]
53/// mod my_suite {
54///     /* non-test items... */
55///
56///     /// Brief test case description.
57///     #[test]
58///     fn my_case() {
59///         assert_false!(false);
60///         expect_true!(1 == 1, "expectation with a message");
61///     }
62///
63///     /// This test case is currently disabled.
64///     #[test]
65///     #[ignore]
66///     fn my_disabled_case() {...}
67/// }
68/// ```
69///
70pub use unittest_macro::test_suite;
71
72// We leverage libc for printing for now. Once all unittests are in Rust we can
73// revisit how printing should work here.
74unsafe extern "C" {
75    pub fn printf(format: *const c_char, ...) -> core::ffi::c_int;
76}
77
78#[macro_export]
79#[doc(hidden)]
80macro_rules! c_str_lit {
81    ($s:expr) => {
82        concat!($s, "\0").as_ptr() as *const core::ffi::c_char
83    };
84}
85
86#[macro_export]
87#[doc(hidden)]
88macro_rules! check_comparison {
89    ($cond:expr, $early_return:expr, $op:literal, $expected:expr, $expected_val:expr, $actual:expr, $actual_val:expr, $msg:expr) => {
90        if !$cond {
91            record_failure!();
92            let format = $crate::failed_format!(concat!("expected %s (%ld) ", $op, " %s (%ld)"));
93            let file_c_str = $crate::c_str_lit!(file!());
94            let expected_str = $crate::c_str_lit!(stringify!($expected));
95            let actual_str = $crate::c_str_lit!(stringify!($actual));
96            let msg_c_str = $crate::c_str_lit!($msg);
97            unsafe {
98                $crate::printf(
99                    format,
100                    file_c_str,
101                    line!() as core::ffi::c_int,
102                    expected_str,
103                    $expected_val as isize,
104                    actual_str,
105                    $actual_val as isize,
106                    msg_c_str,
107                );
108            }
109            if $early_return {
110                return false;
111            }
112        }
113    };
114}
115
116#[macro_export]
117#[doc(hidden)]
118macro_rules! check_condition {
119    ($cond:expr, $early_return:expr, $desc:literal, $actual:expr, $msg:expr) => {
120        if !$cond {
121            record_failure!();
122            let format = $crate::failed_format!($desc);
123            let file_c_str = $crate::c_str_lit!(file!());
124            let actual_str = $crate::c_str_lit!(stringify!($actual));
125            let msg_c_str = $crate::c_str_lit!($msg);
126            unsafe {
127                $crate::printf(
128                    format,
129                    file_c_str,
130                    line!() as core::ffi::c_int,
131                    actual_str,
132                    msg_c_str,
133                );
134            }
135            if $early_return {
136                return false;
137            }
138        }
139    };
140}
141
142#[macro_export]
143#[doc(hidden)]
144macro_rules! failed_format {
145    ($body:expr) => {
146        $crate::c_str_lit!(concat!(
147            "\n",
148            "    [FAILED]\n",
149            "    %s:%d:\n",
150            "    ",
151            $body,
152            "\n",
153            "    %s\n"
154        ))
155    };
156}
157
158/// The data structure that statically defines a test suite, intended to be
159/// defined via the #[test_suite] macro to encoded into a special section in
160/// the kernel.
161#[doc(hidden)]
162#[repr(C)]
163#[derive(Clone, Copy)]
164pub struct TestSuiteRegistration {
165    pub name: *const c_char,
166    pub desc: *const c_char,
167    pub tests: *const TestCaseRegistration,
168    pub test_cnt: usize,
169}
170
171unsafe impl Sync for TestSuiteRegistration {}
172
173/// The data structure defining a test case within a suite, also intended be
174/// defined via the #[test_suite] macro to encoded into a special section in
175/// the kernel
176#[doc(hidden)]
177#[repr(C)]
178#[derive(Clone, Copy)]
179pub struct TestCaseRegistration {
180    pub name: *const c_char,
181    pub fn_: extern "C" fn() -> bool,
182}
183
184unsafe impl Sync for TestCaseRegistration {}
185
186/// Asserts that two expressions are equal, but does not short-circuit on failure.
187#[macro_export]
188macro_rules! expect_eq {
189    ($expected:expr, $actual:expr) => {
190        $crate::expect_eq!($expected, $actual, "")
191    };
192    ($expected:expr, $actual:expr, $msg:expr) => {
193        let e = $expected;
194        let a = $actual;
195        $crate::check_comparison!(e == a, false, "==", $expected, e, $actual, a, $msg);
196    };
197}
198
199/// Asserts that two expressions are equal and short-circuits on failure.
200#[macro_export]
201macro_rules! assert_eq {
202    ($expected:expr, $actual:expr) => {
203        $crate::assert_eq!($expected, $actual, "")
204    };
205    ($expected:expr, $actual:expr, $msg:expr) => {
206        let e = $expected;
207        let a = $actual;
208        $crate::check_comparison!(e == a, true, "==", $expected, e, $actual, a, $msg);
209    };
210}
211
212/// Asserts that two expressions are not equal, but does not short-circuit on failure.
213#[macro_export]
214macro_rules! expect_ne {
215    ($expected:expr, $actual:expr) => {
216        $crate::expect_ne!($expected, $actual, "")
217    };
218    ($expected:expr, $actual:expr, $msg:expr) => {
219        let e = $expected;
220        let a = $actual;
221        $crate::check_comparison!(e != a, false, "!=", $expected, e, $actual, a, $msg);
222    };
223}
224
225/// Asserts that two expressions are not equal and short-circuits on failure.
226#[macro_export]
227macro_rules! assert_ne {
228    ($expected:expr, $actual:expr) => {
229        $crate::assert_ne!($expected, $actual, "")
230    };
231    ($expected:expr, $actual:expr, $msg:expr) => {
232        let e = $expected;
233        let a = $actual;
234        $crate::check_comparison!(e != a, true, "!=", $expected, e, $actual, a, $msg);
235    };
236}
237
238/// Asserts that the first expression is less than the second, but does not short-circuit on failure.
239#[macro_export]
240macro_rules! expect_lt {
241    ($expected:expr, $actual:expr) => {
242        $crate::expect_lt!($expected, $actual, "")
243    };
244    ($expected:expr, $actual:expr, $msg:expr) => {
245        let e = $expected;
246        let a = $actual;
247        $crate::check_comparison!(e < a, false, "<", $expected, e, $actual, a, $msg);
248    };
249}
250
251/// Asserts that the first expression is less than the second and short-circuits on failure.
252#[macro_export]
253macro_rules! assert_lt {
254    ($expected:expr, $actual:expr) => {
255        $crate::assert_lt!($expected, $actual, "")
256    };
257    ($expected:expr, $actual:expr, $msg:expr) => {
258        let e = $expected;
259        let a = $actual;
260        $crate::check_comparison!(e < a, true, "<", $expected, e, $actual, a, $msg);
261    };
262}
263
264/// Asserts that the first expression is less than or equal to the second, but does not short-circuit on failure.
265#[macro_export]
266macro_rules! expect_le {
267    ($expected:expr, $actual:expr) => {
268        $crate::expect_le!($expected, $actual, "")
269    };
270    ($expected:expr, $actual:expr, $msg:expr) => {
271        let e = $expected;
272        let a = $actual;
273        $crate::check_comparison!(e <= a, false, "<=", $expected, e, $actual, a, $msg);
274    };
275}
276
277/// Asserts that the first expression is less than or equal to the second and short-circuits on failure.
278#[macro_export]
279macro_rules! assert_le {
280    ($expected:expr, $actual:expr) => {
281        $crate::assert_le!($expected, $actual, "")
282    };
283    ($expected:expr, $actual:expr, $msg:expr) => {
284        let e = $expected;
285        let a = $actual;
286        $crate::check_comparison!(e <= a, true, "<=", $expected, e, $actual, a, $msg);
287    };
288}
289
290/// Asserts that the first expression is greater than the second, but does not short-circuit on failure.
291#[macro_export]
292macro_rules! expect_gt {
293    ($expected:expr, $actual:expr) => {
294        $crate::expect_gt!($expected, $actual, "")
295    };
296    ($expected:expr, $actual:expr, $msg:expr) => {
297        let e = $expected;
298        let a = $actual;
299        $crate::check_comparison!(e > a, false, ">", $expected, e, $actual, a, $msg);
300    };
301}
302
303/// Asserts that the first expression is greater than the second and short-circuits on failure.
304#[macro_export]
305macro_rules! assert_gt {
306    ($expected:expr, $actual:expr) => {
307        $crate::assert_gt!($expected, $actual, "")
308    };
309    ($expected:expr, $actual:expr, $msg:expr) => {
310        let e = $expected;
311        let a = $actual;
312        $crate::check_comparison!(e > a, true, ">", $expected, e, $actual, a, $msg);
313    };
314}
315
316/// Asserts that the first expression is greater than or equal to the second, but does not short-circuit on failure.
317#[macro_export]
318macro_rules! expect_ge {
319    ($expected:expr, $actual:expr) => {
320        $crate::expect_ge!($expected, $actual, "")
321    };
322    ($expected:expr, $actual:expr, $msg:expr) => {
323        let e = $expected;
324        let a = $actual;
325        $crate::check_comparison!(e >= a, false, ">=", $expected, e, $actual, a, $msg);
326    };
327}
328
329/// Asserts that the first expression is greater than or equal to the second and short-circuits on failure.
330#[macro_export]
331macro_rules! assert_ge {
332    ($expected:expr, $actual:expr) => {
333        $crate::assert_ge!($expected, $actual, "")
334    };
335    ($expected:expr, $actual:expr, $msg:expr) => {
336        let e = $expected;
337        let a = $actual;
338        $crate::check_comparison!(e >= a, true, ">=", $expected, e, $actual, a, $msg);
339    };
340}
341
342/// Asserts that the expression evaluates to true, but does not short-circuit on failure.
343#[macro_export]
344macro_rules! expect_true {
345    ($actual:expr) => {
346        $crate::expect_true!($actual, "")
347    };
348    ($actual:expr, $msg:expr) => {
349        let a = $actual;
350        $crate::check_condition!(a, false, "%s is false", $actual, $msg);
351    };
352}
353
354/// Asserts that the expression evaluates to true and short-circuits on failure.
355#[macro_export]
356macro_rules! assert_true {
357    ($actual:expr) => {
358        $crate::assert_true!($actual, "")
359    };
360    ($actual:expr, $msg:expr) => {
361        let a = $actual;
362        $crate::check_condition!(a, true, "%s is false", $actual, $msg);
363    };
364}
365
366/// Asserts that the expression evaluates to false, but does not short-circuit on failure.
367#[macro_export]
368macro_rules! expect_false {
369    ($actual:expr) => {
370        $crate::expect_false!($actual, "")
371    };
372    ($actual:expr, $msg:expr) => {
373        let a = $actual;
374        $crate::check_condition!(!a, false, "%s is true", $actual, $msg);
375    };
376}
377
378/// Asserts that the expression evaluates to false and short-circuits on failure.
379#[macro_export]
380macro_rules! assert_false {
381    ($actual:expr) => {
382        $crate::assert_false!($actual, "")
383    };
384    ($actual:expr, $msg:expr) => {
385        let a = $actual;
386        $crate::check_condition!(!a, true, "%s is true", $actual, $msg);
387    };
388}
389
390/// Asserts that the pointer is null, but does not short-circuit on failure.
391#[macro_export]
392macro_rules! expect_null {
393    ($actual:expr) => {
394        $crate::expect_null!($actual, "")
395    };
396    ($actual:expr, $msg:expr) => {
397        let a = $actual;
398        $crate::check_condition!(a.is_null(), false, "%s is non-null!", $actual, $msg);
399    };
400}
401
402/// Asserts that the pointer is null and short-circuits on failure.
403#[macro_export]
404macro_rules! assert_null {
405    ($actual:expr) => {
406        $crate::assert_null!($actual, "")
407    };
408    ($actual:expr, $msg:expr) => {
409        let a = $actual;
410        $crate::check_condition!(a.is_null(), true, "%s is non-null!", $actual, $msg);
411    };
412}
413
414/// Asserts that the pointer is non-null, but does not short-circuit on failure.
415#[macro_export]
416macro_rules! expect_nonnull {
417    ($actual:expr) => {
418        $crate::expect_nonnull!($actual, "")
419    };
420    ($actual:expr, $msg:expr) => {
421        let a = $actual;
422        $crate::check_condition!(!a.is_null(), false, "%s is null!", $actual, $msg);
423    };
424}
425
426/// Asserts that the pointer is non-null and short-circuits on failure.
427#[macro_export]
428macro_rules! assert_nonnull {
429    ($actual:expr) => {
430        $crate::assert_nonnull!($actual, "")
431    };
432    ($actual:expr, $msg:expr) => {
433        let a = $actual;
434        $crate::check_condition!(!a.is_null(), true, "%s is null!", $actual, $msg);
435    };
436}
437
438/// Asserts that the expression evaluates to OK, but does not short-circuit on failure.
439#[macro_export]
440macro_rules! expect_ok {
441    ($actual:expr) => {
442        $crate::expect_ok!($actual, "")
443    };
444    ($actual:expr, $msg:expr) => {
445        let a: ::unittest::__Status = $actual.into();
446        $crate::check_comparison!(
447            a == ::unittest::__Status::OK,
448            false,
449            "==",
450            ::unittest::__Status::OK,
451            ::unittest::__Status::OK.into_raw(),
452            a,
453            a.into_raw(),
454            $msg
455        );
456    };
457}
458
459/// Asserts that the expression evaluates to OK and short-circuits on failure.
460#[macro_export]
461macro_rules! assert_ok {
462    ($actual:expr) => {
463        $crate::assert_ok!($actual, "")
464    };
465    ($actual:expr, $msg:expr) => {
466        let a: ::unittest::__Status = $actual.into();
467        $crate::check_comparison!(
468            a == ::unittest::__Status::OK,
469            true,
470            "==",
471            ::unittest::__Status::OK,
472            ::unittest::__Status::OK.into_raw(),
473            a,
474            a.into_raw(),
475            $msg
476        );
477    };
478}
479
480/// Asserts that the expression evaluates to Result::Ok and returns the resulting value, otherwise
481/// short-circuits.
482#[macro_export]
483macro_rules! unwrap_ok {
484    ($actual:expr) => {
485        $crate::unwrap_ok!($actual, "")
486    };
487    ($actual:expr, $msg:expr) => {
488        match ($actual) {
489            Ok(r) => r,
490            Err(err) => {
491                let err: ::unittest::__Status = err.into();
492                $crate::check_comparison!(
493                    err == ::unittest::__Status::OK,
494                    true,
495                    "==",
496                    ::unittest::__Status::OK,
497                    ::unittest::__Status::OK.into_raw(),
498                    err,
499                    err.into_raw(),
500                    $msg
501                );
502                return false;
503            }
504        }
505    };
506}
507
508// When building this crate with unit tests we also pass `--cfg ktest` to
509// enable the unconditional use of #[test_suite] below.
510#[cfg(test)]
511mod tests {
512    use core::ffi::CStr;
513    use core::{ptr, slice};
514    use std::cell::Cell;
515    use std::vec::Vec;
516
517    use super::{TestSuiteRegistration, test_suite};
518
519    unsafe extern "C" {
520        static __start_unittest_testcases: TestSuiteRegistration;
521        static __stop_unittest_testcases: TestSuiteRegistration;
522    }
523
524    // Thread-local since #[test] instances are run in parallel.
525    thread_local! {
526        static END_REACHED: Cell<bool> = Cell::new(false);
527    }
528
529    fn mark_end_as_reached() {
530        END_REACHED.with(|cell| cell.set(true));
531    }
532
533    fn mark_end_as_not_reached() {
534        END_REACHED.with(|cell| cell.set(false));
535    }
536
537    fn expect_end_reached() {
538        std::assert_eq!(END_REACHED.with(|cell| cell.get()), true);
539    }
540
541    fn expect_end_not_reached() {
542        std::assert_eq!(END_REACHED.with(|cell| cell.get()), false);
543    }
544
545    fn get_test_suites() -> Vec<TestSuiteRegistration> {
546        let start = unsafe { &__start_unittest_testcases as *const TestSuiteRegistration };
547        let stop = unsafe { &__stop_unittest_testcases as *const TestSuiteRegistration };
548
549        let count = unsafe { stop.offset_from(start) } as usize;
550
551        let test_suites_rodata = unsafe { slice::from_raw_parts(start, count) };
552
553        let mut suites = Vec::from(test_suites_rodata);
554
555        suites.sort_by(|a, b| {
556            let a_name = unsafe { CStr::from_ptr(a.name) };
557            let b_name = unsafe { CStr::from_ptr(b.name) };
558            a_name.cmp(b_name)
559        });
560        suites
561    }
562
563    /// Suite with one function description.
564    #[test_suite(name = "one_function")]
565    mod suite_with_one_function {
566        /// Empty function description.
567        #[test]
568        fn empty() {}
569    }
570
571    /// Suite with non-test items.
572    #[test_suite]
573    mod suite_with_other_items {
574        use std::vec;
575
576        trait Countable {
577            fn count(&self) -> usize;
578        }
579
580        impl<T> Countable for Vec<T> {
581            fn count(&self) -> usize {
582                self.len()
583            }
584        }
585
586        fn get_count<T: Countable>(countable: T) -> usize {
587            countable.count()
588        }
589
590        /// Check use statement.
591        #[test]
592        fn check_other_items() {
593            let v = vec![1, 2, 3];
594            expect_eq!(get_count(v), 3);
595        }
596    }
597
598    /// Suite with ignored test.
599    #[test_suite(name = "with_ignored")]
600    mod suite_with_ignored {
601        /// Ignored test.
602        #[ignore]
603        #[test]
604        fn ignored_test() {
605            assert_true!(false);
606        }
607
608        /// Normal test.
609        #[test]
610        fn normal_test() {}
611    }
612
613    /// Assertion tests description.
614    #[test_suite]
615    mod assertions {
616        /// Success cases.
617        #[test]
618        fn test_success() {
619            assert_eq!(1, 1);
620            assert_ne!(1, 2);
621            assert_lt!(1, 2);
622            assert_le!(1, 1);
623            assert_gt!(2, 1);
624            assert_ge!(2, 2);
625
626            assert_true!(true);
627            assert_false!(false);
628
629            let null_ptr: *const i32 = ptr::null();
630            let nonnull_ptr: *const i32 = &42 as *const i32;
631            assert_null!(null_ptr);
632            assert_nonnull!(nonnull_ptr);
633
634            assert_ok!(zx_status::Status::OK);
635
636            let _ = unwrap_ok!(Ok::<(), zx_status::Status>(()));
637
638            mark_end_as_reached();
639        }
640
641        /// Test that assert_eq fails on inequality.
642        #[test]
643        fn fail_assert_eq() {
644            assert_eq!(1, 2);
645            mark_end_as_reached();
646        }
647
648        /// Test that assert_ne fails on equality.
649        #[test]
650        fn fail_assert_ne() {
651            assert_ne!(1, 1);
652            mark_end_as_reached();
653        }
654
655        /// Test that assert_lt fails when not less-than.
656        #[test]
657        fn fail_assert_lt() {
658            assert_lt!(2, 1);
659            mark_end_as_reached();
660        }
661
662        /// Test that assert_le fails when greater.
663        #[test]
664        fn fail_assert_le() {
665            assert_le!(2, 1);
666            mark_end_as_reached();
667        }
668
669        /// Test that assert_gt fails when not greater-than.
670        #[test]
671        fn fail_assert_gt() {
672            assert_gt!(1, 2);
673            mark_end_as_reached();
674        }
675
676        /// Test that assert_ge fails when less.
677        #[test]
678        fn fail_assert_ge() {
679            assert_ge!(1, 2);
680            mark_end_as_reached();
681        }
682
683        /// Test that assert_true fails when value is false.
684        #[test]
685        fn fail_assert_true() {
686            assert_true!(false);
687            mark_end_as_reached();
688        }
689
690        /// Test that assert_false fails when value is true.
691        #[test]
692        fn fail_assert_false() {
693            assert_false!(true);
694            mark_end_as_reached();
695        }
696
697        /// Test that assert_null fails when pointer is non-null.
698        #[test]
699        fn fail_assert_null() {
700            assert_null!(&42 as *const i32);
701            mark_end_as_reached();
702        }
703
704        /// Test that assert_nonnull fails when pointer is null.
705        #[test]
706        fn fail_assert_nonnull() {
707            assert_nonnull!(ptr::null::<i32>());
708            mark_end_as_reached();
709        }
710
711        /// Test that assert_ok fails when value is non-zero.
712        #[test]
713        fn fail_assert_ok() {
714            assert_ok!(zx_status::Status::INTERNAL);
715            mark_end_as_reached();
716        }
717
718        /// Test that unwrap_ok fails when value is an error.
719        #[test]
720        fn test_unwrap_ok() {
721            let _: () = unwrap_ok!(Err(zx_status::Status::INTERNAL));
722            mark_end_as_reached();
723        }
724    }
725
726    /// Expectation tests description.
727    #[test_suite]
728    mod expectations {
729        /// Success cases.
730        #[test]
731        fn test_success() {
732            expect_eq!(1, 1);
733            expect_eq!(1, 1, "one should be one");
734            expect_ne!(1, 2);
735            expect_ne!(1, 2, "one should not be two");
736            expect_lt!(1, 2);
737            expect_lt!(1, 2, "one should be less than two");
738            expect_le!(1, 1);
739            expect_le!(1, 2);
740            expect_gt!(2, 1);
741            expect_ge!(2, 2);
742
743            expect_true!(true);
744            expect_true!(true, "should be true");
745            expect_false!(false);
746            expect_false!(false, "should be false");
747
748            let null_ptr: *const i32 = ptr::null();
749            let nonnull_ptr: *const i32 = &42 as *const i32;
750            expect_null!(null_ptr);
751            expect_null!(null_ptr, "should be null");
752            expect_nonnull!(nonnull_ptr);
753            expect_nonnull!(nonnull_ptr, "should be non-null");
754
755            expect_ok!(zx_status::Status::OK);
756            expect_ok!(zx_status::Status::OK, "should be OK");
757
758            mark_end_as_reached();
759        }
760
761        /// Test that expect_eq fails on inequality.
762        #[test]
763        fn fail_expect_eq() {
764            expect_eq!(1, 2);
765            mark_end_as_reached();
766        }
767
768        /// Test that expect_ne fails on equality.
769        #[test]
770        fn fail_expect_ne() {
771            expect_ne!(1, 1);
772            mark_end_as_reached();
773        }
774
775        /// Test that expect_lt fails when not less-than.
776        #[test]
777        fn fail_expect_lt() {
778            expect_lt!(2, 1);
779            mark_end_as_reached();
780        }
781
782        /// Test that expect_le fails when greater.
783        #[test]
784        fn fail_expect_le() {
785            expect_le!(2, 1);
786            mark_end_as_reached();
787        }
788
789        /// Test that expect_gt fails when not greater-than.
790        #[test]
791        fn fail_expect_gt() {
792            expect_gt!(1, 2);
793            mark_end_as_reached();
794        }
795
796        /// Test that expect_ge fails when less.
797        #[test]
798        fn fail_expect_ge() {
799            expect_ge!(1, 2);
800            mark_end_as_reached();
801        }
802
803        /// Test that expect_true fails when value is false.
804        #[test]
805        fn fail_expect_true() {
806            expect_true!(false);
807            mark_end_as_reached();
808        }
809
810        /// Test that expect_false fails when value is true.
811        #[test]
812        fn fail_expect_false() {
813            expect_false!(true);
814            mark_end_as_reached();
815        }
816
817        /// Test that expect_null fails when pointer is non-null.
818        #[test]
819        fn fail_expect_null() {
820            expect_null!(&42 as *const i32);
821            mark_end_as_reached();
822        }
823
824        /// Test that expect_nonnull fails when pointer is null.
825        #[test]
826        fn fail_expect_nonnull() {
827            expect_nonnull!(ptr::null::<i32>());
828            mark_end_as_reached();
829        }
830
831        /// Test that expect_ok fails when value is non-zero.
832        #[test]
833        fn fail_expect_ok() {
834            expect_ok!(zx_status::Status::INTERNAL);
835            mark_end_as_reached();
836        }
837    }
838
839    #[test]
840    fn check_suite_count() {
841        let suites = get_test_suites();
842        std::assert_eq!(suites.len(), 5);
843    }
844
845    #[test]
846    fn check_suite_assertions() {
847        let suites = get_test_suites();
848        std::assert!(suites.len() > 0);
849        let suite = &suites[0];
850
851        std::assert_eq!(unsafe { CStr::from_ptr(suite.name) }.to_bytes(), b"assertions");
852        std::assert_eq!(suite.test_cnt, 13);
853
854        let cases_rodata = unsafe { slice::from_raw_parts(suite.tests, suite.test_cnt) };
855        for case in cases_rodata {
856            mark_end_as_not_reached();
857            let name = unsafe { CStr::from_ptr(case.name) }.to_str().unwrap();
858            let res = (case.fn_)();
859            if name == "test_success" {
860                std::assert_eq!(res, true, "assertions::test_success should pass");
861                expect_end_reached();
862            } else {
863                std::assert_eq!(res, false, "assertions::{} should fail", name);
864                expect_end_not_reached();
865            }
866        }
867    }
868
869    #[test]
870    fn check_suite_expectations() {
871        let suites = get_test_suites();
872        std::assert!(suites.len() > 1);
873        let suite = &suites[1];
874
875        std::assert_eq!(unsafe { CStr::from_ptr(suite.name) }.to_bytes(), b"expectations");
876        std::assert_eq!(suite.test_cnt, 12);
877
878        let cases = unsafe { slice::from_raw_parts(suite.tests, suite.test_cnt) };
879        for case in cases {
880            mark_end_as_not_reached();
881            let name = unsafe { CStr::from_ptr(case.name) }.to_str().unwrap();
882            let res = (case.fn_)();
883            if name == "test_success" {
884                std::assert_eq!(res, true, "expectations::test_success should pass");
885            } else {
886                std::assert_eq!(res, false, "expectations::{} should fail", name);
887            }
888            expect_end_reached();
889        }
890    }
891
892    #[test]
893    fn check_suite_with_one_function() {
894        let suites = get_test_suites();
895        std::assert!(suites.len() > 2);
896        let suite = &suites[2];
897
898        std::assert_eq!(unsafe { CStr::from_ptr(suite.name) }.to_bytes(), b"one_function");
899        std::assert_eq!(
900            unsafe { CStr::from_ptr(suite.desc) }.to_str().unwrap(),
901            "Suite with one function description."
902        );
903        std::assert_eq!(suite.test_cnt, 1);
904        let case = unsafe { &*suite.tests };
905        std::assert_eq!(unsafe { CStr::from_ptr(case.name) }.to_bytes(), b"empty");
906        assert!((case.fn_)());
907    }
908
909    #[test]
910    fn check_suite_with_other_items() {
911        let suites = get_test_suites();
912        std::assert!(suites.len() > 3);
913        let suite = &suites[3];
914
915        std::assert_eq!(
916            unsafe { CStr::from_ptr(suite.name) }.to_bytes(),
917            b"suite_with_other_items"
918        );
919        std::assert_eq!(
920            unsafe { CStr::from_ptr(suite.desc) }.to_str().unwrap(),
921            "Suite with non-test items."
922        );
923        std::assert_eq!(suite.test_cnt, 1);
924        let case = unsafe { &*suite.tests };
925        std::assert_eq!(unsafe { CStr::from_ptr(case.name) }.to_bytes(), b"check_other_items");
926        assert!((case.fn_)());
927    }
928
929    #[test]
930    fn check_suite_with_ignored() {
931        let suites = get_test_suites();
932        std::assert!(suites.len() > 4);
933        let suite = &suites[4];
934
935        std::assert_eq!(unsafe { CStr::from_ptr(suite.name) }.to_bytes(), b"with_ignored");
936        std::assert_eq!(suite.test_cnt, 1);
937        let case = unsafe { &*suite.tests };
938        std::assert_eq!(unsafe { CStr::from_ptr(case.name) }.to_bytes(), b"normal_test");
939    }
940}