How is the rust test harness generated? Why is reexport_test_harness_main failing to export the harness main symbol?

I would like to use the generated test harness in the context of a custom test framework for a kernel. I'm using #![reexport_test_harness_main = test_main] to reexport the test harness main function under a different symbol, however when calling the function I get:

error[E0425]: cannot find function `test_main` in this scope
  --> tests/basic_math.rs:46:3
   |
46 |         test_main();
   |         ^^^^^^^^^ not found in this scope

I've made my integration test as similar as possible to the integration test in phill opp's blog post about testing with custom test frameworks: https://github.com/phil-opp/blog_os/tree/post-04. Running his tests works for me, so I know that reexport_test_harness_main isn't directly broken.

Are there any implicit requirements that might prevent the test harness from being generated? How can I get some more information on what might be the root cause behind the missing test_main symbol?

This is my integration test:

//tests/basic_math.rs
#![feature(test)]
#![no_std]
#![no_main]
#![test_runner(test_runner)]
#![feature(custom_test_frameworks)]
#![reexport_test_harness_main = "test_main"]

use hermit::{print, println};
pub trait Testable {
	fn run(&self) -> ();
}

impl<T> Testable for T
where
	T: Fn(),
{
	fn run(&self) {
		print!("{}...\t", core::any::type_name::<T>());
		self();
		println!("[ok]");
	}
}

pub fn test_runner(tests: &[&dyn Testable]) {
	println!("Running {} tests", tests.len());
	for test in tests {
		test.run();
	}
}

#[test_case]
fn add_one() {
	let x = 1 + 2;
	assert_eq!(x, 3);
}

// After initializing the kernel calls this function
#[no_mangle]
extern "C" fn runtime_entry(_argc: i32, _argv: *const *const u8, _env: *const *const u8) -> ! {
	//Toggling this changes the error from compile time to link time
	// extern "Rust" {
	// 	fn test_main();
	// }
	unsafe {
		test_main();
	}
	hermit::sys_exit(0)
}

The integration test itself runs fine if I remove the #[test_case] and test_main()and manually call my tests, but ideally I'd like to use the rust test harness.
Any ideas for how I can get closer to the root issue are appreciated.

If you can, could you share your repository? I think the best way I could help would be to mess with the code after reproducing the error. I tried to reproduce it from just the test file, but it compiled fine (although it did run into issues when running, I expect that's a different thing than what you're running into).

Yes, of course I can share the code. I initially didn't share, because sharing the whole repository is pretty far from a minimal example.
The integration test in question is under tests/basic_math in this branch.

The test is compiled and run with cargo test --test basic_math -Z build-std=core,alloc --target x86_64-unknown-hermit-kernel.

Note: .cargo/config sets a custom runner that invokes the tests (via tests/hermit_test_runner.py), which is also very much a work in progress, and relies on a custom hypervisor (available via cargo install uhyve (requires kvm)). Using qemu is also possible, but requires a couple of extra dependencies. However this is probably not so relevant for my issue regarding the compilation error.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.