Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests #118

Merged
merged 9 commits into from
Nov 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
language: rust
cache: cargo
rust:
- nightly
install:
- sudo apt-get -qqy install qemu-system-x86
before_script:
- rustup component add rust-src
- rustup component add llvm-tools-preview
- cargo install bootimage
script:
- cargo test --lib --no-default-features --features serial,qwerty,pcnet -- -display none -serial stdio -device isa-debug-exit,iobase=0xf4,iosize=0x04
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,6 @@ volatile = "0.2.6"
vte = "0.8.0"
x86_64 = "0.12.2"
time = { version = "0.2.22", default-features = false }

[package.metadata.bootimage]
test-success-exit-code = 33 # (0x10 << 1) | 1
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@ endif

qemu:
qemu-system-x86_64 $(opts)

test:
cargo test --lib --no-default-features --features serial,$(keyboard),$(nic) -- \
-display none -serial stdio -device isa-debug-exit,iobase=0xf4,iosize=0x04
25 changes: 25 additions & 0 deletions src/kernel/allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,28 @@ pub fn used() -> usize {
pub fn free() -> usize {
ALLOCATOR.lock().free()
}

#[test_case]
fn many_boxes() {
use alloc::boxed::Box;

let heap_value_1 = Box::new(42);
let heap_value_2 = Box::new(1337);
assert_eq!(*heap_value_1, 42);
assert_eq!(*heap_value_2, 1337);

for i in 0..1000 {
let x = Box::new(i);
assert_eq!(*x, i);
}
}

#[test_case]
fn large_vec() {
let n = 1000;
let mut vec = Vec::new();
for i in 0..n {
vec.push(i);
}
assert_eq!(vec.iter().sum::<u64>(), (n - 1) * n / 2);
}
10 changes: 10 additions & 0 deletions src/kernel/clock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,13 @@ fn is_leap_year(year: u64) -> bool {
true
}
}

#[test_case]
fn uptime_assertion() {
assert!(uptime() > 0.0);
}

#[test_case]
fn realtime_assertion() {
assert!(realtime() > 1234567890.0);
}
20 changes: 11 additions & 9 deletions src/kernel/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,15 +157,17 @@ macro_rules! print {
#[macro_export]
macro_rules! log {
($($arg:tt)*) => ({
let uptime = $crate::kernel::clock::uptime();
let csi_color = $crate::kernel::console::Style::color("LightGreen");
let csi_reset = $crate::kernel::console::Style::reset();
if cfg!(feature="vga") {
$crate::kernel::vga::print_fmt(format_args!("{}[{:.6}]{} ", csi_color, uptime, csi_reset));
$crate::kernel::vga::print_fmt(format_args!($($arg)*));
} else {
$crate::kernel::serial::print_fmt(format_args!("{}[{:.6}]{} ", csi_color, uptime, csi_reset));
$crate::kernel::serial::print_fmt(format_args!($($arg)*));
if !cfg!(test) {
let uptime = $crate::kernel::clock::uptime();
let csi_color = $crate::kernel::console::Style::color("LightGreen");
let csi_reset = $crate::kernel::console::Style::reset();
if cfg!(feature="vga") {
$crate::kernel::vga::print_fmt(format_args!("{}[{:.6}]{} ", csi_color, uptime, csi_reset));
$crate::kernel::vga::print_fmt(format_args!($($arg)*));
} else {
$crate::kernel::serial::print_fmt(format_args!("{}[{:.6}]{} ", csi_color, uptime, csi_reset));
$crate::kernel::serial::print_fmt(format_args!($($arg)*));
}
}
});
}
Expand Down
15 changes: 15 additions & 0 deletions src/kernel/random.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#[cfg(not(test))]
use rand_chacha::ChaChaRng;
#[cfg(not(test))]
use rand_core::{RngCore, SeedableRng};
use x86_64::instructions::random::RdRand;

// FIXME: Compiling this in test generate the following error:
// LLVM ERROR: Do not know how to split the result of this operator!
#[cfg(not(test))]
pub fn get_u64() -> u64 {
let mut seed = [0u8; 32];
if let Some(rdrand) = RdRand::new() {
Expand All @@ -19,6 +24,16 @@ pub fn get_u64() -> u64 {
chacha.next_u64()
}

#[cfg(test)]
pub fn get_u64() -> u64 {
if let Some(rdrand) = RdRand::new() {
if let Some(rand) = rdrand.get_u64() {
return rand;
}
}
0
}

pub fn get_u32() -> u32 {
get_u64() as u32
}
Expand Down
82 changes: 82 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#![no_std]
#![feature(alloc_error_handler)]
#![feature(abi_x86_interrupt)]
#![cfg_attr(test, no_main)]
#![feature(custom_test_frameworks)]
#![test_runner(crate::test_runner)]
#![reexport_test_harness_main = "test_main"]

extern crate alloc;

Expand Down Expand Up @@ -33,3 +37,81 @@ pub fn init(boot_info: &'static BootInfo) {
fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! {
panic!("allocation error: {:?}", layout)
}

pub trait Testable {
fn run(&self) -> ();
}

impl<T> Testable for T where T: Fn() {
fn run(&self) {
print!("test {} ... ", core::any::type_name::<T>());
self();
let csi_color = kernel::console::Style::color("LightGreen");
let csi_reset = kernel::console::Style::reset();
print!("{}ok{}\n", csi_color, csi_reset);
}
}

pub fn test_runner(tests: &[&dyn Testable]) {
let n = tests.len();
print!("\nrunning {} test{}\n", n, if n == 1 { "" } else { "s" });
for test in tests {
test.run();
}
exit_qemu(QemuExitCode::Success);
}


#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)]
pub enum QemuExitCode {
Success = 0x10,
Failed = 0x11,
}

pub fn exit_qemu(exit_code: QemuExitCode) {
use x86_64::instructions::port::Port;

unsafe {
let mut port = Port::new(0xf4);
port.write(exit_code as u32);
}
}

pub fn hlt_loop() -> ! {
loop {
x86_64::instructions::hlt();
}
}

#[cfg(test)]
use bootloader::entry_point;

#[cfg(test)]
use core::panic::PanicInfo;

#[cfg(test)]
entry_point!(test_kernel_main);

#[cfg(test)]
fn test_kernel_main(boot_info: &'static BootInfo) -> ! {
init(boot_info);
test_main();
hlt_loop();
}

#[cfg(test)]
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
let csi_color = kernel::console::Style::color("LightRed");
let csi_reset = kernel::console::Style::reset();
print!("{}failed{}\n\n", csi_color, csi_reset);
print!("{}\n\n", info);
exit_qemu(QemuExitCode::Failed);
hlt_loop();
}

#[test_case]
fn trivial_assertion() {
assert_eq!(1, 1);
}