OS 简单教程番外1:给内核添加测试框架OS 简单教程番外1:给内核添加测试框架
🪡

OS 简单教程番外1:给内核添加测试框架

给内核添加测试框架

为了方便开发我们给内核添加测试框架,rust 本来就有测试框架,可以利用起来
// in src/main.rs #![feature(custom_test_frameworks)] #![test_runner(crate::test_runner)] #![reexport_test_harness_main = "test_main"] #[cfg(test)] fn test_runner(tests: &[&dyn Fn()]) {    println!("Running {} tests", tests.len());    for test in tests {        test();   } }
  • #![feature(custom_test_frameworks)] 是自定义测试框架
  • #![test_runner(crate::test_runner)] 是用 test_runner 做为测试 runner
  • 入口本来是测试框架自己生成的 _start ,我们指定 test_main
  • 最后在我们的 rust_main 中调用 test_main
#[no_mangle] extern "C" fn rust_main() -> ! {    clear_bss();    heap::init();    trap::init();    task::init();    #[cfg(test)]    test_main();    task::run(); }
现在试试用 cargo test,可惜不行,因为我们要在 k210 上执行,所以改造 Makefile 吧。
test: env @echo Platform: $(BOARD) @cd ../user && make build $(eval override KERNEL_ELF := $(shell cargo test --no-run --message-format=json | jq -r "select(.profile.test == true) | .filenames[]")) @$(OBJCOPY) $(KERNEL_ELF) --strip-all -O binary $(KERNEL_BIN) (which $(K210-BURNER)) || (cd .. && git clone https://github.com/sipeed/kflash.py.git && mv kflash.py tools) @cp $(BOOTLOADER) $(BOOTLOADER).copy @dd if=$(KERNEL_BIN) of=$(BOOTLOADER).copy bs=$(K210_BOOTLOADER_SIZE) seek=1 @mv $(BOOTLOADER).copy $(KERNEL_BIN) @sudo chmod 777 $(K210-SERIALPORT) python3 $(K210-BURNER) -p $(K210-SERIALPORT) -b 1500000 $(KERNEL_BIN) python3 -m serial.tools.miniterm --eol LF --dtr 0 --rts 0 --filter direct $(K210-SERIALPORT) 115200
  • 先 build 应用程序,和直接 run 一样
  • $(eval override KERNEL_ELF := $(shell cargo test --no-run --message-format=json | jq -r "select(.profile.test == true) | .filenames[]")) 这句不同,这句的意思是:
    • 安装 jq,brew install jq
    • 执行 cargo test --no-run --message-format=json ,带测试编译,不执行,结果 json 展示。
    • 因为二进制文件带编译 hash 每次都不一样,我们用 --message-format=json ,然后用 jq 解析 json
    • 最后赋值 KERNEL_ELF
  • 后面同 build
接着就可以添加测试用例了,然后 make test 执行
#[test_case] pub fn heap_test() {    use alloc::boxed::Box;    use alloc::vec::Vec;    extern "C" {        fn sbss();        fn ebss();   }    let bss_range = sbss as usize..ebss as usize;    let a = Box::new(5);    assert_eq!(*a, 5);    assert!(bss_range.contains(&(a.as_ref() as *const _ as usize)));    drop(a);    let mut v: Vec<usize> = Vec::new();    for i in 0..500 {        v.push(i);   }    for i in 0..500 {        assert_eq!(v[i], i);   }    assert!(bss_range.contains(&(v.as_ptr() as usize)));    drop(v);    println!("heap_test passed!"); }
可以看到,make test 结果在 k210 上执行测试用例,而 make run 和以前一样。
[rustsbi] RustSBI version 0.2.0-alpha.3 .______       __   __     _______.___________. _______..______   __ |   _ \     | | | |   /       |           | /       ||   _ \ | | | |_) |   | | | |   |   (----`---| |----`|   (----`| |_) || | |     /     | | | |   \   \       | |     \   \   |   _ < | | | |\ \----.| `--' |.----)   |     | | .----)   |   | |_) || | | _| `._____| \______/ |_______/       |__| |_______/   |______/ |__| [rustsbi] Platform: K210 (Version 0.2.0) [rustsbi] misa: RV64ACDFIMSU [rustsbi] mideleg: 0x22 [rustsbi] medeleg: 0x1ab [rustsbi] Kernel entry: 0x80020000 [kernel] app_0 [0x80035018, 0x80035938) Running 1 tests heap_test passed! Hello OS from app [kernel] Application exited with code 0
代码请参考: https://github.com/buhe/bugu/tree/5-test