From 4dfa0230ea3faddbca6bd334dd3eabff3d930970 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Tue, 8 Apr 2025 16:51:10 +0300 Subject: [PATCH 01/31] add baisc test runner, notes - global search RYANS-NOTES --- kernel/src/main.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 7cd0d5a..b403ab2 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -1,13 +1,23 @@ #![no_std] #![no_main] +#![feature(custom_test_frameworks)] +#![test_runner(crate::test_runner)] use hexium_os::{boot, hlt_loop, init, panic_log}; +use hexium_os::{info, print, println}; // RYANS_NOTES: Keeping the imports used in the comments further below #[unsafe(no_mangle)] unsafe extern "C" fn kmain() -> ! { assert!(boot::BASE_REVISION.is_supported()); init(); + + // RYANS_NOTES: The lines below do not seem to have an effect after the init method above however calling them above the init method causes a bootloop. + // print!("Test"); + // println!("Test2"); + // info!("Test3"); + // panic!("Some message"); + // info!("Test4"); hlt_loop(); } @@ -19,3 +29,13 @@ fn rust_panic(info: &core::panic::PanicInfo) -> ! { print_register_dump(&get_registers()); hlt_loop(); } + +#[cfg(test)] +fn test_runner(tests: &[&dyn Fn()]) { + + println!("Running {} tests", tests.len()); + + for test in tests { + test(); + } +} \ No newline at end of file From 9e060bbd80bd05e3e6b5481e17ba25446f2e795a Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Tue, 8 Apr 2025 19:18:17 +0300 Subject: [PATCH 02/31] WIP - fix panic_handler not found, current error, invalid memory reference --- kernel/src/lib.rs | 28 ++++++++++++++++++++++++---- kernel/src/main.rs | 38 ++++++++++++++++++++++++++++---------- 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 7e9923d..8e1c56c 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -1,10 +1,13 @@ #![no_std] +#![no_main] #![feature(abi_x86_interrupt)] +#![feature(custom_test_frameworks)] +#![test_runner(test_runner)] extern crate alloc; use alloc::string::String; -use core::arch::asm; +use core::{arch::asm, panic::PanicInfo}; pub mod boot; pub mod devices; @@ -26,12 +29,17 @@ pub fn init() { let mut vfs = fs::vfs::VFS::new(None); fs::ramfs::init(&mut vfs); + + info!("Before\n"); print_startup_message(&mut vfs); + info!("After\n"); - let mut executor = crate::task::executor::Executor::new(); - let _ = executor.spawn(crate::task::Task::new(devices::keyboard::trace_keypresses())); - executor.run(); + // RYAN-NOTES: Commented out for now as the code doesn't run past this section. Will return it back. + // let mut executor = crate::task::executor::Executor::new(); + // let _ = executor.spawn(crate::task::Task::new(devices::keyboard::trace_keypresses())); + // executor.run(); + info!("After2\n"); //vfs.unmount_fs(); } @@ -50,6 +58,8 @@ fn print_startup_message(vfs: &mut fs::vfs::VFS) -> [u8; 128] { } } + info!("Testing\n"); + info!( "Hexium OS kernel v{} succesfully initialized at {}\n", env!("CARGO_PKG_VERSION"), @@ -72,3 +82,13 @@ pub fn hlt_loop() -> ! { } } } + +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + loop {} +} + + +fn test_runner(_test: &[&i32]) { + loop {} +} \ No newline at end of file diff --git a/kernel/src/main.rs b/kernel/src/main.rs index b403ab2..afacb3d 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -2,37 +2,55 @@ #![no_main] #![feature(custom_test_frameworks)] #![test_runner(crate::test_runner)] +#![reexport_test_harness_main = "test_main"] use hexium_os::{boot, hlt_loop, init, panic_log}; use hexium_os::{info, print, println}; // RYANS_NOTES: Keeping the imports used in the comments further below +// use crate::{info, print, println}; #[unsafe(no_mangle)] unsafe extern "C" fn kmain() -> ! { assert!(boot::BASE_REVISION.is_supported()); init(); + + info!("Info in main"); + panic_log!("Panic log"); + + print!("Test2\n"); + + + #[cfg(test)] + test_main(); + // RYANS_NOTES: The lines below do not seem to have an effect after the init method above however calling them above the init method causes a bootloop. // print!("Test"); // println!("Test2"); // info!("Test3"); - // panic!("Some message"); + panic!("Some message"); // info!("Test4"); hlt_loop(); } -#[panic_handler] -fn rust_panic(info: &core::panic::PanicInfo) -> ! { - use hexium_os::utils::registers::*; - panic_log!("{}\n", info); - print_register_dump(&get_registers()); - hlt_loop(); -} +// #[cfg(test)] +// #[panic_handler] +// pub fn test_panic(info: &core::panic::PanicInfo) -> ! { +// hlt_loop(); +// } + +// #[cfg(not(test))] +// #[panic_handler] +// fn rust_panic(info: &core::panic::PanicInfo) -> ! { +// use hexium_os::utils::registers::*; +// panic_log!("{}\n", info); +// print_register_dump(&get_registers()); +// hlt_loop(); +// } #[cfg(test)] -fn test_runner(tests: &[&dyn Fn()]) { - +pub fn test_runner(tests: &[&dyn Fn()]) { println!("Running {} tests", tests.len()); for test in tests { From b9147dc30a3d35f88bd7c592e972f288c05f2b36 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Thu, 10 Apr 2025 14:24:54 +0300 Subject: [PATCH 03/31] wip - testing scripts --- GNUmakefile | 31 +++++++++++++++++++++++++++++++ kernel/.gitignore | 1 + kernel/GNUmakefile | 4 ++++ 3 files changed, 36 insertions(+) diff --git a/GNUmakefile b/GNUmakefile index 9a25ece..035e084 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -28,6 +28,14 @@ run-x86_64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME). -cdrom $(IMAGE_NAME).iso \ $(QEMUFLAGS) +.PHONY: test-run +test-run: + make test + qemu-system-x86_64 hexium_os-x86_64-test.iso + +.PHONY: test +test: $(IMAGE_NAME)-test.iso + ovmf/ovmf-code-$(KARCH).fd: mkdir -p ovmf curl -Lo $@ https://github.com/osdev0/edk2-ovmf-nightly/releases/latest/download/ovmf-code-$(KARCH).fd @@ -45,6 +53,10 @@ limine/limine: kernel: $(MAKE) -C kernel +.PHONY: kernel-test +kernel-test: + $(MAKE) -C kernel test + .PHONY: ramfs ramfs: mkdir -p initrd/ @@ -69,6 +81,25 @@ $(IMAGE_NAME).iso: limine/limine kernel ramfs ./limine/limine bios-install $(IMAGE_NAME).iso rm -rf iso_root +$(IMAGE_NAME)-test.iso: limine/limine kernel-test ramfs + rm -rf iso_root + mkdir -p iso_root/boot + cp -v kernel/kernel-test iso_root/boot/ + cp -v ramfs.img iso_root/boot/ + mkdir -p iso_root/boot/limine + cp -v limine.conf iso_root/boot/limine/ + mkdir -p iso_root/EFI/BOOT + cp -v limine/limine-bios.sys limine/limine-bios-cd.bin limine/limine-uefi-cd.bin iso_root/boot/limine/ + cp -v limine/BOOTX64.EFI iso_root/EFI/BOOT/ + cp -v limine/BOOTIA32.EFI iso_root/EFI/BOOT/ + xorriso -as mkisofs -b boot/limine/limine-bios-cd.bin \ + -no-emul-boot -boot-load-size 4 -boot-info-table \ + --efi-boot boot/limine/limine-uefi-cd.bin \ + -efi-boot-part --efi-boot-image --protective-msdos-label \ + iso_root -o $(IMAGE_NAME)-test.iso + ./limine/limine bios-install $(IMAGE_NAME)-test.iso + rm -rf iso_root + .PHONY: clean clean: $(MAKE) -C kernel clean diff --git a/kernel/.gitignore b/kernel/.gitignore index 5d7f773..9feff12 100644 --- a/kernel/.gitignore +++ b/kernel/.gitignore @@ -1,2 +1,3 @@ /kernel /target +/kernel-test \ No newline at end of file diff --git a/kernel/GNUmakefile b/kernel/GNUmakefile index e2961fe..f9bf68a 100644 --- a/kernel/GNUmakefile +++ b/kernel/GNUmakefile @@ -28,6 +28,10 @@ all: RUSTFLAGS="-C relocation-model=static" cargo build --target $(RUST_TARGET) --profile $(RUST_PROFILE) cp target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR)/hexium_os kernel +test: + RUSTFLAGS="-C relocation-model=static" cargo build --tests --target $(RUST_TARGET) --profile $(RUST_PROFILE) + cp "$(shell find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2-)" kernel-test + .PHONY: clean clean: cargo clean From 0c23f02fb1f3c811d41a011529299eb16ee9fa09 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Mon, 14 Apr 2025 16:46:13 +0300 Subject: [PATCH 04/31] build exec file type --- kernel/GNUmakefile | 10 ++++++++++ kernel/src/lib.rs | 1 + kernel/src/main.rs | 26 +++++++++++++++++++++++++- kernel/src/tests.rs | 8 ++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 kernel/src/tests.rs diff --git a/kernel/GNUmakefile b/kernel/GNUmakefile index f9bf68a..ed0935b 100644 --- a/kernel/GNUmakefile +++ b/kernel/GNUmakefile @@ -30,12 +30,22 @@ all: test: RUSTFLAGS="-C relocation-model=static" cargo build --tests --target $(RUST_TARGET) --profile $(RUST_PROFILE) + find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2- + + shell find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2- + echo $(find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2-) + echo '$(find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2-)' + echo "$(find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2-)" + echo $(shell find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2-) + echo '$(shell find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2-)' + echo "$(shell find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2-)" cp "$(shell find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2-)" kernel-test .PHONY: clean clean: cargo clean rm -rf kernel + rm -rf kernel-test .PHONY: distclean distclean: clean diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 8e1c56c..87443ec 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -21,6 +21,7 @@ pub mod serial; pub mod task; pub mod utils; pub mod writer; +pub mod tests; pub fn init() { writer::init(); diff --git a/kernel/src/main.rs b/kernel/src/main.rs index afacb3d..42b5907 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -2,12 +2,36 @@ #![no_main] #![feature(custom_test_frameworks)] #![test_runner(crate::test_runner)] -#![reexport_test_harness_main = "test_main"] +// #![reexport_test_harness_main = "test_main"] +use hexium_os::tests::{run_tests, TestCase}; use hexium_os::{boot, hlt_loop, init, panic_log}; use hexium_os::{info, print, println}; // RYANS_NOTES: Keeping the imports used in the comments further below // use crate::{info, print, println}; +fn test_example() -> Result<(), &'static str>{ + assert_eq!(1+1, 2); + Ok(()) +} + +pub fn test_main() { + let tests = [ + TestCase{ + name: "test_example", + function: test_example, + } + ]; + + run_tests(&tests); +} + +#[cfg(feature = "test")] +unsafe extern "C" fn kmain() -> ! { + test_main(); + loop {} +} + +#[cfg(not(feature = "test"))] #[unsafe(no_mangle)] unsafe extern "C" fn kmain() -> ! { assert!(boot::BASE_REVISION.is_supported()); diff --git a/kernel/src/tests.rs b/kernel/src/tests.rs new file mode 100644 index 0000000..23fa62a --- /dev/null +++ b/kernel/src/tests.rs @@ -0,0 +1,8 @@ +pub struct TestCase { + pub name: &'static str, + pub function: fn() -> Result<(), &'static str>, +} + +pub fn run_tests(tests: &[TestCase]) { + +} \ No newline at end of file From a67a847def6172c0c3bbaa375701d010280223b5 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Tue, 15 Apr 2025 14:52:25 +0300 Subject: [PATCH 05/31] get a test image running --- GNUmakefile | 5 +++-- kernel/src/main.rs | 10 ++++++++-- kernel/src/tests.rs | 17 +++++++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 035e084..89dd5a1 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -81,10 +81,11 @@ $(IMAGE_NAME).iso: limine/limine kernel ramfs ./limine/limine bios-install $(IMAGE_NAME).iso rm -rf iso_root +# TODO: Use different build folders to avoid cross contamination $(IMAGE_NAME)-test.iso: limine/limine kernel-test ramfs rm -rf iso_root mkdir -p iso_root/boot - cp -v kernel/kernel-test iso_root/boot/ + cp -v kernel/kernel-test iso_root/boot/kernel cp -v ramfs.img iso_root/boot/ mkdir -p iso_root/boot/limine cp -v limine.conf iso_root/boot/limine/ @@ -103,7 +104,7 @@ $(IMAGE_NAME)-test.iso: limine/limine kernel-test ramfs .PHONY: clean clean: $(MAKE) -C kernel clean - rm -rf iso_root $(IMAGE_NAME).iso + rm -rf iso_root *.iso .PHONY: distclean distclean: clean diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 42b5907..4742a05 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -25,13 +25,19 @@ pub fn test_main() { run_tests(&tests); } -#[cfg(feature = "test")] +#[cfg(test)] +#[unsafe(no_mangle)] unsafe extern "C" fn kmain() -> ! { + // info!("Test Main"); + assert!(boot::BASE_REVISION.is_supported()); + init(); + info!("Test Main:1"); test_main(); + info!("Test Main:2"); loop {} } -#[cfg(not(feature = "test"))] +#[cfg(not(test))] #[unsafe(no_mangle)] unsafe extern "C" fn kmain() -> ! { assert!(boot::BASE_REVISION.is_supported()); diff --git a/kernel/src/tests.rs b/kernel/src/tests.rs index 23fa62a..bea5ea2 100644 --- a/kernel/src/tests.rs +++ b/kernel/src/tests.rs @@ -1,8 +1,25 @@ +use crate::{info}; pub struct TestCase { pub name: &'static str, pub function: fn() -> Result<(), &'static str>, } pub fn run_tests(tests: &[TestCase]) { + info!("Running {} tests...", tests.len()); + let mut passed = 0; + + for test in tests { + info!("Test {}", test.name); + + match (test.function)() { + Ok(()) => { + info!("Ok"); + passed += 1; + }, + Err(msg) => info!("FAILED: {}", msg), + } + } + + info!("Passed tests {}, Failed tests {}", passed, tests.len() - passed); } \ No newline at end of file From 2c9d16ff5ebbda6202aeb5fc0db7a061a1276ebf Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Tue, 15 Apr 2025 15:01:33 +0300 Subject: [PATCH 06/31] log on new lines --- kernel/src/devices/keyboard/mod.rs | 4 ++-- kernel/src/fs/ramfs.rs | 6 +++--- kernel/src/interrupts/idt.rs | 2 +- kernel/src/lib.rs | 14 +++++++------- kernel/src/log.rs | 2 +- kernel/src/memory/mod.rs | 2 +- kernel/src/memory/paging.rs | 6 +++--- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/kernel/src/devices/keyboard/mod.rs b/kernel/src/devices/keyboard/mod.rs index 0f56b6b..88157d8 100644 --- a/kernel/src/devices/keyboard/mod.rs +++ b/kernel/src/devices/keyboard/mod.rs @@ -96,10 +96,10 @@ pub async fn trace_keypresses() { if let Some(key) = keyboard.process_keyevent(key_event) { match key { DecodedKey::Unicode(character) => { - trace!("Received keyboard interrupt with key: {}\n", character) + trace!("Received keyboard interrupt with key: {}", character) } DecodedKey::RawKey(key) => { - trace!("Received keyboard interrupt with key: {:?}\n", key) + trace!("Received keyboard interrupt with key: {:?}", key) } } } diff --git a/kernel/src/fs/ramfs.rs b/kernel/src/fs/ramfs.rs index 697afd1..ef49071 100644 --- a/kernel/src/fs/ramfs.rs +++ b/kernel/src/fs/ramfs.rs @@ -20,12 +20,12 @@ impl RamFs { impl FileSystem for RamFs { fn mount(&mut self, _path: &str) -> Result<(), ()> { - info!("RamFs mounted\n"); + info!("RamFs mounted"); Ok(()) } fn unmount(&mut self) -> Result<(), String> { - info!("RamFs unmounted\n"); + info!("RamFs unmounted"); Ok(()) } @@ -60,7 +60,7 @@ pub fn init(vfs: &mut VFS) { if let Some(module_response) = boot::MODULE_REQUEST.get_response() { let modules = module_response.modules(); if !modules.is_empty() { - trace!("Ramdisk information:\n"); + trace!("Ramdisk information:"); print!(" Ramdisk address: {:?}\n", modules[0].addr()); print!(" Ramdisk size (bytes): {:?}\n", modules[0].size()); print!(" Ramdisk module path: {:?}\n", modules[0].path()); diff --git a/kernel/src/interrupts/idt.rs b/kernel/src/interrupts/idt.rs index b54b417..4d8925e 100644 --- a/kernel/src/interrupts/idt.rs +++ b/kernel/src/interrupts/idt.rs @@ -29,7 +29,7 @@ pub fn init() { } extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) { - debug!("EXCEPTION: BREAKPOINT\n{:#?}\n", stack_frame); + debug!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame); } extern "x86-interrupt" fn double_fault_handler( diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 87443ec..a32f837 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -31,16 +31,16 @@ pub fn init() { let mut vfs = fs::vfs::VFS::new(None); fs::ramfs::init(&mut vfs); - info!("Before\n"); + info!("Before"); print_startup_message(&mut vfs); - info!("After\n"); + info!("After"); // RYAN-NOTES: Commented out for now as the code doesn't run past this section. Will return it back. // let mut executor = crate::task::executor::Executor::new(); // let _ = executor.spawn(crate::task::Task::new(devices::keyboard::trace_keypresses())); // executor.run(); - info!("After2\n"); + info!("After2"); //vfs.unmount_fs(); } @@ -51,18 +51,18 @@ fn print_startup_message(vfs: &mut fs::vfs::VFS) -> [u8; 128] { Ok(vnode) => match vfs.read_file(&vnode, &mut buffer, 0) { Ok(_bytes_read) => {} Err(err) => { - error!("Error reading file: {}\n", err); + error!("Error reading file: {}", err); } }, Err(err) => { - error!("File not found: {}\n", err); + error!("File not found: {}", err); } } - info!("Testing\n"); + info!("Testing"); info!( - "Hexium OS kernel v{} succesfully initialized at {}\n", + "Hexium OS kernel v{} succesfully initialized at {}", env!("CARGO_PKG_VERSION"), unsafe { rtc::read_rtc() } ); diff --git a/kernel/src/log.rs b/kernel/src/log.rs index ce44d89..d2e8e46 100644 --- a/kernel/src/log.rs +++ b/kernel/src/log.rs @@ -26,7 +26,7 @@ macro_rules! log { $crate::log::LogLevel::Panic => ("PANIC", "\x1b[97;41m"), // White text on Red background }; - $crate::print!("{}[{}]\x1b[0m {}", color_code, label, format_args!($($arg)*)); + $crate::println!("{}[{}]\x1b[0m {}", color_code, label, format_args!($($arg)*)); }}; } diff --git a/kernel/src/memory/mod.rs b/kernel/src/memory/mod.rs index 70994fc..d429d1e 100644 --- a/kernel/src/memory/mod.rs +++ b/kernel/src/memory/mod.rs @@ -14,7 +14,7 @@ pub fn init() -> () { if let Some(hhdm_response) = boot::HHDM_REQUEST.get_response() { PHYS_MEM_OFFSET.call_once(|| VirtAddr::new(hhdm_response.offset())); } - trace!("Hhdm offset: {:#x}\n", phys_mem_offset()); + trace!("Hhdm offset: {:#x}", phys_mem_offset()); // Create frame allocator let mut frame_allocator = diff --git a/kernel/src/memory/paging.rs b/kernel/src/memory/paging.rs index af42cfc..a4a6f3a 100644 --- a/kernel/src/memory/paging.rs +++ b/kernel/src/memory/paging.rs @@ -28,9 +28,9 @@ pub extern "x86-interrupt" fn page_fault_handler( ) { use x86_64::registers::control::Cr2; - error!("EXCEPTION: PAGE FAULT\n"); - error!("Accessed Address: {:?}\n", Cr2::read()); - error!("Error Code: {:?}\n", error_code); + error!("EXCEPTION: PAGE FAULT"); + error!("Accessed Address: {:?}", Cr2::read()); + error!("Error Code: {:?}", error_code); print!("\n{:#?}\n", stack_frame); hlt_loop(); } From 953f76d4180075cd32201bf63cef43dcc56c4698 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Tue, 15 Apr 2025 15:48:01 +0300 Subject: [PATCH 07/31] use rust default test_main --- kernel/src/main.rs | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 4742a05..2bb9019 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -2,28 +2,41 @@ #![no_main] #![feature(custom_test_frameworks)] #![test_runner(crate::test_runner)] -// #![reexport_test_harness_main = "test_main"] +#![reexport_test_harness_main = "test_main"] use hexium_os::tests::{run_tests, TestCase}; use hexium_os::{boot, hlt_loop, init, panic_log}; use hexium_os::{info, print, println}; // RYANS_NOTES: Keeping the imports used in the comments further below // use crate::{info, print, println}; +#[test_case] +fn test_fail_example() { + println!("test_fail_example..."); + assert_eq!(1, 2); + println!("ok!"); +} + +#[test_case] +fn test_example2() { + println!("test_example2"); + assert_eq!(1+1, 2); + println!("ok!"); +} fn test_example() -> Result<(), &'static str>{ assert_eq!(1+1, 2); Ok(()) } -pub fn test_main() { - let tests = [ - TestCase{ - name: "test_example", - function: test_example, - } - ]; +// pub fn test_main() { +// let tests = [ +// TestCase{ +// name: "test_example", +// function: test_example, +// } +// ]; - run_tests(&tests); -} +// run_tests(&tests); +// } #[cfg(test)] #[unsafe(no_mangle)] From 8ed3088e9b3a66a7951881a4cb504ba202645b57 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Tue, 15 Apr 2025 16:05:47 +0300 Subject: [PATCH 08/31] exit qemu with custom exit code after tests complete --- GNUmakefile | 2 +- kernel/src/main.rs | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 89dd5a1..fc6ad1c 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -31,7 +31,7 @@ run-x86_64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME). .PHONY: test-run test-run: make test - qemu-system-x86_64 hexium_os-x86_64-test.iso + qemu-system-x86_64 hexium_os-x86_64-test.iso -device isa-debug-exit,iobase=0xf4,iosize=0x04 || [ $$? -eq 33 ] .PHONY: test test: $(IMAGE_NAME)-test.iso diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 2bb9019..b98a598 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -11,7 +11,7 @@ use hexium_os::{info, print, println}; // RYANS_NOTES: Keeping the imports used #[test_case] fn test_fail_example() { println!("test_fail_example..."); - assert_eq!(1, 2); + assert_eq!(1, 1); println!("ok!"); } @@ -99,4 +99,22 @@ pub fn test_runner(tests: &[&dyn Fn()]) { for test in tests { test(); } + + 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); + } } \ No newline at end of file From eb459b33bad95b7f4d492f01b2de21e9a0a74035 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Wed, 16 Apr 2025 08:48:14 +0300 Subject: [PATCH 09/31] add test panic handler; for some reason isn't called in tests, main one is instead --- GNUmakefile | 2 +- kernel/src/lib.rs | 74 ++++++++++++++++++++++++++++++++++++++++++++-- kernel/src/main.rs | 30 +++++-------------- 3 files changed, 79 insertions(+), 27 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index fc6ad1c..c862798 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -31,7 +31,7 @@ run-x86_64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME). .PHONY: test-run test-run: make test - qemu-system-x86_64 hexium_os-x86_64-test.iso -device isa-debug-exit,iobase=0xf4,iosize=0x04 || [ $$? -eq 33 ] + qemu-system-x86_64 hexium_os-x86_64-test.iso -device isa-debug-exit,iobase=0xf4,iosize=0x04 -serial stdio || [ $$? -eq 33 ] .PHONY: test test: $(IMAGE_NAME)-test.iso diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index a32f837..b39a54f 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -8,6 +8,7 @@ extern crate alloc; use alloc::string::String; use core::{arch::asm, panic::PanicInfo}; +use utils::registers::{get_registers, print_register_dump}; pub mod boot; pub mod devices; @@ -84,12 +85,79 @@ pub fn hlt_loop() -> ! { } } +#[cfg(test)] #[panic_handler] -fn panic(_info: &PanicInfo) -> ! { - loop {} +fn rust_panic(info: &core::panic::PanicInfo) -> ! { + serial_println!("[failed]"); + serial_println!("Error: {}", info); + exit_qemu(QemuExitCode::Failed); + hlt_loop(); +} + +#[cfg(not(test))] +#[panic_handler] +fn rust_panic(info: &core::panic::PanicInfo) -> ! { + panic_log!("{}\n", info); + print_register_dump(&get_registers()); + #[cfg(test)] + println!("Test"); + #[cfg(not(test))] + println!("Not Test"); + print!("Main Panic"); + hlt_loop(); } +// #[cfg(not(test))] +// #[panic_handler] +// fn rust_panic(info: &core::panic::PanicInfo) -> ! { +// serial_println!("Rust panic"); +// #[cfg(test)] +// test_panic_handler(&info); +// #[cfg(not(test))] +// main_panic_handler(&info); +// hlt_loop(); +// } + +// fn main_panic_handler(info: &PanicInfo) { +// println!("Main panic handler"); +// panic_log!("{}\n", info); +// print_register_dump(&get_registers()); +// #[cfg(test)] +// println!("Test"); +// #[cfg(not(test))] +// println!("Not Test"); +// print!("Main Panic"); +// } + +// fn test_panic_handler(info: &PanicInfo) { +// println!("Test panic handler"); +// serial_println!("[failed]"); +// serial_println!("Error: {}", info); +// exit_qemu(QemuExitCode::Failed); +// } fn test_runner(_test: &[&i32]) { loop {} -} \ No newline at end of file +} + + +#[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); + } +} + +// #[panic_handler] +// fn panic(_info: &PanicInfo) -> ! { +// loop {} +// } diff --git a/kernel/src/main.rs b/kernel/src/main.rs index b98a598..acb53ad 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -5,21 +5,21 @@ #![reexport_test_harness_main = "test_main"] use hexium_os::tests::{run_tests, TestCase}; -use hexium_os::{boot, hlt_loop, init, panic_log}; +use hexium_os::{boot, hlt_loop, init, panic_log, serial_println, exit_qemu, QemuExitCode}; use hexium_os::{info, print, println}; // RYANS_NOTES: Keeping the imports used in the comments further below // use crate::{info, print, println}; #[test_case] fn test_fail_example() { - println!("test_fail_example..."); - assert_eq!(1, 1); - println!("ok!"); + serial_println!("test_fail_example..."); + assert_eq!(0, 1); + serial_println!("ok!"); } #[test_case] fn test_example2() { - println!("test_example2"); + serial_println!("test_example2"); assert_eq!(1+1, 2); - println!("ok!"); + serial_println!("ok!"); } fn test_example() -> Result<(), &'static str>{ @@ -94,27 +94,11 @@ unsafe extern "C" fn kmain() -> ! { #[cfg(test)] pub fn test_runner(tests: &[&dyn Fn()]) { - println!("Running {} tests", tests.len()); + serial_println!("Running {} tests", tests.len()); for test in tests { test(); } 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); - } } \ No newline at end of file From 98358ad57d11b4e3b17b8d03477746c255b73ba4 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Wed, 16 Apr 2025 09:22:50 +0300 Subject: [PATCH 10/31] hide display for tests --- GNUmakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GNUmakefile b/GNUmakefile index c862798..7790d89 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -31,7 +31,7 @@ run-x86_64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME). .PHONY: test-run test-run: make test - qemu-system-x86_64 hexium_os-x86_64-test.iso -device isa-debug-exit,iobase=0xf4,iosize=0x04 -serial stdio || [ $$? -eq 33 ] + qemu-system-x86_64 hexium_os-x86_64-test.iso -device isa-debug-exit,iobase=0xf4,iosize=0x04 -serial stdio -display none || [ $$? -eq 33 ] .PHONY: test test: $(IMAGE_NAME)-test.iso From ad66ba9c0078fc9eaf3ef305b65a4749f786bc1f Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Wed, 16 Apr 2025 09:23:05 +0300 Subject: [PATCH 11/31] remove failing test --- kernel/src/lib.rs | 2 +- kernel/src/main.rs | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index b39a54f..02083ce 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -36,7 +36,7 @@ pub fn init() { print_startup_message(&mut vfs); info!("After"); - // RYAN-NOTES: Commented out for now as the code doesn't run past this section. Will return it back. + // RYAN_NOTES: Commented out for now as the code doesn't run past this section. Will return it back. // let mut executor = crate::task::executor::Executor::new(); // let _ = executor.spawn(crate::task::Task::new(devices::keyboard::trace_keypresses())); // executor.run(); diff --git a/kernel/src/main.rs b/kernel/src/main.rs index acb53ad..7d09522 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -8,12 +8,14 @@ use hexium_os::tests::{run_tests, TestCase}; use hexium_os::{boot, hlt_loop, init, panic_log, serial_println, exit_qemu, QemuExitCode}; use hexium_os::{info, print, println}; // RYANS_NOTES: Keeping the imports used in the comments further below // use crate::{info, print, println}; -#[test_case] -fn test_fail_example() { - serial_println!("test_fail_example..."); - assert_eq!(0, 1); - serial_println!("ok!"); -} + +// RYAN_NOTES: Commented out because failing tests failed to close qemu since the main panic handler is still being called instead of the test panic handler +// #[test_case] +// fn test_fail_example() { +// serial_println!("test_fail_example..."); +// assert_eq!(0, 1); +// serial_println!("ok!"); +// } #[test_case] fn test_example2() { From aa52e5c5c0f782979d847badd255e005cda6fcd1 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Wed, 16 Apr 2025 09:41:38 +0300 Subject: [PATCH 12/31] define testable trait for tests --- kernel/src/lib.rs | 14 ++++++++++++++ kernel/src/main.rs | 10 +++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 02083ce..46146f8 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -157,6 +157,20 @@ pub fn exit_qemu(exit_code: QemuExitCode) { } } +pub trait Testable { + fn run(&self) -> (); +} + +impl Testable for T +where T : Fn(), +{ + fn run(&self) -> () { + serial_print!("{}...\t", core::any::type_name::()); + self(); + serial_println!("[ok]"); + } +} + // #[panic_handler] // fn panic(_info: &PanicInfo) -> ! { // loop {} diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 7d09522..a3355cc 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -5,7 +5,7 @@ #![reexport_test_harness_main = "test_main"] use hexium_os::tests::{run_tests, TestCase}; -use hexium_os::{boot, hlt_loop, init, panic_log, serial_println, exit_qemu, QemuExitCode}; +use hexium_os::{boot, hlt_loop, init, panic_log, serial_println, exit_qemu, QemuExitCode, Testable}; use hexium_os::{info, print, println}; // RYANS_NOTES: Keeping the imports used in the comments further below // use crate::{info, print, println}; @@ -19,9 +19,9 @@ use hexium_os::{info, print, println}; // RYANS_NOTES: Keeping the imports used #[test_case] fn test_example2() { - serial_println!("test_example2"); + // serial_println!("test_example2"); assert_eq!(1+1, 2); - serial_println!("ok!"); + // serial_println!("ok!"); } fn test_example() -> Result<(), &'static str>{ @@ -95,11 +95,11 @@ unsafe extern "C" fn kmain() -> ! { // } #[cfg(test)] -pub fn test_runner(tests: &[&dyn Fn()]) { +pub fn test_runner(tests: &[&dyn Testable]) { serial_println!("Running {} tests", tests.len()); for test in tests { - test(); + test.run(); } exit_qemu(QemuExitCode::Success); From fb97de1b0132c517ab5e3fcbb2e8a73fb288431d Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Wed, 16 Apr 2025 10:18:21 +0300 Subject: [PATCH 13/31] println tests --- kernel/src/main.rs | 27 +++++++++++++++++++++++++++ kernel/src/writer.rs | 1 - 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/kernel/src/main.rs b/kernel/src/main.rs index a3355cc..d7f20bf 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -4,7 +4,10 @@ #![test_runner(crate::test_runner)] #![reexport_test_harness_main = "test_main"] +use core::fmt::Write; + use hexium_os::tests::{run_tests, TestCase}; +use hexium_os::writer::WRITER; use hexium_os::{boot, hlt_loop, init, panic_log, serial_println, exit_qemu, QemuExitCode, Testable}; use hexium_os::{info, print, println}; // RYANS_NOTES: Keeping the imports used in the comments further below // use crate::{info, print, println}; @@ -24,6 +27,30 @@ fn test_example2() { // serial_println!("ok!"); } +// RYAN_NOTES: Refactor these tests out of here +#[test_case] +fn test_println_simple() { + println!("Simple print new line statement"); +} + +#[test_case] +fn test_println_long() { + for _ in 0..200 { + println!("Simple print new line many times"); + } +} + +// TODO: RYAN_NOTES: Needs buffer access +// #[test_case] +// fn test_println_output() { +// let s = "Some test fitting single line"; +// println!("{}", s); +// for (i, c) in s.chars().enumerate() { +// let screen_char = WRITER.lock().write_char(c).buffer.chars[BUFFER_HEIGHT - 2][i].read(); +// assert_eq!(char::from(screen_char.ascii_character), c); +// } +// } + fn test_example() -> Result<(), &'static str>{ assert_eq!(1+1, 2); Ok(()) diff --git a/kernel/src/writer.rs b/kernel/src/writer.rs index 46884bc..4270e1d 100644 --- a/kernel/src/writer.rs +++ b/kernel/src/writer.rs @@ -103,6 +103,5 @@ pub fn _print(args: fmt::Arguments) { interrupts::without_interrupts(|| { WRITER.lock().write_fmt(args).unwrap(); - serial_print!("{}", args); }); } From 0b5ff9a54679e990729d7a499b8b1f9164ec7685 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Wed, 16 Apr 2025 12:01:23 +0300 Subject: [PATCH 14/31] properly refactor testing setup into lib --- kernel/src/lib.rs | 79 ++++++++++++------------------------ kernel/src/main.rs | 66 ++++++++---------------------- kernel/src/testsw/writer.rsw | 19 +++++++++ 3 files changed, 62 insertions(+), 102 deletions(-) create mode 100644 kernel/src/testsw/writer.rsw diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 46146f8..ac17ebc 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -1,8 +1,10 @@ #![no_std] #![no_main] +// #![cfg_attr(test, no_main)] #![feature(abi_x86_interrupt)] #![feature(custom_test_frameworks)] -#![test_runner(test_runner)] +#![test_runner(crate::test_runner)] +#![reexport_test_harness_main="test_main"] extern crate alloc; @@ -22,7 +24,7 @@ pub mod serial; pub mod task; pub mod utils; pub mod writer; -pub mod tests; +// pub mod tests; pub fn init() { writer::init(); @@ -85,59 +87,22 @@ pub fn hlt_loop() -> ! { } } -#[cfg(test)] -#[panic_handler] -fn rust_panic(info: &core::panic::PanicInfo) -> ! { +pub fn test_panic_handler(info: &PanicInfo) -> ! { + println!("Test panic handler"); serial_println!("[failed]"); serial_println!("Error: {}", info); exit_qemu(QemuExitCode::Failed); - hlt_loop(); + loop{} } -#[cfg(not(test))] -#[panic_handler] -fn rust_panic(info: &core::panic::PanicInfo) -> ! { - panic_log!("{}\n", info); - print_register_dump(&get_registers()); - #[cfg(test)] - println!("Test"); - #[cfg(not(test))] - println!("Not Test"); - print!("Main Panic"); - hlt_loop(); -} +pub fn test_runner(tests: &[&dyn Testable]) { + serial_println!("Running {} tests", tests.len()); -// #[cfg(not(test))] -// #[panic_handler] -// fn rust_panic(info: &core::panic::PanicInfo) -> ! { -// serial_println!("Rust panic"); -// #[cfg(test)] -// test_panic_handler(&info); -// #[cfg(not(test))] -// main_panic_handler(&info); -// hlt_loop(); -// } - -// fn main_panic_handler(info: &PanicInfo) { -// println!("Main panic handler"); -// panic_log!("{}\n", info); -// print_register_dump(&get_registers()); -// #[cfg(test)] -// println!("Test"); -// #[cfg(not(test))] -// println!("Not Test"); -// print!("Main Panic"); -// } - -// fn test_panic_handler(info: &PanicInfo) { -// println!("Test panic handler"); -// serial_println!("[failed]"); -// serial_println!("Error: {}", info); -// exit_qemu(QemuExitCode::Failed); -// } - -fn test_runner(_test: &[&i32]) { - loop {} + for test in tests { + test.run(); + } + + exit_qemu(QemuExitCode::Success); } @@ -171,7 +136,15 @@ where T : Fn(), } } -// #[panic_handler] -// fn panic(_info: &PanicInfo) -> ! { -// loop {} -// } +#[cfg(test)] +#[unsafe(no_mangle)] +unsafe extern "C" fn kmain() -> ! { + test_main(); + loop {} +} + +#[cfg(test)] +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + test_panic_handler(info) +} \ No newline at end of file diff --git a/kernel/src/main.rs b/kernel/src/main.rs index d7f20bf..01255fa 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -1,30 +1,25 @@ #![no_std] #![no_main] #![feature(custom_test_frameworks)] -#![test_runner(crate::test_runner)] +#![test_runner(hexium_os::test_runner)] #![reexport_test_harness_main = "test_main"] use core::fmt::Write; -use hexium_os::tests::{run_tests, TestCase}; use hexium_os::writer::WRITER; +use core::panic::PanicInfo; use hexium_os::{boot, hlt_loop, init, panic_log, serial_println, exit_qemu, QemuExitCode, Testable}; use hexium_os::{info, print, println}; // RYANS_NOTES: Keeping the imports used in the comments further below // use crate::{info, print, println}; -// RYAN_NOTES: Commented out because failing tests failed to close qemu since the main panic handler is still being called instead of the test panic handler -// #[test_case] -// fn test_fail_example() { -// serial_println!("test_fail_example..."); -// assert_eq!(0, 1); -// serial_println!("ok!"); -// } +#[test_case] +fn test_fail_example() { + assert_eq!(0, 1); +} #[test_case] fn test_example2() { - // serial_println!("test_example2"); assert_eq!(1+1, 2); - // serial_println!("ok!"); } // RYAN_NOTES: Refactor these tests out of here @@ -51,22 +46,6 @@ fn test_println_long() { // } // } -fn test_example() -> Result<(), &'static str>{ - assert_eq!(1+1, 2); - Ok(()) -} - -// pub fn test_main() { -// let tests = [ -// TestCase{ -// name: "test_example", -// function: test_example, -// } -// ]; - -// run_tests(&tests); -// } - #[cfg(test)] #[unsafe(no_mangle)] unsafe extern "C" fn kmain() -> ! { @@ -106,28 +85,17 @@ unsafe extern "C" fn kmain() -> ! { hlt_loop(); } -// #[cfg(test)] -// #[panic_handler] -// pub fn test_panic(info: &core::panic::PanicInfo) -> ! { -// hlt_loop(); -// } - -// #[cfg(not(test))] -// #[panic_handler] -// fn rust_panic(info: &core::panic::PanicInfo) -> ! { -// use hexium_os::utils::registers::*; -// panic_log!("{}\n", info); -// print_register_dump(&get_registers()); -// hlt_loop(); -// } +#[cfg(not(test))] +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + use hexium_os::utils::registers::{print_register_dump, get_registers}; + panic_log!("{}\n", info); + print_register_dump(&get_registers()); + loop {} +} #[cfg(test)] -pub fn test_runner(tests: &[&dyn Testable]) { - serial_println!("Running {} tests", tests.len()); - - for test in tests { - test.run(); - } - - exit_qemu(QemuExitCode::Success); +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + hexium_os::test_panic_handler(info) } \ No newline at end of file diff --git a/kernel/src/testsw/writer.rsw b/kernel/src/testsw/writer.rsw new file mode 100644 index 0000000..b7a4126 --- /dev/null +++ b/kernel/src/testsw/writer.rsw @@ -0,0 +1,19 @@ +#![no_std] +#![no_main] +#![feature(custom_test_frameworks)] +#![test_runner(hexium_os::test_runner)] +#![reexport_test_harness_main="test_main"] + +use core::panic::PanicInfo; + +#[unsafe(no_mangle)] +unsafe extern "C" fn kmain() -> ! { + test_main(); + loop{} +} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + hexium_os::test_panic_handler(info); + loop{} +} \ No newline at end of file From f2aed3697e8c6866a4aac26fba12b6200318a48e Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Wed, 16 Apr 2025 14:38:48 +0300 Subject: [PATCH 15/31] set up integration tests --- kernel/src/lib.rs | 1 - kernel/src/main.rs | 22 +++++++++---------- kernel/src/tests.rs | 25 ---------------------- kernel/src/testsw/writer.rsw | 19 ----------------- kernel/src/writer.rs | 6 +++--- kernel/tests/writer.rs | 41 ++++++++++++++++++++++++++++++++++++ 6 files changed, 55 insertions(+), 59 deletions(-) delete mode 100644 kernel/src/tests.rs delete mode 100644 kernel/src/testsw/writer.rsw create mode 100644 kernel/tests/writer.rs diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index ac17ebc..44457b0 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -24,7 +24,6 @@ pub mod serial; pub mod task; pub mod utils; pub mod writer; -// pub mod tests; pub fn init() { writer::init(); diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 01255fa..98631a7 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -18,22 +18,22 @@ fn test_fail_example() { } #[test_case] -fn test_example2() { +fn test_example() { assert_eq!(1+1, 2); } // RYAN_NOTES: Refactor these tests out of here -#[test_case] -fn test_println_simple() { - println!("Simple print new line statement"); -} +// #[test_case] +// fn test_println_simple() { +// println!("Simple print new line statement"); +// } -#[test_case] -fn test_println_long() { - for _ in 0..200 { - println!("Simple print new line many times"); - } -} +// #[test_case] +// fn test_println_long() { +// for _ in 0..200 { +// println!("Simple print new line many times"); +// } +// } // TODO: RYAN_NOTES: Needs buffer access // #[test_case] diff --git a/kernel/src/tests.rs b/kernel/src/tests.rs deleted file mode 100644 index bea5ea2..0000000 --- a/kernel/src/tests.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::{info}; -pub struct TestCase { - pub name: &'static str, - pub function: fn() -> Result<(), &'static str>, -} - -pub fn run_tests(tests: &[TestCase]) { - info!("Running {} tests...", tests.len()); - - let mut passed = 0; - - for test in tests { - info!("Test {}", test.name); - - match (test.function)() { - Ok(()) => { - info!("Ok"); - passed += 1; - }, - Err(msg) => info!("FAILED: {}", msg), - } - } - - info!("Passed tests {}, Failed tests {}", passed, tests.len() - passed); -} \ No newline at end of file diff --git a/kernel/src/testsw/writer.rsw b/kernel/src/testsw/writer.rsw deleted file mode 100644 index b7a4126..0000000 --- a/kernel/src/testsw/writer.rsw +++ /dev/null @@ -1,19 +0,0 @@ -#![no_std] -#![no_main] -#![feature(custom_test_frameworks)] -#![test_runner(hexium_os::test_runner)] -#![reexport_test_harness_main="test_main"] - -use core::panic::PanicInfo; - -#[unsafe(no_mangle)] -unsafe extern "C" fn kmain() -> ! { - test_main(); - loop{} -} - -#[panic_handler] -fn panic(info: &PanicInfo) -> ! { - hexium_os::test_panic_handler(info); - loop{} -} \ No newline at end of file diff --git a/kernel/src/writer.rs b/kernel/src/writer.rs index 4270e1d..5d10706 100644 --- a/kernel/src/writer.rs +++ b/kernel/src/writer.rs @@ -92,8 +92,8 @@ macro_rules! print { #[macro_export] macro_rules! println { - () => (print!("\n")); - ($($arg:tt)*) => (crate::print!("{}\n", format_args!($($arg)*))); + () => ($crate::print!("\n")); + ($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*))); } #[doc(hidden)] @@ -104,4 +104,4 @@ pub fn _print(args: fmt::Arguments) { interrupts::without_interrupts(|| { WRITER.lock().write_fmt(args).unwrap(); }); -} +} \ No newline at end of file diff --git a/kernel/tests/writer.rs b/kernel/tests/writer.rs new file mode 100644 index 0000000..cc26ca8 --- /dev/null +++ b/kernel/tests/writer.rs @@ -0,0 +1,41 @@ +#![no_std] +#![no_main] +#![feature(custom_test_frameworks)] +#![test_runner(hexium_os::test_runner)] +#![reexport_test_harness_main="test_main"] + +use core::panic::PanicInfo; + +use hexium_os::println; +// use hexium_os::writer::*; + +#[unsafe(no_mangle)] +unsafe extern "C" fn kmain() -> ! { + test_main(); + loop{} +} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + hexium_os::test_panic_handler(info); + loop{} +} + +#[test_case] +fn test_println_simple() { + println!("Simple print new line statement"); +} + +#[test_case] +fn test_println_long() { + for _ in 0..200 { + println!("Simple print new line many times"); + } +} + +#[test_case] +fn test_println_long_more() { + for _ in 0..200 { + println!("Simple print new line many times"); + } +} \ No newline at end of file From e9d0149c377730dd983d718026e8ef24ca29682e Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Thu, 17 Apr 2025 11:52:56 +0300 Subject: [PATCH 16/31] fix infinite re-run of tests --- kernel/tests/writer.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/tests/writer.rs b/kernel/tests/writer.rs index cc26ca8..2dfb32f 100644 --- a/kernel/tests/writer.rs +++ b/kernel/tests/writer.rs @@ -6,11 +6,12 @@ use core::panic::PanicInfo; -use hexium_os::println; +use hexium_os::{println, init}; // use hexium_os::writer::*; #[unsafe(no_mangle)] unsafe extern "C" fn kmain() -> ! { + init(); // RYAN_NOTES: Not sure why it's absence causes an loop running of test_println_long test. test_main(); loop{} } From dc52c18ff0150d1adc3764ec7541dea11e052662 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Thu, 17 Apr 2025 11:53:15 +0300 Subject: [PATCH 17/31] set up better running scripts --- GNUmakefile | 69 +++++++++++++++++++++++++++++----------------- kernel/GNUmakefile | 21 +++++++------- 2 files changed, 55 insertions(+), 35 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 7790d89..3763b0a 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -28,13 +28,30 @@ run-x86_64: ovmf/ovmf-code-$(KARCH).fd ovmf/ovmf-vars-$(KARCH).fd $(IMAGE_NAME). -cdrom $(IMAGE_NAME).iso \ $(QEMUFLAGS) -.PHONY: test-run -test-run: - make test - qemu-system-x86_64 hexium_os-x86_64-test.iso -device isa-debug-exit,iobase=0xf4,iosize=0x04 -serial stdio -display none || [ $$? -eq 33 ] - .PHONY: test -test: $(IMAGE_NAME)-test.iso +test: test-iso + @set -e; \ + FAILED=0; \ + echo "\n\n\n--------RUNNING KERNEL INTEGRATION TESTS-------\n\n"; \ + for iso in hexium_os-tests/*.iso; do \ + echo "==============================="; \ + echo "Running integration test: $$iso"; \ + echo "-------------------------------"; \ + if qemu-system-x86_64 \ + -cdrom "$$iso" \ + -device isa-debug-exit,iobase=0xf4,iosize=0x04 \ + -serial stdio -display none; \ + then \ + echo "✅ Test passed: $$iso"; \ + elif [ $$? -eq 33 ]; then \ + echo "✅ Test passed (exit 33): $$iso"; \ + else \ + echo "❌ Test failed: $$iso"; \ + FAILED=1; \ + fi; \ + echo ""; \ + done; \ + exit $$FAILED ovmf/ovmf-code-$(KARCH).fd: mkdir -p ovmf @@ -81,25 +98,27 @@ $(IMAGE_NAME).iso: limine/limine kernel ramfs ./limine/limine bios-install $(IMAGE_NAME).iso rm -rf iso_root -# TODO: Use different build folders to avoid cross contamination -$(IMAGE_NAME)-test.iso: limine/limine kernel-test ramfs - rm -rf iso_root - mkdir -p iso_root/boot - cp -v kernel/kernel-test iso_root/boot/kernel - cp -v ramfs.img iso_root/boot/ - mkdir -p iso_root/boot/limine - cp -v limine.conf iso_root/boot/limine/ - mkdir -p iso_root/EFI/BOOT - cp -v limine/limine-bios.sys limine/limine-bios-cd.bin limine/limine-uefi-cd.bin iso_root/boot/limine/ - cp -v limine/BOOTX64.EFI iso_root/EFI/BOOT/ - cp -v limine/BOOTIA32.EFI iso_root/EFI/BOOT/ - xorriso -as mkisofs -b boot/limine/limine-bios-cd.bin \ - -no-emul-boot -boot-load-size 4 -boot-info-table \ - --efi-boot boot/limine/limine-uefi-cd.bin \ - -efi-boot-part --efi-boot-image --protective-msdos-label \ - iso_root -o $(IMAGE_NAME)-test.iso - ./limine/limine bios-install $(IMAGE_NAME)-test.iso - rm -rf iso_root +.PHONY: test-iso +test-iso: limine/limine ramfs kernel-test + mkdir -p hexium_os-tests + for testbin in kernel/kernel-test/*; do \ + testname=$$(basename $$testbin); \ + isodir=iso_root_$$testname; \ + mkdir -p $$isodir/boot/limine $$isodir/EFI/BOOT; \ + cp -v $$testbin $$isodir/boot/kernel; \ + cp -v ramfs.img $$isodir/boot/; \ + cp -v limine.conf $$isodir/boot/limine/; \ + cp -v limine/limine-bios.sys limine/limine-bios-cd.bin limine/limine-uefi-cd.bin $$isodir/boot/limine/; \ + cp -v limine/BOOTX64.EFI $$isodir/EFI/BOOT/; \ + cp -v limine/BOOTIA32.EFI $$isodir/EFI/BOOT/; \ + xorriso -as mkisofs -b boot/limine/limine-bios-cd.bin \ + -no-emul-boot -boot-load-size 4 -boot-info-table \ + --efi-boot boot/limine/limine-uefi-cd.bin \ + -efi-boot-part --efi-boot-image --protective-msdos-label \ + $$isodir -o hexium_os-tests/hexium_os-$$testname.iso; \ + ./limine/limine bios-install hexium_os-tests/hexium_os-$$testname.iso; \ + rm -rf $$isodir; \ + done .PHONY: clean clean: diff --git a/kernel/GNUmakefile b/kernel/GNUmakefile index ed0935b..cfa1b07 100644 --- a/kernel/GNUmakefile +++ b/kernel/GNUmakefile @@ -30,16 +30,17 @@ all: test: RUSTFLAGS="-C relocation-model=static" cargo build --tests --target $(RUST_TARGET) --profile $(RUST_PROFILE) - find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2- - - shell find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2- - echo $(find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2-) - echo '$(find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2-)' - echo "$(find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2-)" - echo $(shell find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2-) - echo '$(shell find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2-)' - echo "$(shell find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2-)" - cp "$(shell find . -type f -name 'hexium_os-*' ! -name '*.*' -printf '%T@ %p\n' | sort -nr | head -n1 | cut -d' ' -f2-)" kernel-test + + mkdir -p kernel-test + + # Collect all hexium_os-* and writer-* executables + TEST_BIN_DIR=target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR)/deps + + # Copy first two hexium_os-* test binaries + find target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR)/deps -maxdepth 1 -type f -executable -name 'hexium_os-*' | head -n 2 | xargs -I{} cp {} kernel-test/ + + # Copy all writer-* test binaries + find target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR)/deps -maxdepth 1 -type f -executable -name 'writer-*' -exec cp {} kernel-test/ \; .PHONY: clean clean: From 4da903461a98ee7a11cf34fedd0c5535797b67dd Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Thu, 17 Apr 2025 12:03:46 +0300 Subject: [PATCH 18/31] refactor writer tests --- kernel/src/main.rs | 24 ------------------------ kernel/tests/writer.rs | 13 ++++++++++++- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 98631a7..4c250e5 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -22,30 +22,6 @@ fn test_example() { assert_eq!(1+1, 2); } -// RYAN_NOTES: Refactor these tests out of here -// #[test_case] -// fn test_println_simple() { -// println!("Simple print new line statement"); -// } - -// #[test_case] -// fn test_println_long() { -// for _ in 0..200 { -// println!("Simple print new line many times"); -// } -// } - -// TODO: RYAN_NOTES: Needs buffer access -// #[test_case] -// fn test_println_output() { -// let s = "Some test fitting single line"; -// println!("{}", s); -// for (i, c) in s.chars().enumerate() { -// let screen_char = WRITER.lock().write_char(c).buffer.chars[BUFFER_HEIGHT - 2][i].read(); -// assert_eq!(char::from(screen_char.ascii_character), c); -// } -// } - #[cfg(test)] #[unsafe(no_mangle)] unsafe extern "C" fn kmain() -> ! { diff --git a/kernel/tests/writer.rs b/kernel/tests/writer.rs index 2dfb32f..4692f95 100644 --- a/kernel/tests/writer.rs +++ b/kernel/tests/writer.rs @@ -39,4 +39,15 @@ fn test_println_long_more() { for _ in 0..200 { println!("Simple print new line many times"); } -} \ No newline at end of file +} + +// TODO: RYAN_NOTES: Needs buffer access +// #[test_case] +// fn test_println_output() { +// let s = "Some test fitting single line"; +// println!("{}", s); +// for (i, c) in s.chars().enumerate() { +// let screen_char = WRITER.lock().write_char(c).buffer.chars[BUFFER_HEIGHT - 2][i].read(); +// assert_eq!(char::from(screen_char.ascii_character), c); +// } +// } \ No newline at end of file From 498eea58756885f8f3f01a250c660112625635c6 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Thu, 17 Apr 2025 12:22:54 +0300 Subject: [PATCH 19/31] update make test to pick any other integration test execs --- kernel/GNUmakefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/GNUmakefile b/kernel/GNUmakefile index cfa1b07..7a16426 100644 --- a/kernel/GNUmakefile +++ b/kernel/GNUmakefile @@ -39,8 +39,8 @@ test: # Copy first two hexium_os-* test binaries find target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR)/deps -maxdepth 1 -type f -executable -name 'hexium_os-*' | head -n 2 | xargs -I{} cp {} kernel-test/ - # Copy all writer-* test binaries - find target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR)/deps -maxdepth 1 -type f -executable -name 'writer-*' -exec cp {} kernel-test/ \; + # Copy all test binaries except hexium_os-* + find target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR)/deps -maxdepth 1 -type f -executable ! -name 'hexium_os-*' -exec cp {} kernel-test/ \; .PHONY: clean clean: From 58dc745e1fbb61a09434e2d66b6b98259bb46b26 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Thu, 17 Apr 2025 12:23:16 +0300 Subject: [PATCH 20/31] add should panic tests --- kernel/tests/should_panic.rs | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 kernel/tests/should_panic.rs diff --git a/kernel/tests/should_panic.rs b/kernel/tests/should_panic.rs new file mode 100644 index 0000000..b4db599 --- /dev/null +++ b/kernel/tests/should_panic.rs @@ -0,0 +1,40 @@ +#![no_std] +#![no_main] +#![feature(custom_test_frameworks)] +#![test_runner(test_runner)] +#![reexport_test_harness_main="test_main"] + +use core::panic::PanicInfo; + +use hexium_os::{exit_qemu, init, serial_print, serial_println}; + +#[unsafe(no_mangle)] +unsafe extern "C" fn kmain() -> ! { + init(); + test_main(); + loop{} +} + +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + serial_println!("[ok]"); + exit_qemu(hexium_os::QemuExitCode::Success); + loop {} +} + +pub fn test_runner(tests: &[&dyn Fn()]) { + serial_println!("Running {} tests", tests.len()); + + for test in tests { + test(); + serial_print!("[test did not panic]"); + exit_qemu(hexium_os::QemuExitCode::Failed); + } + exit_qemu(hexium_os::QemuExitCode::Success); +} + +#[test_case] +fn should_fail() { + serial_println!("should_panic::should_fail...\t"); + assert_eq!(0,1); +} \ No newline at end of file From 0248de8875d2533f27085c288682612268a914f2 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Thu, 17 Apr 2025 12:29:50 +0300 Subject: [PATCH 21/31] disable test harness --- kernel/Cargo.toml | 4 ++++ kernel/tests/should_panic.rs | 19 +++---------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 71292d4..7843d08 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -18,3 +18,7 @@ pc-keyboard = "0.7.0" x86 = "0.52.0" x86_64 = "0.14.2" uart_16550 = "0.3.2" + +[[test]] +name="should_panic" +harness=false \ No newline at end of file diff --git a/kernel/tests/should_panic.rs b/kernel/tests/should_panic.rs index b4db599..ddc18c6 100644 --- a/kernel/tests/should_panic.rs +++ b/kernel/tests/should_panic.rs @@ -1,8 +1,5 @@ #![no_std] #![no_main] -#![feature(custom_test_frameworks)] -#![test_runner(test_runner)] -#![reexport_test_harness_main="test_main"] use core::panic::PanicInfo; @@ -11,7 +8,9 @@ use hexium_os::{exit_qemu, init, serial_print, serial_println}; #[unsafe(no_mangle)] unsafe extern "C" fn kmain() -> ! { init(); - test_main(); + should_fail(); + serial_print!("[test did not panic]"); + exit_qemu(hexium_os::QemuExitCode::Failed); loop{} } @@ -22,18 +21,6 @@ fn panic(_info: &PanicInfo) -> ! { loop {} } -pub fn test_runner(tests: &[&dyn Fn()]) { - serial_println!("Running {} tests", tests.len()); - - for test in tests { - test(); - serial_print!("[test did not panic]"); - exit_qemu(hexium_os::QemuExitCode::Failed); - } - exit_qemu(hexium_os::QemuExitCode::Success); -} - -#[test_case] fn should_fail() { serial_println!("should_panic::should_fail...\t"); assert_eq!(0,1); From 0b689c83cdb5789b369ac8d1abb107249407053f Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Thu, 17 Apr 2025 12:33:21 +0300 Subject: [PATCH 22/31] make clean test isos --- GNUmakefile | 1 + 1 file changed, 1 insertion(+) diff --git a/GNUmakefile b/GNUmakefile index 3763b0a..935a032 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -124,6 +124,7 @@ test-iso: limine/limine ramfs kernel-test clean: $(MAKE) -C kernel clean rm -rf iso_root *.iso + rm -rf hexium_os-tests .PHONY: distclean distclean: clean From 2215eb824cd163a81078c9fc4ebf99079169e058 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Thu, 17 Apr 2025 12:39:39 +0300 Subject: [PATCH 23/31] ignore test isos dir --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5a8ec5d..44d005f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ *.iso *.img *.hdd +/hexium_os-tests From a186a38972f954da3684a2d31421dcb10ffc8613 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Thu, 17 Apr 2025 13:05:12 +0300 Subject: [PATCH 24/31] basic clean up --- kernel/GNUmakefile | 7 ++----- kernel/src/lib.rs | 1 - kernel/src/main.rs | 27 +++++++++------------------ 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/kernel/GNUmakefile b/kernel/GNUmakefile index 7a16426..d4ac01c 100644 --- a/kernel/GNUmakefile +++ b/kernel/GNUmakefile @@ -33,13 +33,10 @@ test: mkdir -p kernel-test - # Collect all hexium_os-* and writer-* executables - TEST_BIN_DIR=target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR)/deps - - # Copy first two hexium_os-* test binaries + # Copy first two hexium_os-* test binaries - the third appears to be a normal build exec. find target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR)/deps -maxdepth 1 -type f -executable -name 'hexium_os-*' | head -n 2 | xargs -I{} cp {} kernel-test/ - # Copy all test binaries except hexium_os-* + # Copy all remain integration test binaries except hexium_os-* find target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR)/deps -maxdepth 1 -type f -executable ! -name 'hexium_os-*' -exec cp {} kernel-test/ \; .PHONY: clean diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 44457b0..82296ca 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -1,6 +1,5 @@ #![no_std] #![no_main] -// #![cfg_attr(test, no_main)] #![feature(abi_x86_interrupt)] #![feature(custom_test_frameworks)] #![test_runner(crate::test_runner)] diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 4c250e5..0a3dac3 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -9,8 +9,7 @@ use core::fmt::Write; use hexium_os::writer::WRITER; use core::panic::PanicInfo; use hexium_os::{boot, hlt_loop, init, panic_log, serial_println, exit_qemu, QemuExitCode, Testable}; -use hexium_os::{info, print, println}; // RYANS_NOTES: Keeping the imports used in the comments further below -// use crate::{info, print, println}; +use hexium_os::{info, print, println}; #[test_case] fn test_fail_example() { @@ -39,24 +38,16 @@ unsafe extern "C" fn kmain() -> ! { unsafe extern "C" fn kmain() -> ! { assert!(boot::BASE_REVISION.is_supported()); - init(); - - info!("Info in main"); - - panic_log!("Panic log"); - - print!("Test2\n"); - - - #[cfg(test)] - test_main(); - - // RYANS_NOTES: The lines below do not seem to have an effect after the init method above however calling them above the init method causes a bootloop. + /* + RYANS_NOTES: The lines below do not seem to have an effect after the init method above + however calling them above the init method causes a boot-loop. + NOTE: Calling them after the init method after the executor code has been commented back in, + will cause them not to be run as the executor code seems to block the 'thread'. + */ // print!("Test"); // println!("Test2"); - // info!("Test3"); - panic!("Some message"); - // info!("Test4"); + + init(); hlt_loop(); } From 2df1696bcc5c6f830e8cd2f14220036115dff3e7 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Thu, 17 Apr 2025 13:07:44 +0300 Subject: [PATCH 25/31] fix name for context --- GNUmakefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 935a032..44237f8 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -42,11 +42,11 @@ test: test-iso -device isa-debug-exit,iobase=0xf4,iosize=0x04 \ -serial stdio -display none; \ then \ - echo "✅ Test passed: $$iso"; \ + echo "✅ Integration Test passed: $$iso"; \ elif [ $$? -eq 33 ]; then \ - echo "✅ Test passed (exit 33): $$iso"; \ + echo "✅ Integration Test passed (exit 33): $$iso"; \ else \ - echo "❌ Test failed: $$iso"; \ + echo "❌ Integration Test failed: $$iso"; \ FAILED=1; \ fi; \ echo ""; \ From 11cbb9401027b7e765358883b6db9994579f5635 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Fri, 18 Apr 2025 15:46:23 +0300 Subject: [PATCH 26/31] clean up --- kernel/src/lib.rs | 10 ++-------- kernel/src/main.rs | 14 +++----------- kernel/tests/writer.rs | 5 ++--- 3 files changed, 7 insertions(+), 22 deletions(-) diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 82296ca..61febd5 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -31,17 +31,14 @@ pub fn init() { let mut vfs = fs::vfs::VFS::new(None); fs::ramfs::init(&mut vfs); - - info!("Before"); + print_startup_message(&mut vfs); - info!("After"); - // RYAN_NOTES: Commented out for now as the code doesn't run past this section. Will return it back. + // Issue#30: Commented out for now as the code doesn't run past this section. Will return it back. // let mut executor = crate::task::executor::Executor::new(); // let _ = executor.spawn(crate::task::Task::new(devices::keyboard::trace_keypresses())); // executor.run(); - info!("After2"); //vfs.unmount_fs(); } @@ -60,8 +57,6 @@ fn print_startup_message(vfs: &mut fs::vfs::VFS) -> [u8; 128] { } } - info!("Testing"); - info!( "Hexium OS kernel v{} succesfully initialized at {}", env!("CARGO_PKG_VERSION"), @@ -86,7 +81,6 @@ pub fn hlt_loop() -> ! { } pub fn test_panic_handler(info: &PanicInfo) -> ! { - println!("Test panic handler"); serial_println!("[failed]"); serial_println!("Error: {}", info); exit_qemu(QemuExitCode::Failed); diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 0a3dac3..b669b8b 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -11,11 +11,6 @@ use core::panic::PanicInfo; use hexium_os::{boot, hlt_loop, init, panic_log, serial_println, exit_qemu, QemuExitCode, Testable}; use hexium_os::{info, print, println}; -#[test_case] -fn test_fail_example() { - assert_eq!(0, 1); -} - #[test_case] fn test_example() { assert_eq!(1+1, 2); @@ -24,12 +19,9 @@ fn test_example() { #[cfg(test)] #[unsafe(no_mangle)] unsafe extern "C" fn kmain() -> ! { - // info!("Test Main"); assert!(boot::BASE_REVISION.is_supported()); init(); - info!("Test Main:1"); test_main(); - info!("Test Main:2"); loop {} } @@ -39,13 +31,13 @@ unsafe extern "C" fn kmain() -> ! { assert!(boot::BASE_REVISION.is_supported()); /* - RYANS_NOTES: The lines below do not seem to have an effect after the init method above + Issue#30: The lines at the end of this comment below do not seem to have an effect after the init method above however calling them above the init method causes a boot-loop. NOTE: Calling them after the init method after the executor code has been commented back in, will cause them not to be run as the executor code seems to block the 'thread'. + print!("Test"); + println!("Test2"); */ - // print!("Test"); - // println!("Test2"); init(); diff --git a/kernel/tests/writer.rs b/kernel/tests/writer.rs index 4692f95..222e152 100644 --- a/kernel/tests/writer.rs +++ b/kernel/tests/writer.rs @@ -7,11 +7,10 @@ use core::panic::PanicInfo; use hexium_os::{println, init}; -// use hexium_os::writer::*; #[unsafe(no_mangle)] unsafe extern "C" fn kmain() -> ! { - init(); // RYAN_NOTES: Not sure why it's absence causes an loop running of test_println_long test. + init(); // Issue#30: Not sure why it's absence causes an loop running of test_println_long test. test_main(); loop{} } @@ -41,7 +40,7 @@ fn test_println_long_more() { } } -// TODO: RYAN_NOTES: Needs buffer access +// TODO: Issue#31: Needs buffer access // #[test_case] // fn test_println_output() { // let s = "Some test fitting single line"; From 69be116008a72eed0141445efa022c5d27a326ca Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Fri, 18 Apr 2025 15:59:05 +0300 Subject: [PATCH 27/31] fix some lint issues --- kernel/src/lib.rs | 5 ++--- kernel/src/main.rs | 6 +----- kernel/src/memory/mod.rs | 2 +- kernel/src/writer.rs | 1 - 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 61febd5..f1497dc 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -9,7 +9,6 @@ extern crate alloc; use alloc::string::String; use core::{arch::asm, panic::PanicInfo}; -use utils::registers::{get_registers, print_register_dump}; pub mod boot; pub mod devices; @@ -115,13 +114,13 @@ pub fn exit_qemu(exit_code: QemuExitCode) { } pub trait Testable { - fn run(&self) -> (); + fn run(&self); } impl Testable for T where T : Fn(), { - fn run(&self) -> () { + fn run(&self) { serial_print!("{}...\t", core::any::type_name::()); self(); serial_println!("[ok]"); diff --git a/kernel/src/main.rs b/kernel/src/main.rs index b669b8b..b42e72d 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -4,12 +4,8 @@ #![test_runner(hexium_os::test_runner)] #![reexport_test_harness_main = "test_main"] -use core::fmt::Write; - -use hexium_os::writer::WRITER; use core::panic::PanicInfo; -use hexium_os::{boot, hlt_loop, init, panic_log, serial_println, exit_qemu, QemuExitCode, Testable}; -use hexium_os::{info, print, println}; +use hexium_os::{boot, hlt_loop, init, panic_log}; #[test_case] fn test_example() { diff --git a/kernel/src/memory/mod.rs b/kernel/src/memory/mod.rs index d429d1e..66e53b2 100644 --- a/kernel/src/memory/mod.rs +++ b/kernel/src/memory/mod.rs @@ -10,7 +10,7 @@ pub mod paging; static PHYS_MEM_OFFSET: Once = Once::new(); static mut MEM_MAPPER: Option> = None; -pub fn init() -> () { +pub fn init() { if let Some(hhdm_response) = boot::HHDM_REQUEST.get_response() { PHYS_MEM_OFFSET.call_once(|| VirtAddr::new(hhdm_response.offset())); } diff --git a/kernel/src/writer.rs b/kernel/src/writer.rs index 5d10706..8fbd1a6 100644 --- a/kernel/src/writer.rs +++ b/kernel/src/writer.rs @@ -1,4 +1,3 @@ -use crate::serial_print; use crate::{utils::types::option_to_c_void, boot}; use core::fmt; use core::ptr; From 5b4b72a658ef97fc912a1385bbc0045fe82894b4 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Fri, 18 Apr 2025 16:02:51 +0300 Subject: [PATCH 28/31] add testing to pipeline --- .github/workflows/makefile.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index 23142a6..ec13989 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -28,5 +28,5 @@ jobs: - name: Verify xorriso installation run: xorriso -version - - name: Run build - run: make + - name: Run build & test + run: make test From c12c43b91ba50a4506f7ed185eb15420ff39129d Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Fri, 18 Apr 2025 16:05:59 +0300 Subject: [PATCH 29/31] install qemu to run tests --- .github/workflows/makefile.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index ec13989..d383a87 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -28,5 +28,8 @@ jobs: - name: Verify xorriso installation run: xorriso -version + - name: Install qemu + run: sudo apt-get install qemu-system + - name: Run build & test run: make test From bd71c44a9e435ed37827c7ee03ce7170f692c8c9 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Fri, 18 Apr 2025 16:11:42 +0300 Subject: [PATCH 30/31] remove test from pipeline --- .github/workflows/makefile.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index d383a87..660dd30 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -31,5 +31,5 @@ jobs: - name: Install qemu run: sudo apt-get install qemu-system - - name: Run build & test - run: make test + - name: Run build + run: make From 75a89eb5c3bf0d3541528c1c56bae573dcff21f0 Mon Sep 17 00:00:00 2001 From: RyanKoech Date: Fri, 18 Apr 2025 16:57:46 +0300 Subject: [PATCH 31/31] add precision in selecting correct testing binaries, reintroduce testing to pipeline --- .github/workflows/makefile.yml | 4 ++-- kernel/.gitignore | 3 ++- kernel/GNUmakefile | 20 ++++++++++++-------- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index 660dd30..d383a87 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -31,5 +31,5 @@ jobs: - name: Install qemu run: sudo apt-get install qemu-system - - name: Run build - run: make + - name: Run build & test + run: make test diff --git a/kernel/.gitignore b/kernel/.gitignore index 9feff12..31130f9 100644 --- a/kernel/.gitignore +++ b/kernel/.gitignore @@ -1,3 +1,4 @@ /kernel /target -/kernel-test \ No newline at end of file +/kernel-test +.test-log.txt \ No newline at end of file diff --git a/kernel/GNUmakefile b/kernel/GNUmakefile index d4ac01c..12af846 100644 --- a/kernel/GNUmakefile +++ b/kernel/GNUmakefile @@ -29,15 +29,19 @@ all: cp target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR)/hexium_os kernel test: - RUSTFLAGS="-C relocation-model=static" cargo build --tests --target $(RUST_TARGET) --profile $(RUST_PROFILE) - mkdir -p kernel-test - - # Copy first two hexium_os-* test binaries - the third appears to be a normal build exec. - find target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR)/deps -maxdepth 1 -type f -executable -name 'hexium_os-*' | head -n 2 | xargs -I{} cp {} kernel-test/ - - # Copy all remain integration test binaries except hexium_os-* - find target/$(RUST_TARGET)/$(RUST_PROFILE_SUBDIR)/deps -maxdepth 1 -type f -executable ! -name 'hexium_os-*' -exec cp {} kernel-test/ \; + RUSTFLAGS="-C relocation-model=static" cargo test --no-run --target $(RUST_TARGET) --profile $(RUST_PROFILE) --color always \ + 2>&1 | tee .test-log.txt + @grep -o 'target/[^ )]*' .test-log.txt | while read -r path; do \ + if [ -x "$$path" ]; then \ + echo "Copying $$path to kernel-test/"; \ + cp "$$path" kernel-test/; \ + else \ + echo "Skipping non-executable: $$path"; \ + fi \ + done + + @rm .test-log.txt .PHONY: clean clean: