Nothing to see here, move along
1use crate::sync::SyncUnsafe;
2
3#[repr(C)]
4pub struct TestEntry {
5 pub name: &'static str,
6 pub func: fn(),
7}
8
9struct CurrentTest {
10 num: usize,
11 name: &'static str,
12}
13
14static CURRENT_TEST: SyncUnsafe<CurrentTest> = SyncUnsafe::new(CurrentTest { num: 0, name: "" });
15
16pub fn current() -> (usize, &'static str) {
17 unsafe {
18 let ct = &*CURRENT_TEST.get();
19 (ct.num, ct.name)
20 }
21}
22
23fn set_current(num: usize, name: &'static str) {
24 unsafe {
25 let ct = &mut *CURRENT_TEST.get();
26 ct.num = num;
27 ct.name = name;
28 }
29}
30
31fn test_entries() -> &'static [TestEntry] {
32 #[allow(improper_ctypes)]
33 unsafe extern "C" {
34 static __kernel_tests_start: TestEntry;
35 static __kernel_tests_end: TestEntry;
36 }
37 unsafe {
38 let start = &raw const __kernel_tests_start;
39 let end = &raw const __kernel_tests_end;
40 let count = (end as usize - start as usize) / core::mem::size_of::<TestEntry>();
41 core::slice::from_raw_parts(start, count)
42 }
43}
44
45const PREFIX: &str = "lancer_kernel::tests::";
46
47fn strip_prefix(name: &str) -> &str {
48 match name.strip_prefix(PREFIX) {
49 Some(rest) => rest,
50 None => name,
51 }
52}
53
54pub fn run_all() -> ! {
55 let entries = test_entries();
56 crate::kprintln!("KTAP version 1");
57 crate::kprintln!("1..{}", entries.len());
58 entries.iter().enumerate().for_each(|(i, entry)| {
59 let num = i + 1;
60 let name = strip_prefix(entry.name);
61 set_current(num, name);
62 (entry.func)();
63 crate::kprintln!("ok {} - {}", num, name);
64 });
65 crate::klog!("test", "all {} passed", entries.len());
66 crate::proc::report_all_stack_usage();
67 crate::proc::report_refcount_audit();
68 crate::qemu::exit(crate::qemu::ExitCode::Success);
69}
70
71#[macro_export]
72macro_rules! kernel_test {
73 (fn $name:ident() $body:block) => {
74 fn $name() $body
75
76 const _: () = {
77 #[used]
78 #[unsafe(link_section = ".kernel_tests")]
79 static ENTRY: $crate::test_harness::TestEntry = $crate::test_harness::TestEntry {
80 name: concat!(module_path!(), "::", stringify!($name)),
81 func: $name,
82 };
83 };
84 };
85}