#[cfg(not(feature = "limine"))]
#[macro_export]
macro_rules! klib {
($test_group:literal) => {
$crate::klib!($test_group, klib_config = &ktest::KlibConfig::new_default(), boot_config = &bootloader_api::BootloaderConfig::new_default());
};
($test_group:literal, klib_config = &$klib_config:expr) => {
$crate::klib!($test_group, klib_config = &$klib_config, boot_config = &bootloader_api::BootloaderConfig::new_default());
};
($test_group:literal, boot_config = &$boot_config:expr) => {
$crate::klib!($test_group, klib_config = &ktest::KlibConfig::new_default(), boot_config = &$boot_config);
};
($test_group:literal, klib_config = &$klib_config:expr, boot_config = &$boot_config:expr) => {
#[cfg(test)] const _: () = {
static ___BOOTLOADER_CONFIG: bootloader_api::BootloaderConfig = $boot_config;
static ___KLIB_CONFIG: ktest::KlibConfig = $klib_config;
#[panic_handler]
fn ___panic(info: &core::panic::PanicInfo) -> ! {
ktest::panic(info)
}
fn ___kernel_test_main(boot_info: &'static mut bootloader_api::BootInfo) -> ! {
ktest::init_harness($test_group);
ktest::memory::heap::init_allocator_if_enabled(boot_info)
.expect("Heap allocator initialization failed");
if let Some(before_tests) = ___KLIB_CONFIG.before_tests {
before_tests(boot_info);
}
test_main();
if let Some(after_tests) = ___KLIB_CONFIG.after_tests {
after_tests();
}
loop {
unsafe { core::arch::asm!("hlt", options(nomem, nostack, preserves_flags)); }
}
}
bootloader_api::entry_point!(___kernel_test_main, config = &___BOOTLOADER_CONFIG);
};
};
}
#[cfg(feature = "limine")]
#[macro_export]
macro_rules! klib {
($test_group:literal) => {
$crate::klib!($test_group, klib_config = &ktest::KlibConfig::new_default());
};
($test_group:literal, klib_config = &$klib_config:expr) => {
#[cfg(test)] const _: () = {
#[used]
#[unsafe(link_section = ".requests_start_marker")]
static ___START_MARKER: limine::request::RequestsStartMarker = limine::request::RequestsStartMarker::new();
#[used]
#[unsafe(link_section = ".requests_end_marker")]
static ___END_MARKER: limine::request::RequestsEndMarker = limine::request::RequestsEndMarker::new();
static ___KLIB_CONFIG: ktest::KlibConfig = $klib_config;
#[panic_handler]
fn ___panic(info: &core::panic::PanicInfo) -> ! {
ktest::panic(info)
}
#[unsafe(no_mangle)]
pub extern "C" fn _start() -> ! {
ktest::init_harness($test_group);
if let Some(before_tests) = ___KLIB_CONFIG.before_tests {
before_tests();
}
test_main();
if let Some(after_tests) = ___KLIB_CONFIG.after_tests {
after_tests();
}
loop {
unsafe { core::arch::asm!("hlt", options(nomem, nostack, preserves_flags)); }
}
}
};
};
}
pub struct KlibConfig {
#[cfg(not(feature = "limine"))]
pub before_tests: Option<fn(&'static bootloader_api::BootInfo)>,
#[cfg(feature = "limine")]
pub before_tests: Option<fn()>,
pub after_tests: Option<fn()>
}
impl KlibConfig {
pub const fn new_default() -> Self {
KlibConfig {
before_tests: None,
after_tests: None
}
}
}
pub struct KlibConfigBuilder {
#[cfg(not(feature = "limine"))]
pub before_tests: Option<fn(&'static bootloader_api::BootInfo)>,
#[cfg(feature = "limine")]
pub before_tests: Option<fn()>,
pub after_tests: Option<fn()>
}
impl KlibConfigBuilder {
pub const fn new_default() -> Self {
KlibConfigBuilder {
before_tests: None,
after_tests: None
}
}
#[cfg(not(feature = "limine"))]
pub const fn new(before_tests: Option<fn(&'static bootloader_api::BootInfo)>, after_tests: Option<fn()>) -> Self {
KlibConfigBuilder {
before_tests,
after_tests
}
}
#[cfg(feature = "limine")]
pub const fn new(before_tests: Option<fn()>, after_tests: Option<fn()>) -> Self {
KlibConfigBuilder {
before_tests,
after_tests
}
}
pub const fn build(self) -> KlibConfig {
KlibConfig {
before_tests: self.before_tests,
after_tests: self.after_tests
}
}
#[cfg(not(feature = "limine"))]
pub const fn before_tests(mut self, before_tests: fn(&'static bootloader_api::BootInfo)) -> Self {
self.before_tests = Some(before_tests);
self
}
#[cfg(feature = "limine")]
pub const fn before_tests(mut self, before_tests: fn()) -> Self {
self.before_tests = Some(before_tests);
self
}
pub const fn after_tests(mut self, after_tests: fn()) -> Self {
self.after_tests = Some(after_tests);
self
}
}