use core::mem::MaybeUninit;
use crate::test::outcome::Termination;
pub mod output;
pub mod runner;
pub mod outcome;
#[doc(hidden)]
pub struct Test<T> {
pub name: &'static str,
pub modules: &'static str,
pub test: fn() -> T,
pub ignore: Ignore,
pub should_panic: ShouldPanic,
}
pub trait TestCase {
fn qualified_name(&self) -> &'static str;
fn name(&self) -> &'static str {
let full_name = self.qualified_name();
if let Some(pos) = full_name.rfind("::") {
&full_name[pos + 2..]
} else {
full_name
}
}
fn modules(&self) -> Option<&'static str> {
let full_name = self.qualified_name();
if let Some(pos) = full_name.rfind("::") {
Some(&full_name[..pos])
} else {
None
}
}
fn run(&self) -> ();
fn ignore(&self) -> Ignore;
fn should_panic(&self) -> ShouldPanic;
}
impl<T> TestCase for Test<T>
where
T: Termination,
{
fn run(&self) {
(self.test)().terminate();
}
fn qualified_name(&self) -> &'static str {
self.name
}
fn name(&self) -> &'static str {
self.name
}
fn modules(&self) -> Option<&'static str> {
Some(self.modules)
}
fn ignore(&self) -> Ignore {
self.ignore
}
fn should_panic(&self) -> ShouldPanic {
self.should_panic
}
}
#[derive(Clone, Copy, Debug)]
pub enum Ignore {
No,
Yes
}
#[derive(Clone, Copy, Debug)]
pub enum ShouldPanic {
No,
Yes
}
#[doc(hidden)]
pub const fn split_module_path_len(module_path: &'static str) -> usize {
let mut len = 1;
let mut i = 1;
while i < module_path.len() {
if module_path.as_bytes()[i - 1] == b':' && module_path.as_bytes()[i] == b':' {
len += 1;
i += 1;
}
i += 1;
}
len
}
#[doc(hidden)]
pub const fn split_module_path<const LEN: usize>(module_path: &'static str) -> [&'static str; LEN] {
let mut result: MaybeUninit<[&'static str; LEN]> = MaybeUninit::uninit();
let mut result_index = 0;
let mut module_path_start = 0;
let mut module_path_index = 1;
while module_path_index < module_path.len() {
if module_path.as_bytes()[module_path_index - 1] == b':'
&& module_path.as_bytes()[module_path_index] == b':'
{
let module = unsafe {
str::from_utf8_unchecked(core::slice::from_raw_parts(
module_path.as_ptr().add(module_path_start),
module_path_index - 1 - module_path_start,
))
};
if result_index >= LEN {
panic!("module path was split into too many parts")
}
unsafe {
(result.as_mut_ptr() as *mut &str)
.add(result_index)
.write(module);
}
result_index += 1;
module_path_index += 1;
module_path_start = module_path_index;
}
module_path_index += 1;
}
let module = unsafe {
str::from_utf8_unchecked(core::slice::from_raw_parts(
module_path.as_ptr().add(module_path_start),
module_path.len() - module_path_start,
))
};
if result_index >= LEN {
panic!("module path was split into too many parts")
}
unsafe {
(result.as_mut_ptr() as *mut &str)
.add(result_index)
.write(module);
}
result_index += 1;
if result_index < LEN {
panic!("unable to split module path into enough separate parts")
}
unsafe { result.assume_init() }
}