Skip to content

Commit

Permalink
Runner: add option for expected output in tests
Browse files Browse the repository at this point in the history
This commit adds a new test parameter, 'expect', which takes a substring
that should be present in the output of the test. This is useful to
ensure certain things happen. For instance Linux can successfully boot
on a multi-core machine even if a hart is not responding, which this
patch we can check that all harts booted properly.
  • Loading branch information
CharlyCst committed Dec 9, 2024
1 parent 54ab75a commit cf5af6a
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 3 deletions.
1 change: 1 addition & 0 deletions miralis.toml
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ description = "Run Linux and exit as soon as it reaches userspace on a sifive u5
firmware = "linux"
config = "qemu-virt-2harts"
description = "Run linux with two cores, expecting it to boot with both"
expect = "smp: Brought up 1 node, 2 CPUs"

## ———————————————————————————— Testing Policies ———————————————————————————— ##

Expand Down
2 changes: 2 additions & 0 deletions runner/src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ pub struct Test {
pub description: Option<String>,
pub firmware: Option<String>,
pub payload: Option<String>,
/// An expected string from the output of the test
pub expect: Option<String>,
}
37 changes: 34 additions & 3 deletions runner/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
use std::collections::HashMap;
use std::fs;
use std::io::Read;
use std::path::PathBuf;
use std::process::ExitCode;
use std::process::{ExitCode, Stdio};

use crate::artifacts::{build_target, prepare_firmware_artifact, Target};
use crate::config::{read_config, Config, Platforms};
Expand Down Expand Up @@ -170,6 +171,7 @@ pub fn run_one_test(test: &Test, test_name: &str, cfg: &Config) -> Result<(), Op
return Err(None);
};

// Prepare the command to run
let cmd = match cfg.platform.name.unwrap_or(Platforms::QemuVirt) {
Platforms::QemuVirt => {
get_qemu_cmd(cfg, miralis, firmware, test.payload.as_ref(), false, false)
Expand All @@ -194,9 +196,38 @@ pub fn run_one_test(test: &Test, test_name: &str, cfg: &Config) -> Result<(), Op
.join(" ")
);

let exit_status = cmd.status().expect("Failed to run");
// Then execute the test and check for the success criteria
//
// For some tests we require a substring to be present in the output, in those cases we do some
// aditionnal work on top of checking the exit status.
let mut succeeded = true;
let exit_status = if let Some(expected) = &test.expect {
// We need to get the output of the child, we create a pipe for that purpose
cmd.stdout(Stdio::piped());
let mut child = cmd.spawn().expect("Failed to spawn command");
let pipe = child
.stdout
.as_mut()
.expect("Could not read child process output");
let mut buff = Vec::new();
pipe.read_to_end(&mut buff)
.expect("Failed to read output from child process");
let exit_status = child.wait().expect("Failed to wait for child process");

// We got the exit status, now also check for the expected pattern
let buff = String::from_utf8_lossy(&buff);
if !buff.contains(expected) {
log::error!("Could not find '{}' in the test output", expected);
succeeded = false;
}

exit_status
} else {
// log::warn!("Test :)");
cmd.status().expect("Failed to run")
};

if !exit_status.success() {
if !exit_status.success() || !succeeded {
let cmd_str = format!(
"{} {}",
cmd.get_program().to_str().unwrap(),
Expand Down

0 comments on commit cf5af6a

Please sign in to comment.