Add file-in-file (macro) support to json test runner
This commit is contained in:
parent
ba7e99f482
commit
bd91de42f0
3 changed files with 64 additions and 12 deletions
|
@ -1,4 +1,5 @@
|
||||||
/// Harness information for a test runner
|
/// Harness information for a test runner
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum Feedback {
|
pub enum Feedback {
|
||||||
/// Start of run (no feedback to provide)
|
/// Start of run (no feedback to provide)
|
||||||
Start,
|
Start,
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use super::super::{Instruction, Feedback, TestRunner, TestMetadata};
|
use super::super::{Instruction, Feedback, TestRunner, TestMetadata};
|
||||||
use super::{Test, FailureMode};
|
use super::{Test, FailureMode, TestStepType};
|
||||||
|
|
||||||
/// Test runner for specific JSON data structures.
|
/// Test runner for specific JSON data structures.
|
||||||
pub struct JsonRunner {
|
pub struct JsonRunner {
|
||||||
|
@ -7,11 +9,13 @@ pub struct JsonRunner {
|
||||||
step_i: usize,
|
step_i: usize,
|
||||||
op_i: usize,
|
op_i: usize,
|
||||||
success: bool,
|
success: bool,
|
||||||
|
filepath: Option<PathBuf>,
|
||||||
|
current_macro: Option<Box<Self>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JsonRunner {
|
impl JsonRunner {
|
||||||
/// Load test information from file
|
/// Load test information from file
|
||||||
pub fn from_file<P: AsRef<std::path::Path>>(path: P) -> std::io::Result<Self> {
|
pub fn from_file<P: AsRef<Path>>(path: P) -> std::io::Result<Self> {
|
||||||
let file = std::io::BufReader::new(std::fs::File::open(path.as_ref())?);
|
let file = std::io::BufReader::new(std::fs::File::open(path.as_ref())?);
|
||||||
let test = serde_json::from_reader(file)?;
|
let test = serde_json::from_reader(file)?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
@ -19,6 +23,8 @@ impl JsonRunner {
|
||||||
step_i: 0,
|
step_i: 0,
|
||||||
op_i: 0,
|
op_i: 0,
|
||||||
success: true,
|
success: true,
|
||||||
|
filepath: Some(path.as_ref().into()),
|
||||||
|
current_macro: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +35,8 @@ impl JsonRunner {
|
||||||
step_i: 0,
|
step_i: 0,
|
||||||
op_i: 0,
|
op_i: 0,
|
||||||
success: true,
|
success: true,
|
||||||
|
filepath: None,
|
||||||
|
current_macro: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,9 +48,19 @@ impl TestRunner for JsonRunner {
|
||||||
if matches!(fail_mode, FailureMode::FastFail) && !feedback.is_ok() {
|
if matches!(fail_mode, FailureMode::FastFail) && !feedback.is_ok() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
// handle in-progress macro execution
|
||||||
|
if let Some(current_macro) = &mut self.current_macro {
|
||||||
|
if let Some(instr) = current_macro.next(feedback.clone()) {
|
||||||
|
return Some(instr);
|
||||||
|
} else {
|
||||||
|
self.current_macro = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
#[allow(clippy::never_loop)]
|
#[allow(clippy::never_loop)]
|
||||||
'step_loop: while self.step_i < self.test_data.test.len() {
|
'step_loop: while self.step_i < self.test_data.test.len() {
|
||||||
let step = &self.test_data.test[self.step_i];
|
let step = &self.test_data.test[self.step_i];
|
||||||
|
match step {
|
||||||
|
TestStepType::Regular(step) => {
|
||||||
'op_loop: while self.op_i < step.operations.len() {
|
'op_loop: while self.op_i < step.operations.len() {
|
||||||
if matches!(fail_mode, FailureMode::SkipInstructions) && !feedback.is_ok() {
|
if matches!(fail_mode, FailureMode::SkipInstructions) && !feedback.is_ok() {
|
||||||
log::info!("{:?} Failing instruction, going to next step", fail_mode);
|
log::info!("{:?} Failing instruction, going to next step", fail_mode);
|
||||||
|
@ -53,6 +71,28 @@ impl TestRunner for JsonRunner {
|
||||||
self.op_i += 1;
|
self.op_i += 1;
|
||||||
return Some(instruction.clone().into_instruction(step.tab.clone()));
|
return Some(instruction.clone().into_instruction(step.tab.clone()));
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
TestStepType::Macro { name, file } => {
|
||||||
|
let path = if let Some(filepath) = &self.filepath {
|
||||||
|
filepath.join(file)
|
||||||
|
} else {
|
||||||
|
file.to_owned()
|
||||||
|
};
|
||||||
|
log::debug!("Macro {} expanded to {}", name, path.display());
|
||||||
|
self.step_i += 1;
|
||||||
|
match Self::from_file(&path) {
|
||||||
|
Ok(mut new_macro) => {
|
||||||
|
if let Some(instr) = new_macro.next(feedback.clone()) {
|
||||||
|
self.current_macro = Some(Box::new(new_macro));
|
||||||
|
return Some(instr);
|
||||||
|
} else {
|
||||||
|
log::warn!("Macro {} ({}) is empty!", name, file.display());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => log::error!("Macro {} ({}) failed to load: {}", name, file.display(), e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if matches!(fail_mode, FailureMode::SkipSteps) && !self.success {
|
if matches!(fail_mode, FailureMode::SkipSteps) && !self.success {
|
||||||
log::info!("{:?} Failing step complete, ending test", fail_mode);
|
log::info!("{:?} Failing step complete, ending test", fail_mode);
|
||||||
break 'step_loop;
|
break 'step_loop;
|
||||||
|
|
|
@ -8,7 +8,7 @@ use super::super::{TabSelector, ElementSelector, ElementOpType, ElementOp, TabOp
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct Test {
|
pub struct Test {
|
||||||
pub(super) info: TestInfo,
|
pub(super) info: TestInfo,
|
||||||
pub(super) test: Vec<TestStep>,
|
pub(super) test: Vec<TestStepType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test metadata
|
/// Test metadata
|
||||||
|
@ -41,7 +41,18 @@ impl std::convert::From<TestInfo> for TestMetadata {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test step
|
/// Test Step type
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum TestStepType {
|
||||||
|
Regular(TestStep),
|
||||||
|
Macro {
|
||||||
|
name: String,
|
||||||
|
file: std::path::PathBuf,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Regular test step
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct TestStep {
|
pub struct TestStep {
|
||||||
pub tab: TabDescriptor,
|
pub tab: TabDescriptor,
|
||||||
|
|
Loading…
Reference in a new issue