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 suite macro to work within this crate's test module.
10#[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
21/// Attribute macro defining suite of unit tests defined as module. The
22/// attribute may only be used in a cfg(ktest) context.
23///
24/// Tests are idiomatically modeled as functions, and so modules of such
25/// functions make for a natural representation as a test suite.
26///
27/// Tests defined through this attribute are available to be run via `k ut`.
28///
29/// A test suite module must meet the following criteria:
30/// * It must have a one-line docstring. This line becomes the description of
31///   the suite on the kernel command-line.
32/// * It must contain at least one test function; it may contain any other items.
33///
34/// A test function must meet the following criteria:
35/// * It must be annotated with #[test].
36/// * It too must have a one-line docstring. This line becomes the description
37///   of the test on the kernel command-line.
38/// * It must have a () -> () signature.
39///
40/// A test function should make assertions only using the declarative
41/// assert_*/expect_* macros defined in the unittest module.
42///
43/// Disabling a test can be done with a further annotation of #[ignore]. Such a
44/// test will still be compiled; it just will not contribute test metadata.
45///
46/// # Example
47/// ```rust,ignore
48/// /// Brief test suite description.
49/// #[cfg(ktest)]
50/// #[unittest::suite(name = "optional_name")]
51/// mod my_suite {
52///     /* non-test items... */
53///
54///     /// Brief test case description.
55///     #[test]
56///     fn my_case() {
57///         assert_false!(false);
58///         expect_true!(1 == 1, "expectation with a message");
59///     }
60///
61///     /// This test case is currently disabled.
62///     #[test]
63///     #[ignore]
64///     fn my_disabled_case() {...}
65/// }
66/// ```
67///
68pub 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/// The data structure that statically defines a test suite, intended to be
146/// defined via the #[suite] macro to encoded into a special section in
147/// the kernel.
148#[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    /// The name of the suite.
162    ///
163    /// Registrations are emitted by the #[suite] macro as compile-time
164    /// constants, so a missing or non-UTF-8 name is a programming error.
165    pub fn name(&self) -> &'_ str {
166        assert!(!self.name.is_null(), "test suite registration has no name");
167        // Safety: the name is a static, NUL-terminated string.
168        unsafe { CStr::from_ptr(self.name) }.to_str().expect("test suite name is not valid UTF-8")
169    }
170
171    /// The description of the suite, if it has one.
172    pub fn desc(&self) -> Option<&'_ str> {
173        if self.desc.is_null() {
174            return None;
175        }
176        // Safety: the description is a static, NUL-terminated string.
177        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    /// The test cases of the suite.
182    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        // Safety: the registration records `test_cnt` contiguous test cases.
188        unsafe { slice::from_raw_parts(self.tests, self.test_cnt) }
189    }
190}
191
192/// The data structure defining a test case within a suite, also intended be
193/// defined via the #[suite] macro to encoded into a special section in
194/// the kernel
195#[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    /// The name of the test case.
207    ///
208    /// Registrations are emitted by the #[suite] macro as compile-time
209    /// constants, so a missing or non-UTF-8 name is a programming error.
210    pub fn name(&self) -> &'_ str {
211        assert!(!self.name.is_null(), "test case registration has no name");
212        // Safety: the name is a static, NUL-terminated string.
213        unsafe { CStr::from_ptr(self.name) }.to_str().expect("test case name is not valid UTF-8")
214    }
215}
216
217/// Asserts that two expressions are equal, but does not short-circuit on failure.
218#[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/// Asserts that two expressions are equal and short-circuits on failure.
231#[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/// Asserts that two expressions are not equal, but does not short-circuit on failure.
244#[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/// Asserts that two expressions are not equal and short-circuits on failure.
257#[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/// Asserts that the first expression is less than the second, but does not short-circuit on failure.
270#[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/// Asserts that the first expression is less than the second and short-circuits on failure.
283#[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/// Asserts that the first expression is less than or equal to the second, but does not short-circuit on failure.
296#[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/// Asserts that the first expression is less than or equal to the second and short-circuits on failure.
309#[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/// Asserts that the first expression is greater than the second, but does not short-circuit on failure.
322#[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/// Asserts that the first expression is greater than the second and short-circuits on failure.
335#[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/// Asserts that the first expression is greater than or equal to the second, but does not short-circuit on failure.
348#[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/// Asserts that the first expression is greater than or equal to the second and short-circuits on failure.
361#[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/// Asserts that the expression evaluates to true, but does not short-circuit on failure.
374#[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/// Asserts that the expression evaluates to true and short-circuits on failure.
386#[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/// Asserts that the expression evaluates to false, but does not short-circuit on failure.
398#[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/// Asserts that the expression evaluates to false and short-circuits on failure.
410#[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/// Asserts that the pointer is null, but does not short-circuit on failure.
422#[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/// Asserts that the pointer is null and short-circuits on failure.
434#[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/// Asserts that the pointer is non-null, but does not short-circuit on failure.
446#[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/// Asserts that the pointer is non-null and short-circuits on failure.
458#[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/// Asserts that the expression evaluates to OK, but does not short-circuit on failure.
534#[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/// Asserts that the expression evaluates to OK and short-circuits on failure.
546#[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/// Asserts that the expression evaluates to the specified error status, but does not short-circuit
558/// on failure.
559#[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/// Asserts that the expression evaluates to the specified error status and short-circuits on
580/// failure.
581#[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/// Asserts that the expression evaluates to Result::Ok and returns the resulting value, otherwise
602/// short-circuits.
603#[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/// Asserts that the expression evaluates to Option::Some and returns the resulting value, otherwise
629/// short-circuits.
630#[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/// Creates an isolated subtest closure with its own failure tracking.
647///
648/// Within a subtest, assertions (`expect_*!`, `assert_*!`, `unwrap_*!`) record failures to the
649/// subtest's local status flag rather than the enclosing test's flag. Hard assertions (`assert_*!`,
650/// `unwrap_*!`) return `false` early from the subtest without returning from the enclosing test.
651///
652/// Returns `bool`: `true` if all assertions in the subtest passed, `false` otherwise.
653#[macro_export]
654macro_rules! subtest {
655    (|$($param:ident : $ty:ty),* $(,)?| $body:block) => {
656        |$($param : $ty),*| -> bool {
657            // Unused when the subtest body contains no soft assertions.
658            #[allow(unused_mut)]
659            let mut all_ok = true;
660            macro_rules! record_failure {
661                () => {
662                    // Unused when an early-return assertion mutates all_ok before returning.
663                    #[allow(unused_assignments)]
664                    {
665                        all_ok = false;
666                    }
667                };
668            }
669            $body
670            all_ok
671        }
672    };
673}
674
675// When building this crate with unit tests we also pass `--cfg ktest` to
676// enable the unconditional use of #[suite] below.
677#[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 since #[test] instances are run in parallel.
692    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 with one function description.
731    #[suite(name = "one_function")]
732    mod suite_with_one_function {
733        /// Empty function description.
734        #[test]
735        fn empty() {}
736    }
737
738    /// Suite with non-test items.
739    #[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        /// Check use statement.
758        #[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 with ignored test.
766    #[suite(name = "with_ignored")]
767    mod suite_with_ignored {
768        /// Ignored test.
769        #[ignore]
770        #[test]
771        fn ignored_test() {
772            assert_true!(false);
773        }
774
775        /// Normal test.
776        #[test]
777        fn normal_test() {}
778    }
779
780    /// Assertion tests description.
781    #[suite]
782    mod assertions {
783        /// Success cases.
784        #[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 that assert_eq fails on inequality.
815        #[test]
816        fn fail_assert_eq() {
817            assert_eq!(1, 2);
818            mark_end_as_reached();
819        }
820
821        /// Test that assert_ne fails on equality.
822        #[test]
823        fn fail_assert_ne() {
824            assert_ne!(1, 1);
825            mark_end_as_reached();
826        }
827
828        /// Test that assert_lt fails when not less-than.
829        #[test]
830        fn fail_assert_lt() {
831            assert_lt!(2, 1);
832            mark_end_as_reached();
833        }
834
835        /// Test that assert_le fails when greater.
836        #[test]
837        fn fail_assert_le() {
838            assert_le!(2, 1);
839            mark_end_as_reached();
840        }
841
842        /// Test that assert_gt fails when not greater-than.
843        #[test]
844        fn fail_assert_gt() {
845            assert_gt!(1, 2);
846            mark_end_as_reached();
847        }
848
849        /// Test that assert_ge fails when less.
850        #[test]
851        fn fail_assert_ge() {
852            assert_ge!(1, 2);
853            mark_end_as_reached();
854        }
855
856        /// Test that assert_true fails when value is false.
857        #[test]
858        fn fail_assert_true() {
859            assert_true!(false);
860            mark_end_as_reached();
861        }
862
863        /// Test that assert_false fails when value is true.
864        #[test]
865        fn fail_assert_false() {
866            assert_false!(true);
867            mark_end_as_reached();
868        }
869
870        /// Test that assert_null fails when pointer is non-null.
871        #[test]
872        fn fail_assert_null() {
873            assert_null!(&42 as *const i32);
874            mark_end_as_reached();
875        }
876
877        /// Test that assert_nonnull fails when pointer is null.
878        #[test]
879        fn fail_assert_nonnull() {
880            assert_nonnull!(ptr::null::<i32>());
881            mark_end_as_reached();
882        }
883
884        /// Test that assert_ok fails when value is non-zero.
885        #[test]
886        fn fail_assert_ok() {
887            assert_ok!(Err::<(), _>(zx_status::Status::INTERNAL));
888            mark_end_as_reached();
889        }
890
891        /// Test that assert_err fails when error does not match.
892        #[test]
893        fn fail_assert_err() {
894            assert_err!(Ok::<(), _>(()), zx_status::Status::INTERNAL);
895            mark_end_as_reached();
896        }
897
898        /// Test that unwrap_ok fails when value is an error.
899        #[test]
900        fn test_unwrap_ok() {
901            let _: () = unwrap_ok!(Err(zx_status::Status::INTERNAL));
902            mark_end_as_reached();
903        }
904
905        /// Test that unwrap_some fails when value is None.
906        #[test]
907        fn test_unwrap_some() {
908            let _: () = unwrap_some!(None::<()>);
909            mark_end_as_reached();
910        }
911    }
912
913    /// Expectation tests description.
914    #[suite]
915    mod expectations {
916        /// Success cases.
917        #[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 that expect_eq fails on inequality.
958        #[test]
959        fn fail_expect_eq() {
960            expect_eq!(1, 2);
961            mark_end_as_reached();
962        }
963
964        /// Test that expect_ne fails on equality.
965        #[test]
966        fn fail_expect_ne() {
967            expect_ne!(1, 1);
968            mark_end_as_reached();
969        }
970
971        /// Test that expect_lt fails when not less-than.
972        #[test]
973        fn fail_expect_lt() {
974            expect_lt!(2, 1);
975            mark_end_as_reached();
976        }
977
978        /// Test that expect_le fails when greater.
979        #[test]
980        fn fail_expect_le() {
981            expect_le!(2, 1);
982            mark_end_as_reached();
983        }
984
985        /// Test that expect_gt fails when not greater-than.
986        #[test]
987        fn fail_expect_gt() {
988            expect_gt!(1, 2);
989            mark_end_as_reached();
990        }
991
992        /// Test that expect_ge fails when less.
993        #[test]
994        fn fail_expect_ge() {
995            expect_ge!(1, 2);
996            mark_end_as_reached();
997        }
998
999        /// Test that expect_true fails when value is false.
1000        #[test]
1001        fn fail_expect_true() {
1002            expect_true!(false);
1003            mark_end_as_reached();
1004        }
1005
1006        /// Test that expect_false fails when value is true.
1007        #[test]
1008        fn fail_expect_false() {
1009            expect_false!(true);
1010            mark_end_as_reached();
1011        }
1012
1013        /// Test that expect_null fails when pointer is non-null.
1014        #[test]
1015        fn fail_expect_null() {
1016            expect_null!(&42 as *const i32);
1017            mark_end_as_reached();
1018        }
1019
1020        /// Test that expect_nonnull fails when pointer is null.
1021        #[test]
1022        fn fail_expect_nonnull() {
1023            expect_nonnull!(ptr::null::<i32>());
1024            mark_end_as_reached();
1025        }
1026
1027        /// Test that expect_ok fails when value is non-zero.
1028        #[test]
1029        fn fail_expect_ok() {
1030            expect_ok!(zx_status::Status::INTERNAL);
1031            mark_end_as_reached();
1032        }
1033
1034        /// Test that expect_err fails when error does not match.
1035        #[test]
1036        fn fail_expect_err() {
1037            expect_err!(Ok::<(), _>(()), zx_status::Status::INTERNAL);
1038            mark_end_as_reached();
1039        }
1040    }
1041
1042    /// Subtests description.
1043    #[suite(name = "subtests")]
1044    mod subtests {
1045        /// Test that record_failure inside a subtest does not fail the outer test.
1046        #[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}