Skip to content

Commit

Permalink
Re-work test suite
Browse files Browse the repository at this point in the history
The existing test suite relied on ITM/ETM for getting test information.
We've since built up other tooling that doesn't require those features.
Switch to a hiffy based test design to allow for control of tests to
happen off target.
  • Loading branch information
labbott committed Sep 1, 2023
1 parent cd5f3c4 commit 851a70c
Show file tree
Hide file tree
Showing 26 changed files with 401 additions and 410 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions build/xtask/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,7 @@ impl BuildConfig<'_> {
"asm_const",
"naked_functions",
"named-profiles",
"used_with_arg",
]);
// nightly features that our dependencies use:
nightly_features.extend([
Expand Down
2 changes: 2 additions & 0 deletions task/hiffy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ hubris-num-tasks = { path = "../../sys/num-tasks", features = ["task-enum"] }
ringbuf = { path = "../../lib/ringbuf" }
static-cell = { path = "../../lib/static-cell" }
userlib = { path = "../../sys/userlib" }
test-api = { path = "../../test/test-api", optional = true}

byteorder.workspace = true
cfg-if.workspace = true
Expand All @@ -36,6 +37,7 @@ anyhow.workspace = true
cfg-if.workspace = true

[features]
testsuite = [ "test-api" ]
itm = [ "userlib/log-itm" ]
semihosting = [ "userlib/log-semihosting" ]
i2c = []
Expand Down
1 change: 1 addition & 0 deletions task/hiffy/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ where
/// on the Hubris side. (The purpose of this function is to allow for
/// device-mandated sleeps to in turn for allow for bulk device operations.)
///
#[allow(dead_code)]
pub(crate) fn sleep(
stack: &[Option<u32>],
_data: &[u8],
Expand Down
3 changes: 3 additions & 0 deletions task/hiffy/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ cfg_if::cfg_if! {
} else if #[cfg(feature = "stm32g0")] {
pub mod stm32g0;
use crate::stm32g0::*;
} else if #[cfg(feature = "testsuite")] {
pub mod tests;
use crate::tests::*;
} else {
pub mod generic;
use crate::generic::*;
Expand Down
117 changes: 117 additions & 0 deletions task/hiffy/src/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use byteorder::ByteOrder;
use hif::*;
use ringbuf::*;
use test_api::*;
#[allow(unused_imports)]
use userlib::{sys_send, task_slot};
use zerocopy::AsBytes;

task_slot!(TEST_TASK, suite);
task_slot!(RUNNER, runner);

// arg0: test id number
pub(crate) fn run_a_test(
stack: &[Option<u32>],
_data: &[u8],
rval: &mut [u8],
) -> Result<usize, Failure> {
if stack.len() < 1 {
return Err(Failure::Fault(Fault::MissingParameters));
}

let fp = stack.len() - 1;

let id = match stack[fp + 0] {
Some(id) => id,
None => {
return Err(Failure::Fault(Fault::EmptyParameter(0)));
}
};

userlib::kipc::restart_task(TEST_TASK.get_task_index().into(), true);

ringbuf_entry!(Trace::RunTest(id));
let (rc, _len) = sys_send(
TEST_TASK.get_task_id(),
SuiteOp::RunCase as u16,
&id.as_bytes(),
&mut [],
&[],
);

if rc != 0 {
return Err(Failure::FunctionError(rc));
}

let mut result: u32 = TestResult::NotDone as u32;

loop {
let (rc, _len) = sys_send(
RUNNER.get_task_id(),
RunnerOp::TestResult as u16,
&[],
&mut result.as_bytes_mut(),
&[],
);

if rc != 0 {
return Err(Failure::FunctionError(rc));
}

match TestResult::try_from(result) {
Ok(x) => match x {
TestResult::Success => {
byteorder::LittleEndian::write_u32(rval, 1);
return Ok(core::mem::size_of::<u32>());
}
TestResult::Failure => {
byteorder::LittleEndian::write_u32(rval, 0);
return Ok(core::mem::size_of::<u32>());
}
TestResult::NotDone => (),
},
Err(x) => return Err(Failure::FunctionError(x)),
}
}
}

#[derive(Copy, Clone, PartialEq)]
enum Trace {
Execute((usize, hif::Op)),
Failure(Failure),
Success,
RunTest(u32),
None,
}

ringbuf!(Trace, 64, Trace::None);

pub enum Functions {
RunTest(usize, bool),
}

pub(crate) static HIFFY_FUNCS: &[Function] = &[run_a_test];

//
// This definition forces the compiler to emit the DWARF needed for debuggers
// to be able to know function indices, arguments and return values.
//
#[no_mangle]
#[used]
static HIFFY_FUNCTIONS: Option<&Functions> = None;

pub(crate) fn trace_execute(offset: usize, op: hif::Op) {
ringbuf_entry!(Trace::Execute((offset, op)));
}

pub(crate) fn trace_success() {
ringbuf_entry!(Trace::Success);
}

pub(crate) fn trace_failure(f: hif::Failure) {
ringbuf_entry!(Trace::Failure(f));
}
1 change: 1 addition & 0 deletions test/test-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ edition = "2021"
[dependencies]
userlib = { path = "../../sys/userlib" }
num-traits = { workspace = true }
zerocopy = { workspace = true }

[build-dependencies]
build-util = { path = "../../build/util" }
Expand Down
29 changes: 24 additions & 5 deletions test/test-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@ pub enum AssistOp {
/// Operations that are performed by the test-suite
#[derive(FromPrimitive)]
pub enum SuiteOp {
/// Get the number of test cases (`() -> usize`).
GetCaseCount = 1,
/// Get the name of a case (`usize -> [u8]`).
GetCaseName = 2,
/// Run a case, replying before it starts (`usize -> ()`).
RunCase = 3,
}
Expand All @@ -57,5 +53,28 @@ pub enum RunnerOp {
ReadAndClearNotes = 0,
/// Signals that a test is complete, and that the runner is switching back
/// to passive mode (`() -> ()`).
TestComplete = 0xFFFF,
TestComplete = 0xfffe,
/// Returns the result of the last test if it completed
TestResult = 0xffff,
}

#[derive(FromPrimitive)]
#[repr(u32)]
pub enum TestResult {
Failure = 0,
Success = 1,
NotDone = 3,
}

impl TryFrom<u32> for TestResult {
type Error = u32;

fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
0 => Ok(TestResult::Failure),
1 => Ok(TestResult::Success),
3 => Ok(TestResult::NotDone),
x => Err(x),
}
}
}
1 change: 0 additions & 1 deletion test/test-assist/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@ fn eat_some_pi(highregs: bool) {

#[export_name = "main"]
fn main() -> ! {
sys_log!("assistant starting");
let mut buffer = [0; 4];
let mut last_reply = 0u32;
let mut stored_value = 0;
Expand Down
1 change: 1 addition & 0 deletions test/test-runner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ cortex-m = { workspace = true }
cortex-m-semihosting = { workspace = true, optional = true }
num-traits = { workspace = true }
zerocopy = { workspace = true }
ringbuf = { path = "../../lib/ringbuf" }

armv6m-atomic-hack = { path = "../../lib/armv6m-atomic-hack" }
hubris-num-tasks = { path = "../../sys/num-tasks" }
Expand Down
Loading

0 comments on commit 851a70c

Please sign in to comment.