os/test/
mod.rs

1mod guard;
2pub mod macros;
3pub mod net_test;
4use crate::{
5    arch::intr::{are_interrupts_enabled, disable_interrupts, enable_interrupts},
6    earlyprintln,
7};
8
9/// 测试运行器。它由测试框架自动调用,并传入一个包含所有测试的切片。
10#[cfg(test)]
11pub fn test_runner(tests: &[&dyn Fn()]) {
12    use crate::{arch::lib::sbi::shutdown, earlyprintln, test::macros::TEST_FAILED};
13    use core::sync::atomic::Ordering;
14    earlyprintln!("\n\x1b[33m--- Running {} tests ---\x1b[0m", tests.len());
15
16    // 重置失败计数器
17    TEST_FAILED.store(0, Ordering::SeqCst);
18
19    // 遍历并执行所有由 #[test_case] 注册的测试
20    for test in tests {
21        test();
22    }
23
24    let failed = TEST_FAILED.load(Ordering::SeqCst);
25    earlyprintln!("\x1b[33m\n--- Test Summary ---\x1b[0m");
26    earlyprintln!(
27        "\x1b[33mTotal: {}\x1b[0m, \x1b[32mPassed: {}\x1b[0m, \x1b[91mFailed: {}\x1b[0m, \x1b[33mTests Finished\x1b[0m",
28        tests.len(),
29        tests.len() - failed,
30        failed
31    );
32
33    if failed > 0 {
34        earlyprintln!("\x1b[91mSome tests failed!\x1b[0m");
35        shutdown(true);
36    } else {
37        earlyprintln!("\x1b[32mAll tests passed!\x1b[0m");
38        shutdown(false);
39    }
40}
41
42pub fn run_early_tests() {
43    // 从链接器脚本中定义的符号获取段的起始和结束地址
44    unsafe extern "C" {
45        static __early_test_start: extern "C" fn();
46        static __early_test_end: extern "C" fn();
47    }
48
49    // 创建一个指向函数指针的切片
50    // 安全性:我们假设链接器脚本正确创建了这些符号,并且它们对齐了函数指针。
51    // 段中的每个项都是一个 `fn()` 类型的指针。
52    let start = unsafe { &__early_test_start as *const _ as *const extern "C" fn() };
53    let end = unsafe { &__early_test_end as *const _ as *const extern "C" fn() };
54
55    // 计算测试数量
56    let count = unsafe { end.offset_from(start) } as usize;
57    if count == 0 {
58        earlyprintln!("\x1b[36m[early_test] No early tests to run.\x1b[0m");
59        return;
60    }
61
62    earlyprintln!(
63        "\n\x1b[36m--- Running {} early tests (pre-mm) ---\x1b[0m",
64        count
65    );
66
67    // 遍历并执行所有测试函数
68    for i in 0..count {
69        let test_fn = unsafe { *start.add(i) };
70        test_fn();
71    }
72
73    earlyprintln!("\x1b[36m--- Early tests finished ---\x1b[0m\n");
74}
75
76/// 一个 RAII 守卫,用于在作用域内启用中断,并在离开作用域时恢复之前的状态。
77///
78/// # Safety
79///
80/// 创建此守卫需要调用 `enable_interrupts`,这是一个 `unsafe` 操作。
81/// 因此,`new` 函数也是 `unsafe` 的。封装它的宏将负责处理安全性。
82pub struct InterruptGuard {
83    // 存储创建守卫之前的中断状态,以便恢复。
84    // true = 已启用, false = 已禁用
85    was_enabled: bool,
86}
87
88impl InterruptGuard {
89    /// 创建一个新的守卫并启用中断。
90    ///
91    /// # Safety
92    ///
93    /// 调用者必须确保此时启用中断是安全的。例如,不能在持有自旋锁时调用。
94    #[inline(always)]
95    pub fn new() -> Self {
96        // 读取当前中断状态,保存,如果是禁用的drop时会重新禁用
97        let was_enabled = are_interrupts_enabled();
98        // 启用中断
99        unsafe {
100            enable_interrupts();
101        }
102        Self { was_enabled }
103    }
104}
105
106impl Drop for InterruptGuard {
107    #[inline(always)]
108    fn drop(&mut self) {
109        if !self.was_enabled {
110            // 如果之前是禁用的,就再次禁用。
111            unsafe {
112                disable_interrupts();
113            }
114        }
115        // 如果之前是启用的,我们什么都不用做,因为中断本来就是开启的。
116    }
117}
118
119#[cfg(test)]
120mod tests {
121    #[cfg(target_arch = "riscv64")]
122    use riscv::interrupt::Interrupt;
123
124    use crate::{early_test, kassert, println, test_case};
125
126    test_case!(trivial_assertion, {
127        kassert!(0 != 1);
128    });
129
130    early_test!(exampe_early_test, {
131        kassert!(1 == 1);
132    });
133
134    // 测试 `test_case!` 宏的 `(Interrupts)` 环境是否能正确地
135    // 在测试开始时启用中断,并在测试结束后恢复原始状态。
136    // test_case!(verify_interrupt_environment, (Interrupt), {
137    //     // 在这个代码块内部,中断应该已经被宏自动启用了。
138    //     // 我们断言这一点来验证宏的行为。
139    //     kassert!(crate::arch::intr::are_interrupts_enabled());
140
141    //     println!("  -> Assertion passed: Interrupts are enabled.");
142
143    //     // 为了让测试更有意义,我们可以手动禁用中断,
144    //     // 然后验证 RAII 守卫是否会在测试结束时恢复它们。
145    //     println!("  -> Manually disabling interrupts for demonstration...");
146    //     unsafe {
147    //         crate::arch::intr::disable_interrupts();
148    //     }
149
150    //     kassert!(!crate::arch::intr::are_interrupts_enabled());
151
152    //     println!("  -> Assertion passed: Interrupts are now disabled manually.");
153    //     println!("  -> Leaving test block, the guard should now restore the state...");
154    // });
155
156    // 一个配套的测试,在 `(Interrupts)` 测试之后运行,
157    // 用来验证中断状态确实被恢复到了禁用状态。
158    // test_case!(verify_interrupts_restored_after_test, {
159    //     // 默认情况下,我们的测试运行器是在中断禁用的环境下运行的。
160    //     // 如果前一个测试的 RAII 守卫工作正常,那么中断现在应该是禁用的。
161    //     kassert!(!crate::arch::intr::are_interrupts_enabled());
162
163    //     println!("  -> Assertion passed: Interrupts were correctly restored to disabled state.");
164    // });
165}