Add testing framework for the kernel
robert-w-gries opened this issue · comments
Integration Tests
We should test every component:
- Memory
- Interrupts
- Scheduling
- Inter-process Communication
Original Post
We are starting to get into the meat of OS dev, so we'll need some proper testing tools.
What do we want in our testing framework?
- Unit tests
- Integration tests
- Regression tests
- Testing on actual hardware (stretch goal)
What can be done now?
Unit tests and Regression tests can be implemented without much effort. We already have CI with Travis, and unit tests should be able to run without any dependencies on external code/tools.
What needs to be done?
Regression tests are increasingly vital as the kernel grows more complex. A couple of lines of kprintln!
output will not be sufficient to test preemption, inter-process communication, and file systems.
Ideally, we can create a test harness that uses a virtualization crate to run our kernel and perform tests.
KVM/libvirt bindings
rust-x86
looks to use the kvm
crate to accomplish their testing. This is a good place to start. See gz/rust-x86#20 for a relevant conversation
A full list of virt crates can be found here
utest
crate
Another intriguing option is the utest
crate. However, there are limitations and requirements that might not mesh well with this kernel.
Regarding unit tests
Unit tests were more complex than I thought. See intermezzOS/kernel#69 for details.
By using utest
, I have managed to get a trivial unit test running on qemu
for both i686
and x86_64
:
$ qemu-x86_64 target/x86_64-rxinu-utest/debug/foo-f0f4593aa62d2a5d
warning: TCG doesn't support requested feature: CPUID.01H:ECX.vmx [bit 5]
running 1 tests
test foo ... OK
test result: OK. 1 passed; 0 failed; 0 ignored
The next challenge is getting rxinu
code to run in the unit tests. The most immediate problem is that we can't write extern crate rxinu;
in our tests
directory because rxinu
is compiled as a staticlib
.
I believe there are two paths forward from here:
Link rxinu.a
into tests module
I believe it's possible to link our rxinu.a
library into the tests module. However, this seems impractical because we would need to manually define all rxinu
functions as extern
.
Use a custom build script to build rxinu
crate as normal lib
By using a custom build script, we can first build rxinu
as a lib
. Then, we can create a staticlib
using the rxinu
crate. This way, we can easily call our rxinu
code in our tests
module:
#[test]
fn zero_mapped() {
use rxinu::arch::memory::Mapper;
let mut page_table = unsafe { Mapper::new() };
// address 0 is mapped
assert!(page_table.translate(0).is_some());
}
If necessary, we can follow this guide to use build.rs
only for cargo test
Unit tests are definitely achievable. See Phil's post about unit testing.