Repository navigation
Testing #1009
Replies: 173 comments 84 replies
|
I'm not sure if I did something wrong, but by following along with this guide exactly I was receiving an error about fmt being undeclared after setting up the CompareMessage implementation. I fixed it by adding |
|
@leggettc18 You did nothing wrong, I forgot to mention these imports. Fixed in 1f97103. Thanks for reporting! |
|
I'm unable to run
|
|
Try I have the same problem but couldn't figure out why the file isn't automatically found. |
|
@AntoineSebert Do you have a @Beidah Sounds like forgot a |
|
@phil-opp Yes it's there. The problem seems to have disappread today, and anyway it's not a big deal. |
|
The recent improvements in the test framework now produce text outputs that are not colored in green, thus making the test result less visible within the terminal. |
|
Yes, there is! You can use ANSI escape codes for coloring. For example, you can create a type to print something in green: use core::fmt;
struct Green(&'static str);
impl fmt::Display for Green {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "\x1B[32m")?; // prefix code
write!(f, "{}", self.0)?;
write!(f, "\x1B[0m")?; // postfix code
Ok(())
}
}Now you can do I opened #603 for adding this to the post. |
|
In the process of adding tests, I encountered some strange errors. In this test, I simply created a writer, but failed, and judging from the error message, it seems that it did not execute any tests at all, because I did not see the information printed by test_runner or panic_handler on the console. lws@lsw:/document/project/flandre-os/FlandreOS$ cargo xtest test_default_writer
Compiling flandre_os v0.0.1 (/document/project/flandre-os/FlandreOS)
Finished dev [unoptimized + debuginfo] target(s) in 0.33s
Running target/x86_64-flandre_os/debug/deps/flandre_os-d120248f92b70111
Building bootloader
Compiling bootloader v0.6.0 (/work/tool/rust/cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/bootloader-0.6.0)
Finished release [optimized + debuginfo] target(s) in 0.72s
Running: `qemu-system-x86_64 -drive format=raw,file=/document/project/flandre-os/FlandreOS/target/x86_64-flandre_os/debug/deps/bootimage-flandre_os-d120248f92b70111.bin -device isa-debug-exit,iobase=0xf4,iosize=0x04 -serial stdio -display none test_default_writer`
qemu-system-x86_64: -display none: drive with bus=0, unit=0 (index=0) exists
error: test failed, to rerun pass '--lib'
|
|
I did all kinds of printing tests and the printing function seemed to work normally, but when I tried to add some tests to ensure that these functions would not be damaged in future modifications, I got the above errors. |
|
I think passing a test name to |
Yes, as you see from the "Running: What you can do is to run the tests of the library component through |
I tried adding the "x" as you indicated in the above paragraph. The test did not fail. WIth some more fooling about i see that the I have submitted a pull request #610 |
|
Hi, thank you for taking your time and effort into making this brilliant blog! I've learnt so much about operating systems and the Rust language in general! Can't wait to see how this blog unfolds and what new things you'll bring. I just wanted to ask if it is the expected behaviour for It seems to me that perhaps this was the desired behaviour? If so, is there a way for me to send data to the serial port while the QEMU instance is running as normal? |
|
cargo test gives this: (signal: 11, SIGSEGV: invalid memory reference) |
|
If anyone else is experience the same issue that I was with Insert into your Make sure you're using the latest nightly compiler. |
|
both lib.rs and basic_boot.rs contain a entry point function "_start", but cargo test still compile. Why is that? |
|
I think there's a minor error, in the panic function it said shouldn't return, but there's no semi-column at the end of the function call. I've tried to copy paste the code into my editor and the lsp tells me to add a semi-column. // in tests/basic_boot.rs
#![test_runner(blog_os::test_runner)]
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
blog_os::test_panic_handler(info)
} |
|
I am receiving a compilation error whenever I attempt to include the error[E0053]: method `steps_between` has an incompatible type for trait
--> /Users/danielmorozoff/.cargo/registry/src/index.crates.io-6f17d22bba15001f/x86_64-0.14.12/src/addr.rs:382:51
|
382 | fn steps_between(start: &Self, end: &Self) -> Option<usize> {
| ^^^^^^^^^^^^^ expected `(usize, Option<usize>)`, found `Option<usize>`
|
= note: expected signature `fn(&addr::VirtAddr, &addr::VirtAddr) -> (usize, Option<usize>)`
found signature `fn(&addr::VirtAddr, &addr::VirtAddr) -> Option<usize>`
help: change the output type to match the trait
|
382 | fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
| ~~~~~~~~~~~~~~~~~~~~~~ |
|
I have a error at the first step trying to run the "cargo test" barely...Has the different error as wrote in this book. UnwhiteCat@uccomputer ~/Codes/rust/blogos $ cargo test
Compiling scopeguard v1.2.0
Compiling bootloader v0.9.29
error[E0152]: duplicate lang item in crate `core` (which `rustc_std_workspace_core` depends on): `sized`
|
= note: the lang item is first defined in crate `core` (which `bootloader` depends on)
= note: first definition in `core` loaded from /home/UnwhiteCat/Codes/rust/blogos/target/x86_64-blog_os/debug/deps/libcore-33e3a870bea73245.rmeta
= note: second definition in `core` loaded from /home/UnwhiteCat/Codes/rust/blogos/target/x86_64-blog_os/debug/deps/libcore-f389adb7b0a7ac1b.rmeta
error[E0152]: duplicate lang item in crate `core` (which `rustc_std_workspace_core` depends on): `sized`
|
= note: the lang item is first defined in crate `core` (which `scopeguard` depends on)
= note: first definition in `core` loaded from /home/UnwhiteCat/Codes/rust/blogos/target/x86_64-blog_os/debug/deps/libcore-33e3a870bea73245.rmeta
= note: second definition in `core` loaded from /home/UnwhiteCat/Codes/rust/blogos/target/x86_64-blog_os/debug/deps/libcore-f389adb7b0a7ac1b.rmeta
For more information about this error, try `rustc --explain E0152`.
error: could not compile `scopeguard` (lib) due to 1 previous error
warning: build failed, waiting for other jobs to finish...
error: could not compile `bootloader` (lib) due to 1 previous errorHere is my rustc version. UnwhiteCat@uccomputer ~/Codes/rust/blogos $ rustc --version
rustc 1.85.0-nightly (6b6a867ae 2024-11-27) |
|
for some reason, qemu does not exit after calling |
|
When writing the |
|
If a test fails it prevents the next tests to be executed(by going through the panic handler due to the assert). |
|
Hi! When I try to run cargo test, it doesnt launch qemu, but I can't get to see any errors at all. Here is my code: The output in my console: All seems good but Qemu wont show up. Why?? Tried to use chatgpt but didnt help at all. |
|
First of all, thanks a lot for all this work!! Haven't gotten to the real meat yet I guess, but already enjoying it and learning very much. Just a tiny detail here: I guess it should be "... all exit codes ..."
|
|
@phil-opp about this:
Here's the best solution I could come up with. It seems to work just fine for me, but please let me know if you find any issue with this approach: // tests/should_panic.rs
#![no_std]
#![no_main]
#![feature(custom_test_frameworks)]
#![test_runner(test_runner)]
#![reexport_test_harness_main = "test_main"]
use spin::Mutex;
use rust_os::{
qemu::{types::QemuExitCode, utils::exit_qemu},
serial_print, serial_println,
};
static TEST_IDX: Mutex<u8> = Mutex::new(0);
#[unsafe(no_mangle)] // don't mangle the name of this function
pub extern "C" fn _start() -> ! {
test_main();
loop {}
}
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
serial_println!("[ok]");
*TEST_IDX.lock() += 1;
test_main();
loop {}
}
pub fn test_runner(tests: &[&dyn Fn()]) {
let num_tests = tests.len();
let test_idx = *TEST_IDX.lock() as usize;
if test_idx < num_tests {
let test = tests[test_idx];
test();
serial_println!("[test did not panic]");
exit_qemu(QemuExitCode::Failed);
} else {
exit_qemu(QemuExitCode::Success);
}
}
#[test_case]
fn should_fail_0() {
serial_print!("should_panic::should_fail_0...\t");
assert_eq!(0, 1);
}
#[test_case]
fn should_fail_1() {
serial_print!("should_panic::should_fail_1...\t");
assert_eq!(0, 1);
} |
|
I'm kind of a fan of using VSCode Docker devcontainers to avoid populating my computer with millions of dependencies from different languages / code experimentations. I started this tutorial by building in my devcontainer and then manually running qemu from the host. This worked until I started the "testing" session, since bootimage doesn't seem to have a way to build the test binaries and use them to create the image. After some research, I came up with the following script that sort of does the same than bootimage but allows me to create images from my test binaries and see the test results in qemu. I figured out the script by looking at the bootimage source and the bootloader README documentation (version 0.9). I hope it's useful for others |
|
Rust newbie here - why do we have to duplicate so much testing code between main.rs and lib.rs? Surely if lib.rs is the testing entrypoint, we should be able to remove all test-related code from main? |
|
Hi, this is my solution for running multiple tests that panic. I just tweaked it and shamelessly stole from @HernanFdz the idea of re-calling test_main in the panic handler. I added an in-panic guard (explained why in the code) and used atomics instead of mutexes because grabbing a spinlock in the panic handler can lead to an endless loop if not carefully done. Here's what worked for me (some of the boilerplate is different because I am using the latest version of bootloader but you get the idea): #![feature(custom_test_frameworks)]
#![test_runner(crate::test_runner)]
#![reexport_test_harness_main = "test_main"]
#![no_std]
#![no_main]
use core::panic::PanicInfo;
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use kernel::qemu::{QemuExitCode, exit_qemu};
use log::{error, info};
// Using atomic to avoid using `unsafe`, but it would be sound to use `unsafe` here.
static NEXT: AtomicUsize = AtomicUsize::new(0);
static IN_PANIC: AtomicBool = AtomicBool::new(false);
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
if IN_PANIC.swap(true, Ordering::Relaxed) {
// Somehow ended up here without stepping into `test_runner` first.
// Currently not required, but prevents painful debugging in the future:
// The way to end up here other than after a test ran by test_runner is that
// anything between setting `IN_PANIC` and clearing it again in `test_runner`
// panics, for example, the `info!` call below. If that were the case and
// there was no IN_PANIC guard, the panic handler would be triggered endlessly
// until the stack overflows.
exit_qemu(QemuExitCode::FAILURE);
loop {}
}
info!("[ok]");
NEXT.fetch_add(1, Ordering::Relaxed);
test_main();
loop {}
}
use bootloader_api::BootInfo;
bootloader_api::entry_point!(main);
fn main(boot_info: &'static mut BootInfo) -> ! {
kernel::init(boot_info);
test_main();
loop {}
}
// Re-implement test_runner because the one in lib does not expect panic!
pub fn test_runner(tests: &[&dyn Fn()]) {
let next = NEXT.load(Ordering::Relaxed);
if next == 0 {
info!("Running {} tests", tests.len());
}
if next < tests.len() {
IN_PANIC.store(false, Ordering::Relaxed);
tests[next]();
error!("[test did not panic]");
exit_qemu(QemuExitCode::FAILURE);
}
// no more tests to run, all panicked
exit_qemu(QemuExitCode::SUCCESS);
}
#[test_case]
fn should_fail_0() {
info!("should_panic::should_fail...");
assert_eq!(0, 1);
}
#[test_case]
fn should_fail_1() {
info!("should_panic::should_fail_two...");
assert_eq!(0, 2);
} |

Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
This is a general purpose comment thread for the Testing post.
All reactions