Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to test after migration from 0.9.x #330

Open
muellerpeter-pms opened this issue Jan 20, 2023 · 4 comments
Open

How to test after migration from 0.9.x #330

muellerpeter-pms opened this issue Jan 20, 2023 · 4 comments

Comments

@muellerpeter-pms
Copy link

I migrated from 0.9.x to 0.11.

The build works fine but tests are broken the old way. When testing teh kernel there is no executable, what I can understand. But when testing the parent directory only the crate itself will be tested. When testing the parent directory with --workspace option there is no target transferred to the kernel build, which leads to the error:

"error: language item required, but not found: `eh_personality`
 |
  = note: this can occur when a binary crate with `#![no_std]` is compiled for a target where `eh_personality` is defined in the standard library
  = help: you may be able to compile for a target that doesn't need `eh_personality`, specify a target with `--target` or in `.cargo/config`

I guess there is an option to pass the target even in test build mode. But I didn't find yet.

Thanks in advane!

@Benabik
Copy link

Benabik commented Jan 30, 2023

I got the tests to build by leaving a kernel/.cargo/config.toml file:

[build]
target = "x86_64-unknown-none"

Actually running the tests runs into further issues: namely that it tries to run the ELF file as a binary. This was done in 0.9 by also having the following in the cargo config:

[target.'cfg(target_os = "none")']
runner = "bootimage runner"

What bootimage runner seems to do is build a boot image from an executable passed as an argument and then execute qemu. The code to do that is now in build.rs and src/main.rs from the disk image template. I'm guessing I could create a new bin crate in the workspace that does what both of those files do but getting the kernel from std::env::args_os() instead of std::env::var_os("CARGO_BIN_FILE_KERNEL_kernel").

@Benabik
Copy link

Benabik commented Jan 30, 2023

Yup! I added the following runner to my OS workspace:

// runner/src/main.rs

use std::path::PathBuf;

fn main() {
    let mut args = std::env::args_os().skip(1); // Skip runner name

    let mut cmd = std::process::Command::new("qemu-system-x86_64");
    cmd.args([
        "-device",
        "isa-debug-exit,iobase=0xf4,iosize=0x04",
        "-serial",
        "stdio",
    ]);
    while args.len() > 1 {
        cmd.arg(args.next().unwrap());
    }

    let kernel = PathBuf::from(args.next().unwrap());

    // choose whether to start the UEFI or BIOS image
    let uefi = false;

    let mut image_path = std::env::temp_dir().join(kernel.file_name().unwrap());
    image_path.set_extension("img");

    if uefi {
        todo!("Replace PIC with APIC before using UEFI");
        /*
        bootloader::UefiBoot::new(&kernel).create_disk_image(&image_path).unwrap();

        cmd.arg("-bios").arg(ovmf_prebuilt::ovmf_pure_efi());
        */
    } else {
        // create a BIOS disk image
        bootloader::BiosBoot::new(&kernel)
            .create_disk_image(&image_path)
            .unwrap();
    }

    let mut drive: std::ffi::OsString = "format=raw,file=".into();
    drive.push(&image_path);
    cmd.arg("-drive").arg(drive);

    // Start QEMU and wait
    let mut child = cmd.spawn().unwrap();
    child.wait().unwrap();
    std::fs::remove_file(&image_path).unwrap();
}

Edit: Above code used to use OUT_DIR, but that is apparently unreliable for a test runner. Now creates a file in temp_dir and removes after QEMU exits.

And my kernel/.cargo/config.toml is

[build]
target = "x86_64-unknown-none"

[target.'cfg(target_os = "none")']
runner = ["../target/debug/runner", "-display", "none"]

Options to the runner are passed to QEMU, and I highly recommend removing -display none until you get it to pass once (since the bootloader panics are shown on the framebuffer). Also note that you need to build the runner manually after you make changes to it.

@emanuele-em
Copy link

I'm interested in this but I don't understand @Benabik fix, can you link the repo?

@jasondyoungberg
Copy link

I was able to get my tests to run by first compiling the kernel with

cargo test -p kernel --no-run --target x86_64-unknown-none

Then replacing the kernel in build.rs and running it like normal.

I don't yet know how to get cargo test to work, but I'm watching rust-lang/cargo#11680 for a solution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants