Skip to main content

os_test_framework/
lib.rs

1//! # os-test-framework
2//!
3//! Test framework for embedded systems and OS kernels.
4//!
5//! `os-test-framework` requires `alloc`, so your kernel will need a `global-allocator`.
6//!
7//! ## Getting Started
8//!
9//! First, enable `custom_test_frameworks`, set `test_runner` as the test runner
10//! from `os-test-framework`, and `reexport_test_harness_main`.
11//!
12//! ```rust,ignore
13//! #![feature(custom_test_frameworks)]
14//! #![reexport_test_harness_main = "test_main"]
15//! #![test_runner(os_test_framework::run_tests)]
16//! ```
17//!
18//! Implement `Platform`. The framework writes output through
19//! `Platform::print` and finishes the run through `Platform::exit`:
20//!
21//! ```rust,ignore
22//! use core::fmt::Arguments;
23//! use os_test_framework::platform::{ExitState, Platform};
24//!
25//! struct MyPlatform;
26//!
27//! impl Platform for MyPlatform {
28//!     fn print(&mut self, args: Arguments) {
29//!         let _ = args;
30//!         todo!()
31//!     }
32//!
33//!     fn exit(&self, state: ExitState) -> ! {
34//!         match state {
35//!             ExitState::Success => todo!(),
36//!             ExitState::Failed => todo!(),
37//!         }
38//!     }
39//! }
40//! ```
41//!
42//! Call `init_platform` with your `Platform`, and `test_main` from your kernel
43//! entry point:
44//!
45//! ```rust,ignore
46//! use os_test_framework::platform::init_platform;
47//!
48//! fn kernel_entry() {
49//!     init_platform(MyPlatform);
50//!     test_main();
51//! }
52//! ```
53//!
54//! Forward panics from your OS to `os-test-framework`:
55//!
56//! ```rust,ignore
57//! use core::panic::PanicInfo;
58//!
59//! #[cfg(test)]
60//! #[panic_handler]
61//! fn panic(info: &PanicInfo) -> ! {
62//!     os_test_framework::panic::handle_panic(info)
63//! }
64//! ```
65//!
66//! ## Adding A Test
67//!
68//! You can declare tests like this:
69//!
70//! ```rust,ignore
71//! use os_test_framework::test;
72//!
73//! test! {
74//!     "Hello" {
75//!         assert!(true);
76//!     }
77//! }
78//! ```
79//!
80//! You can add multiple tests in the same file:
81//!
82//! ```rust,ignore
83//! use os_test_framework::test;
84//!
85//! test! {
86//!     "Hello" {
87//!         assert!(true);
88//!     }
89//! }
90//!
91//! test! {
92//!     "Hello2" {
93//!         assert!(true);
94//!     }
95//! }
96//! ```
97#![no_std]
98
99use owo_colors::OwoColorize;
100
101use crate::platform::{ExitState, platform};
102
103extern crate alloc;
104
105pub mod panic;
106pub mod platform;
107#[doc(hidden)]
108pub mod __private {
109    pub use crate::_run_test;
110    pub use crate::printing::_print;
111}
112
113mod make_test;
114mod printing;
115
116pub fn run_tests(tests: &[&dyn Fn()]) -> ! {
117    println!("\nRunning {} tests", tests.len().bold());
118
119    for test in tests {
120        test()
121    }
122
123    platform().lock().exit(ExitState::Success);
124}
125
126#[doc(hidden)]
127pub fn _run_test(name: &str, func: impl FnOnce()) {
128    print!("{}", name);
129    func();
130    println!(" {}", "OK".green().bold());
131}