Skip to content

Commit

Permalink
add single chip test that can take a url
Browse files Browse the repository at this point in the history
  • Loading branch information
Emilgardis committed Feb 4, 2024
1 parent 6570752 commit b829f35
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 24 deletions.
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ features = ["full","extra-traits"]
members = ["ci/svd2rust-regress"]
default-members = ["."]
exclude = [
"output/**",
# workaround for https://github.com/rust-lang/cargo/pull/12779
"output",
# workaround for https://github.com/rust-lang/cargo/pull/12779, doesn't work for output though
# see https://github.com/rust-lang/cargo/issues/6009#issuecomment-1925445245
"output/baseline/**",
"output/current/**"
]
127 changes: 112 additions & 15 deletions ci/svd2rust-regress/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ pub fn get_cargo_workspace() -> &'static std::path::Path {
}

#[derive(clap::Parser, Debug)]
pub struct TestOpts {
pub struct TestAll {
/// Run a long test (it's very long)
#[clap(short = 'l', long)]
pub long_test: bool,
Expand All @@ -59,7 +59,7 @@ pub struct TestOpts {
#[clap(short = 'c', long)]
pub chip: Vec<String>,

/// Filter by manufacturer, case sensitive, may be combined with other filters
/// Filter by manufacturer, may be combined with other filters
#[clap(
short = 'm',
long = "manufacturer",
Expand All @@ -68,7 +68,7 @@ pub struct TestOpts {
)]
pub mfgr: Option<String>,

/// Filter by architecture, case sensitive, may be combined with other filters
/// Filter by architecture, may be combined with other filters
#[clap(
short = 'a',
long = "architecture",
Expand Down Expand Up @@ -104,7 +104,97 @@ pub struct TestOpts {
// TODO: Compile svd2rust?
}

impl TestOpts {
#[derive(clap::Parser, Debug)]
// TODO: Replace with https://github.com/clap-rs/clap/issues/2621 when available
#[group(id = "svd_source", required = true)]
pub struct Test {
/// Enable formatting with `rustfmt`
#[arg(short = 'f', long)]
pub format: bool,

#[arg(long)]
/// Enable splitting `lib.rs` with `form`
pub form_lib: bool,

#[arg(
short = 'm',
long = "manufacturer",
ignore_case = true,
value_parser = manufacturers(),
)]
/// Manufacturer
pub mfgr: Option<String>,
#[arg(
short = 'a',
long = "architecture",
ignore_case = true,
value_parser = architectures(),
)]
/// Architecture
pub arch: Option<String>,
#[arg(long, group = "svd_source", conflicts_with_all = ["svd_file"], requires = "arch")]
/// URL to SVD file to test
pub url: Option<String>,
#[arg(long = "svd", group = "svd_source")]
/// Path to SVD file to test
pub svd_file: Option<PathBuf>,
#[arg(long, group = "svd_source")]
/// Chip to use, use `--url` or `--svd-file` for another way to specify svd
pub chip: Option<String>,

/// Path to an `svd2rust` binary, relative or absolute.
/// Defaults to `target/release/svd2rust[.exe]` of this repository
/// (which must be already built)
#[clap(short = 'p', long = "svd2rust-path", default_value = default_svd2rust())]
pub current_bin_path: PathBuf,
#[clap(last = true)]
pub command: Option<String>,
}

impl Test {
fn run(&self, opts: &Opts) -> Result<(), anyhow::Error> {
match self {
Self { url: Some(url), .. } => {}
Self {
svd_file: Some(svd_file),
..
} => {}
Self {
chip: Some(chip), ..
} => {}
_ => unreachable!("clap should not allow this"),
}
let test = if let (Some(url), Some(arch)) = (&self.url, &self.arch) {
tests::TestCase {
arch: svd2rust::Target::parse(&arch)?,
mfgr: tests::Manufacturer::Unknown,
chip: self
.chip
.as_deref()
.or_else(|| url.rsplit('/').next().and_then(|s| s.strip_suffix(".svd")))
.ok_or_else(|| {
anyhow::anyhow!(
"could not figure out chip name, specify with `--chip <name>`",
)
})?
.to_owned(),
svd_url: Some(url.clone()),
should_pass: true,
run_when: tests::RunWhen::default(),
}
} else {
tests::tests(Some(&opts.test_cases))?
.iter()
.find(|t| self.chip.iter().any(|c| WildMatch::new(c).matches(&t.chip)))
.ok_or_else(|| anyhow::anyhow!("no test found for chip"))?
.to_owned()
};
test.test(opts, &self.current_bin_path, self.command.as_deref())?;
Ok(())
}
}

