Skip to content

Commit 676a26c

Browse files
authored
Merge pull request #333 from rust-osdev/test-output
[test runner] Print QEMU output directly instead of waiting until it finishes
2 parents 27bad39 + a51bb15 commit 676a26c

File tree

2 files changed

+72
-61
lines changed

2 files changed

+72
-61
lines changed

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ jobs:
6565
- name: Run api tests
6666
run: cargo test -p bootloader_api
6767
- name: Run integration tests
68-
run: cargo test
68+
run: cargo test -- --test-threads 1
6969

7070
# test feature gates (only on one OS is enough)
7171
- name: Test with only UEFI feature

tests/runner/src/lib.rs

+71-60
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{io::Write, path::Path, process::Command};
1+
use std::{io::Read, path::Path, process::Command};
22

33
const QEMU_ARGS: &[&str] = &[
44
"-device",
@@ -9,6 +9,7 @@ const QEMU_ARGS: &[&str] = &[
99
"none",
1010
"--no-reboot",
1111
];
12+
const SEPARATOR: &str = "\n____________________________________\n";
1213

1314
pub fn run_test_kernel(kernel_binary_path: &str) {
1415
run_test_kernel_with_ramdisk(kernel_binary_path, None)
@@ -30,7 +31,7 @@ pub fn run_test_kernel_with_ramdisk(kernel_binary_path: &str, ramdisk_path: Opti
3031

3132
// create a TFTP folder with the kernel executable and UEFI bootloader for
3233
// UEFI PXE booting
33-
let tftp_path = kernel_path.with_extension(".tftp");
34+
let tftp_path = kernel_path.with_extension("tftp");
3435
uefi_builder.create_pxe_tftp_folder(&tftp_path).unwrap();
3536

3637
run_test_kernel_on_uefi(&gpt_path);
@@ -54,73 +55,83 @@ pub fn run_test_kernel_with_ramdisk(kernel_binary_path: &str, ramdisk_path: Opti
5455

5556
#[cfg(feature = "uefi")]
5657
pub fn run_test_kernel_on_uefi(out_gpt_path: &Path) {
57-
let mut run_cmd = Command::new("qemu-system-x86_64");
58-
run_cmd
59-
.arg("-drive")
60-
.arg(format!("format=raw,file={}", out_gpt_path.display()));
61-
run_cmd.args(QEMU_ARGS);
62-
run_cmd.arg("-bios").arg(ovmf_prebuilt::ovmf_pure_efi());
63-
64-
let child_output = run_cmd.output().unwrap();
65-
strip_ansi_escapes::Writer::new(std::io::stderr())
66-
.write_all(&child_output.stderr)
67-
.unwrap();
68-
strip_ansi_escapes::Writer::new(std::io::stderr())
69-
.write_all(&child_output.stdout)
70-
.unwrap();
71-
72-
match child_output.status.code() {
73-
Some(33) => {} // success
74-
Some(35) => panic!("Test failed"), // success
75-
other => panic!("Test failed with unexpected exit code `{:?}`", other),
76-
}
58+
let ovmf_pure_efi = ovmf_prebuilt::ovmf_pure_efi();
59+
let args = [
60+
"-bios",
61+
ovmf_pure_efi.to_str().unwrap(),
62+
"-drive",
63+
&format!("format=raw,file={}", out_gpt_path.display()),
64+
];
65+
run_qemu(args);
7766
}
7867

7968
#[cfg(feature = "bios")]
8069
pub fn run_test_kernel_on_bios(out_mbr_path: &Path) {
81-
let mut run_cmd = Command::new("qemu-system-x86_64");
82-
run_cmd
83-
.arg("-drive")
84-
.arg(format!("format=raw,file={}", out_mbr_path.display()));
85-
run_cmd.args(QEMU_ARGS);
86-
87-
let child_output = run_cmd.output().unwrap();
88-
strip_ansi_escapes::Writer::new(std::io::stderr())
89-
.write_all(&child_output.stderr)
90-
.unwrap();
91-
strip_ansi_escapes::Writer::new(std::io::stderr())
92-
.write_all(&child_output.stdout)
93-
.unwrap();
94-
95-
match child_output.status.code() {
96-
Some(33) => {} // success
97-
Some(35) => panic!("Test failed"), // success
98-
other => panic!("Test failed with unexpected exit code `{:?}`", other),
99-
}
70+
let args = [
71+
"-drive",
72+
&(format!("format=raw,file={}", out_mbr_path.display())),
73+
];
74+
run_qemu(args);
10075
}
10176

10277
#[cfg(feature = "uefi")]
10378
pub fn run_test_kernel_on_uefi_pxe(out_tftp_path: &Path) {
79+
let ovmf_pure_efi = ovmf_prebuilt::ovmf_pure_efi();
80+
let args = [
81+
"-netdev",
82+
&format!(
83+
"user,id=net0,net=192.168.17.0/24,tftp={},bootfile=bootloader,id=net0",
84+
out_tftp_path.display()
85+
),
86+
"-device",
87+
"virtio-net-pci,netdev=net0",
88+
"-bios",
89+
ovmf_pure_efi.to_str().unwrap(),
90+
];
91+
run_qemu(args);
92+
}
93+
94+
fn run_qemu<'a, A>(args: A)
95+
where
96+
A: IntoIterator<Item = &'a str>,
97+
{
98+
use std::process::Stdio;
99+
104100
let mut run_cmd = Command::new("qemu-system-x86_64");
105-
run_cmd.arg("-netdev").arg(format!(
106-
"user,id=net0,net=192.168.17.0/24,tftp={},bootfile=bootloader,id=net0",
107-
out_tftp_path.display()
108-
));
109-
run_cmd.arg("-device").arg("virtio-net-pci,netdev=net0");
101+
run_cmd.args(args);
110102
run_cmd.args(QEMU_ARGS);
111-
run_cmd.arg("-bios").arg(ovmf_prebuilt::ovmf_pure_efi());
112-
113-
let child_output = run_cmd.output().unwrap();
114-
strip_ansi_escapes::Writer::new(std::io::stderr())
115-
.write_all(&child_output.stderr)
116-
.unwrap();
117-
strip_ansi_escapes::Writer::new(std::io::stderr())
118-
.write_all(&child_output.stdout)
119-
.unwrap();
120-
121-
match child_output.status.code() {
122-
Some(33) => {} // success
123-
Some(35) => panic!("Test failed"),
124-
other => panic!("Test failed with unexpected exit code `{:?}`", other),
103+
let run_cmd_str = format!("{run_cmd:?}");
104+
105+
run_cmd.stdout(Stdio::piped());
106+
run_cmd.stderr(Stdio::piped());
107+
108+
let mut child = run_cmd.spawn().unwrap();
109+
110+
let child_stdout = child.stdout.take().unwrap();
111+
let mut child_stderr = child.stderr.take().unwrap();
112+
113+
let copy_stdout = std::thread::spawn(move || {
114+
let print_cmd = format!("\nRunning {run_cmd_str}\n\n").into_bytes();
115+
let mut output = print_cmd.chain(child_stdout).chain(SEPARATOR.as_bytes());
116+
std::io::copy(
117+
&mut output,
118+
&mut strip_ansi_escapes::Writer::new(std::io::stdout()),
119+
)
120+
});
121+
let copy_stderr = std::thread::spawn(move || {
122+
std::io::copy(
123+
&mut child_stderr,
124+
&mut strip_ansi_escapes::Writer::new(std::io::stderr()),
125+
)
126+
});
127+
128+
let exit_status = child.wait().unwrap();
129+
match exit_status.code() {
130+
Some(33) => {} // success
131+
Some(35) => panic!("Test failed"), // success
132+
other => panic!("Test failed with unexpected exit code `{other:?}`"),
125133
}
134+
135+
copy_stdout.join().unwrap().unwrap();
136+
copy_stderr.join().unwrap().unwrap();
126137
}

0 commit comments

Comments
 (0)