impl TestAll {
fn run(&self, opt: &Opts) -> Result<(), anyhow::Error> {
let tests = tests::tests(Some(&opt.test_cases))?
.iter()
Expand Down Expand Up @@ -152,7 +242,7 @@ impl TestOpts {
tests.par_iter().for_each(|t| {
let start = Instant::now();

match t.test(opt, self) {
match t.test(opt, &self.current_bin_path, self.command.as_deref()) {
Ok(s) => {
if let Some(stderrs) = s {
let mut buf = String::new();
Expand Down Expand Up @@ -217,7 +307,8 @@ impl TestOpts {
#[derive(clap::Subcommand, Debug)]
pub enum Subcommand {
Diff(Diffing),
Tests(TestOpts),
Tests(TestAll),
Test(Test),
Ci(Ci),
}

Expand Down Expand Up @@ -256,15 +347,17 @@ pub struct Opts {
impl Opts {
const fn use_rustfmt(&self) -> bool {
match self.subcommand {
Subcommand::Tests(TestOpts { format, .. })
Subcommand::Tests(TestAll { format, .. })
| Subcommand::Test(Test { format, .. })
| Subcommand::Diff(Diffing { format, .. })
| Subcommand::Ci(Ci { format, .. }) => format,
}
}

const fn use_form(&self) -> bool {
match self.subcommand {
Subcommand::Tests(TestOpts { form_lib, .. })
Subcommand::Tests(TestAll { form_lib, .. })
| Subcommand::Test(Test { form_lib, .. })
| Subcommand::Diff(Diffing {
form_split: form_lib,
..
Expand All @@ -278,13 +371,10 @@ impl Opts {
fn default_test_cases() -> std::ffi::OsString {
std::env::var_os("CARGO_MANIFEST_DIR").map_or_else(
|| std::ffi::OsString::from("tests.yml".to_owned()),
|mut e| {
e.extend([std::ffi::OsStr::new("/tests.yml")]);
std::path::PathBuf::from(e)
.strip_prefix(std::env::current_dir().unwrap())
.unwrap()
.to_owned()
.into_os_string()
|path| {
let path = std::path::PathBuf::from(path);
let path = path.join("tests.yml");
path.to_owned().into_os_string()
},
)
}
Expand Down Expand Up @@ -414,6 +504,13 @@ fn main() -> Result<(), anyhow::Error> {
}
Subcommand::Diff(diff) => diff.run(&opt).with_context(|| "failed to run diff"),
Subcommand::Ci(ci) => ci.run(&opt).with_context(|| "failed to run ci"),
Subcommand::Test(test) => {
anyhow::ensure!(
test.current_bin_path.exists(),
"svd2rust binary does not exist"
);
test.run(&opt).with_context(|| "failed to run test")
}
}
}

Expand Down
12 changes: 6 additions & 6 deletions ci/svd2rust-regress/src/svd_test.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::{anyhow, Context, Result};
use svd2rust::{util::ToSanitizedCase, Target};

use crate::{command::CommandExt, tests::TestCase, Opts, TestOpts};
use crate::{command::CommandExt, tests::TestCase, Opts, TestAll};
use std::io::prelude::*;
use std::path::PathBuf;
use std::process::Command;
Expand Down Expand Up @@ -133,17 +133,18 @@ impl CommandHelper for Command {
}

impl TestCase {
#[tracing::instrument(skip(self, opts, test_opts), fields(name = %self.name()))]
#[tracing::instrument(skip(self, opts), fields(name = %self.name()))]
pub fn test(
&self,
opts: &Opts,
test_opts: &TestOpts,
bin_path: &Path,
command: Option<&str>,
) -> Result<Option<Vec<PathBuf>>, TestError> {
let (chip_dir, mut process_stderr_paths) = self
.setup_case(
&opts.output_dir,
&test_opts.current_bin_path,
test_opts.command.as_deref(),
bin_path,
command,
)
.with_context(|| anyhow!("when setting up case for {}", self.name()))?;
// Run `cargo check`, capturing stderr to a log file
Expand Down Expand Up @@ -355,7 +356,6 @@ impl TestCase {

process_stderr_paths.push(rustfmt_err_file);
}
tracing::info!("Done processing");
Ok((chip_dir, process_stderr_paths))
}
}
Expand Down
2 changes: 1 addition & 1 deletion ci/svd2rust-regress/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ pub enum RunWhen {
Never,
}

#[derive(serde::Serialize, serde::Deserialize, Clone)]
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
pub struct TestCase {
pub arch: Target,
pub mfgr: Manufacturer,
Expand Down

0 comments on commit b829f35

Please sign in to comment.