xtask: Add tests, clean a bit

This commit is contained in:
Henrik Tjäder 2023-02-28 23:55:02 +01:00
parent 14457da4f8
commit a575266ec2
3 changed files with 285 additions and 242 deletions

View file

@ -65,6 +65,7 @@ jobs:
uses: Swatinem/rust-cache@v2 uses: Swatinem/rust-cache@v2
- run: cargo xtask --verbose --backend ${{ matrix.backend }} check - run: cargo xtask --verbose --backend ${{ matrix.backend }} check
# Clippy # Clippy
clippy: clippy:
name: clippy name: clippy
@ -193,8 +194,8 @@ jobs:
run: cargo xtask --verbose --backend ${{ matrix.backend }} qemu run: cargo xtask --verbose --backend ${{ matrix.backend }} qemu
# Run test suite # Run test suite
testsrtic: tests:
name: tests rtic name: tests
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
strategy: strategy:
matrix: matrix:
@ -203,6 +204,14 @@ jobs:
- thumbv6-backend - thumbv6-backend
- thumbv8base-backend - thumbv8base-backend
- thumbv8main-backend - thumbv8main-backend
package:
- rtic
- rtic-arbiter
- rtic-channel
- rtic-common
- rtic-macros
- rtic-monotonics
- rtic-time
steps: steps:
- name: Checkout - name: Checkout
@ -211,114 +220,18 @@ jobs:
- name: Cache Dependencies - name: Cache Dependencies
uses: Swatinem/rust-cache@v2 uses: Swatinem/rust-cache@v2
- name: Configure Rust target (v6, v7, v8.b v8.m)
run: |
rustup target add thumbv7m-none-eabi
rustup target add thumbv6m-none-eabi
rustup target add thumbv8m.base-none-eabi
rustup target add thumbv8m.main-none-eabi
- name: Fail on warnings - name: Fail on warnings
working-directory: ./rtic run: find . -type f -name lib.rs -execdir sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' {} +
run: sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' src/lib.rs
- name: Run cargo test - name: Run cargo test
working-directory: ./rtic run: cargo xtask --verbose --backend ${{ matrix.backend }} test ${{ matrix.package }}
run: cargo test --features ${{ matrix.backend }} --test ui
# Run the macros test-suite
testsmacros:
name: tests rtic-macros
runs-on: ubuntu-22.04
strategy:
matrix:
backend:
- cortex-m-source-masking
- cortex-m-basepri
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Cache Dependencies
uses: Swatinem/rust-cache@v2
- name: Fail on warnings
working-directory: ./rtic-macros
run: sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' src/lib.rs
- name: cargo check
working-directory: ./rtic-macros
run: cargo test --features ${{ matrix.backend }}
# Run test suite
testsarbiter:
name: tests rtic-arbiter
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Cache Dependencies
uses: Swatinem/rust-cache@v2
- name: Fail on warnings
working-directory: ./rtic-arbiter
run: sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' src/lib.rs
- name: Run cargo test
working-directory: ./rtic-arbiter
run: cargo test --features testing
# Run test suite
testschannel:
name: tests rtic-channel
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Cache Dependencies
uses: Swatinem/rust-cache@v2
- name: Fail on warnings
working-directory: ./rtic-channel
run: sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' src/lib.rs
- name: Run cargo test
working-directory: ./rtic-channel
run: cargo test --features testing
# Run test suite
testsmonotonics:
name: tests rtic-monotonics
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Cache Dependencies
uses: Swatinem/rust-cache@v2
- name: Fail on warnings
working-directory: ./rtic-monotonics
run: sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' src/lib.rs
- name: Run cargo test
working-directory: ./rtic-monotonics
run: cargo test --test tests
# Run test suite
teststime:
name: tests rtic-time
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Cache Dependencies
uses: Swatinem/rust-cache@v2
- name: Fail on warnings
working-directory: ./rtic-time
run: sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' src/lib.rs
- name: Run cargo test
working-directory: ./rtic-time
run: cargo test
# Build documentation, check links # Build documentation, check links
docs: docs:
@ -624,12 +537,7 @@ jobs:
- clippy - clippy
- checkexamples - checkexamples
- testexamples - testexamples
- testsrtic - tests
- testsmacros
- testsarbiter
- testschannel
- testsmonotonics
- teststime
- docs - docs
- mdbook - mdbook
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04

View file

@ -1,4 +1,4 @@
use crate::{debug, RunResult, Sizearguments, TestRunError}; use crate::{debug, Package, RunResult, Sizearguments, TestRunError};
use core::fmt; use core::fmt;
use os_pipe::pipe; use os_pipe::pipe;
use std::{fs::File, io::Read, process::Command}; use std::{fs::File, io::Read, process::Command};
@ -18,58 +18,63 @@ pub enum CargoCommand<'a> {
cargoarg: &'a Option<&'a str>, cargoarg: &'a Option<&'a str>,
example: &'a str, example: &'a str,
target: &'a str, target: &'a str,
features: Option<&'a str>, features: Option<String>,
mode: BuildMode, mode: BuildMode,
}, },
Qemu { Qemu {
cargoarg: &'a Option<&'a str>, cargoarg: &'a Option<&'a str>,
example: &'a str, example: &'a str,
target: &'a str, target: &'a str,
features: Option<&'a str>, features: Option<String>,
mode: BuildMode, mode: BuildMode,
}, },
ExampleBuild { ExampleBuild {
cargoarg: &'a Option<&'a str>, cargoarg: &'a Option<&'a str>,
example: &'a str, example: &'a str,
target: &'a str, target: &'a str,
features: Option<&'a str>, features: Option<String>,
mode: BuildMode, mode: BuildMode,
}, },
ExampleCheck { ExampleCheck {
cargoarg: &'a Option<&'a str>, cargoarg: &'a Option<&'a str>,
example: &'a str, example: &'a str,
target: &'a str, target: &'a str,
features: Option<&'a str>, features: Option<String>,
mode: BuildMode, mode: BuildMode,
}, },
Build { Build {
cargoarg: &'a Option<&'a str>, cargoarg: &'a Option<&'a str>,
package: Vec<String>, package: Option<Package>,
target: &'a str, target: &'a str,
features: Option<&'a str>, features: Option<String>,
mode: BuildMode, mode: BuildMode,
}, },
Check { Check {
cargoarg: &'a Option<&'a str>, cargoarg: &'a Option<&'a str>,
package: Vec<String>, package: Option<Package>,
target: &'a str, target: &'a str,
features: Option<&'a str>, features: Option<String>,
mode: BuildMode, mode: BuildMode,
}, },
Clippy { Clippy {
cargoarg: &'a Option<&'a str>, cargoarg: &'a Option<&'a str>,
package: Vec<String>, package: Option<Package>,
target: &'a str, target: &'a str,
features: Option<&'a str>, features: Option<String>,
}, },
Format { Format {
cargoarg: &'a Option<&'a str>, cargoarg: &'a Option<&'a str>,
package: Vec<String>, package: Option<Package>,
check_only: bool, check_only: bool,
}, },
Doc { Doc {
cargoarg: &'a Option<&'a str>, cargoarg: &'a Option<&'a str>,
features: Option<&'a str>, features: Option<String>,
},
Test {
package: Option<Package>,
features: Option<String>,
test: Option<String>,
}, },
Book { Book {
mdbookarg: &'a Option<&'a str>, mdbookarg: &'a Option<&'a str>,
@ -78,7 +83,7 @@ pub enum CargoCommand<'a> {
cargoarg: &'a Option<&'a str>, cargoarg: &'a Option<&'a str>,
example: &'a str, example: &'a str,
target: &'a str, target: &'a str,
features: Option<&'a str>, features: Option<String>,
mode: BuildMode, mode: BuildMode,
arguments: Option<Sizearguments>, arguments: Option<Sizearguments>,
}, },
@ -95,8 +100,7 @@ impl<'a> CargoCommand<'a> {
CargoCommand::Format { .. } => "fmt", CargoCommand::Format { .. } => "fmt",
CargoCommand::Doc { .. } => "doc", CargoCommand::Doc { .. } => "doc",
CargoCommand::Book { .. } => "build", CargoCommand::Book { .. } => "build",
// TODO CargoCommand::Test { .. } => "test",
// CargoCommand::Test { .. } => "test",
} }
} }
pub fn command(&self) -> &str { pub fn command(&self) -> &str {
@ -110,10 +114,9 @@ impl<'a> CargoCommand<'a> {
| CargoCommand::ExampleSize { .. } | CargoCommand::ExampleSize { .. }
| CargoCommand::Clippy { .. } | CargoCommand::Clippy { .. }
| CargoCommand::Format { .. } | CargoCommand::Format { .. }
| CargoCommand::Test { .. }
| CargoCommand::Doc { .. } => "cargo", | CargoCommand::Doc { .. } => "cargo",
CargoCommand::Book { .. } => "mdbook", CargoCommand::Book { .. } => "mdbook",
// TODO
// CargoCommand::Test { .. } => "test",
} }
} }
@ -175,10 +178,9 @@ impl<'a> CargoCommand<'a> {
} }
args.extend_from_slice(&[self.name(), "--target", target]); args.extend_from_slice(&[self.name(), "--target", target]);
if !package.is_empty() {
for package in package { if let Some(package) = package {
args.extend_from_slice(&["--package", package]); args.extend_from_slice(&["--package", package.to_string()]);
}
} }
if let Some(feature) = features { if let Some(feature) = features {
@ -201,10 +203,9 @@ impl<'a> CargoCommand<'a> {
args.extend_from_slice(&[cargoarg]); args.extend_from_slice(&[cargoarg]);
} }
args.extend_from_slice(&[self.name(), "--target", target]); args.extend_from_slice(&[self.name(), "--target", target]);
if !package.is_empty() {
for package in package { if let Some(package) = package {
args.extend_from_slice(&["--package", package]); args.extend_from_slice(&["--package", package.to_string()]);
}
} }
if let Some(feature) = features { if let Some(feature) = features {
@ -227,10 +228,9 @@ impl<'a> CargoCommand<'a> {
} }
args.extend_from_slice(&[self.name(), "--target", target]); args.extend_from_slice(&[self.name(), "--target", target]);
if !package.is_empty() {
for package in package { if let Some(package) = package {
args.extend_from_slice(&["--package", package]); args.extend_from_slice(&["--package", package.to_string()]);
}
} }
if let Some(feature) = features { if let Some(feature) = features {
@ -251,6 +251,26 @@ impl<'a> CargoCommand<'a> {
} }
args args
} }
CargoCommand::Test {
package,
features,
test,
} => {
let mut args = vec!["+nightly"];
args.extend_from_slice(&[self.name()]);
if let Some(package) = package {
args.extend_from_slice(&["--package", package.to_string()]);
}
if let Some(feature) = features {
args.extend_from_slice(&["--features", feature]);
}
if let Some(test) = test {
args.extend_from_slice(&["--test", test]);
}
args
}
CargoCommand::Book { mdbookarg } => { CargoCommand::Book { mdbookarg } => {
let mut args = vec![]; let mut args = vec![];
@ -273,10 +293,8 @@ impl<'a> CargoCommand<'a> {
args.extend_from_slice(&[cargoarg]); args.extend_from_slice(&[cargoarg]);
} }
if !package.is_empty() { if let Some(package) = package {
for package in package { args.extend_from_slice(&["--package", package.to_string()]);
args.extend_from_slice(&["--package", package]);
}
} }
if *check_only { if *check_only {
args.extend_from_slice(&["--check"]); args.extend_from_slice(&["--check"]);

View file

@ -17,7 +17,6 @@ use std::{
}; };
use env_logger::Env; use env_logger::Env;
use exitcode;
use log::{debug, error, info, log_enabled, trace, Level}; use log::{debug, error, info, log_enabled, trace, Level};
use crate::{ use crate::{
@ -34,6 +33,88 @@ const ARMV8MMAIN: &str = "thumbv8m.main-none-eabi";
const DEFAULT_FEATURES: &str = "test-critical-section"; const DEFAULT_FEATURES: &str = "test-critical-section";
#[derive(clap::ValueEnum, Copy, Clone, Debug)]
pub enum Package {
Rtic,
RticArbiter,
RticChannel,
RticCommon,
RticMacros,
RticMonotonics,
RticTime,
}
impl fmt::Display for Package {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.to_string())
}
}
impl Package {
fn to_string(&self) -> &str {
match self {
Package::Rtic => "rtic",
Package::RticArbiter => "rtic-arbiter",
Package::RticChannel => "rtic-channel",
Package::RticCommon => "rtic-common",
Package::RticMacros => "rtic-macros",
Package::RticMonotonics => "rtic-monotonics",
Package::RticTime => "rtic-time",
}
}
}
struct TestMetadata {}
impl TestMetadata {
fn match_package(package: Package, backend: Backends) -> CargoCommand<'static> {
match package {
Package::Rtic => {
let features = Some(format!(
"{},{}",
DEFAULT_FEATURES,
backend.to_rtic_feature(),
));
CargoCommand::Test {
package: Some(package),
features,
test: Some("ui".to_owned()),
}
}
Package::RticMacros => CargoCommand::Test {
package: Some(package),
features: Some(backend.to_rtic_macros_feature().to_owned()),
test: None,
},
Package::RticArbiter => CargoCommand::Test {
package: Some(package),
features: Some("testing".to_owned()),
test: None,
},
Package::RticChannel => CargoCommand::Test {
package: Some(package),
features: Some("testing".to_owned()),
test: None,
},
Package::RticCommon => CargoCommand::Test {
package: Some(package),
features: Some("testing".to_owned()),
test: None,
},
Package::RticMonotonics => CargoCommand::Test {
package: Some(package),
features: None,
test: Some("tests".to_owned()),
},
Package::RticTime => CargoCommand::Test {
package: Some(package),
features: None,
test: None,
},
}
}
}
#[derive(clap::ValueEnum, Copy, Clone, Default, Debug)] #[derive(clap::ValueEnum, Copy, Clone, Default, Debug)]
enum Backends { enum Backends {
Thumbv6, Thumbv6,
@ -61,6 +142,14 @@ impl Backends {
Backends::Thumbv8Main => "thumbv8main-backend", Backends::Thumbv8Main => "thumbv8main-backend",
} }
} }
fn to_rtic_macros_feature(&self) -> &str {
match self {
Backends::Thumbv6 => "cortex-m-source-masking",
Backends::Thumbv7 => "cortex-m-basepri",
Backends::Thumbv8Base => "cortex-m-source-masking",
Backends::Thumbv8Main => "cortex-m-basepri",
}
}
} }
#[derive(Copy, Clone, Default, Debug)] #[derive(Copy, Clone, Default, Debug)]
@ -108,19 +197,19 @@ struct Cli {
#[derive(Debug, Subcommand)] #[derive(Debug, Subcommand)]
enum Commands { enum Commands {
/// Check formatting /// Check formatting
FormatCheck(Package), FormatCheck(PackageOpt),
/// Format code /// Format code
Format(Package), Format(PackageOpt),
/// Run clippy /// Run clippy
Clippy(Package), Clippy(PackageOpt),
/// Check all packages /// Check all packages
Check(Package), Check(PackageOpt),
/// Build all packages /// Build all packages
Build(Package), Build(PackageOpt),
/// Check all examples /// Check all examples
ExampleCheck, ExampleCheck,
@ -155,17 +244,20 @@ enum Commands {
/// Build docs /// Build docs
Doc, Doc,
/// Run tests
Test(PackageOpt),
/// Build books with mdbook /// Build books with mdbook
Book, Book,
} }
#[derive(Args, Debug)] #[derive(Args, Debug)]
/// Restrict to package, or run on whole workspace /// Restrict to package, or run on whole workspace
struct Package { struct PackageOpt {
/// For which package/workspace member to operate /// For which package/workspace member to operate
/// ///
/// If omitted, work on all /// If omitted, work on all
package: Option<String>, package: Option<Package>,
} }
#[derive(Args, Debug)] #[derive(Args, Debug)]
@ -379,14 +471,14 @@ fn main() -> anyhow::Result<()> {
&examples_to_run, &examples_to_run,
)?; )?;
} }
Commands::Size(arguments) => { Commands::Size(args) => {
// x86_64 target not valid // x86_64 target not valid
info!("Measuring for backend: {backend:?}"); info!("Measuring for backend: {backend:?}");
build_and_check_size( build_and_check_size(
&cargologlevel, &cargologlevel,
backend, backend,
&examples_to_run, &examples_to_run,
&arguments.sizearguments, &args.sizearguments,
)?; )?;
} }
Commands::Qemu(args) | Commands::Run(args) => { Commands::Qemu(args) | Commands::Run(args) => {
@ -403,6 +495,10 @@ fn main() -> anyhow::Result<()> {
info!("Running cargo doc on backend: {backend:?}"); info!("Running cargo doc on backend: {backend:?}");
cargo_doc(&cargologlevel, backend)?; cargo_doc(&cargologlevel, backend)?;
} }
Commands::Test(args) => {
info!("Running cargo test on backend: {backend:?}");
cargo_test(&args, backend)?;
}
Commands::Book => { Commands::Book => {
info!("Running mdbook build"); info!("Running mdbook build");
cargo_book(&cargologlevel)?; cargo_book(&cargologlevel)?;
@ -415,30 +511,22 @@ fn main() -> anyhow::Result<()> {
fn cargo( fn cargo(
operation: BuildOrCheck, operation: BuildOrCheck,
cargoarg: &Option<&str>, cargoarg: &Option<&str>,
package: &Package, package: &PackageOpt,
backend: Backends, backend: Backends,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
// rtic crate has features which needs special handling let features = package_feature_extractor(package, backend);
let rtic_features = &format!("{},{}", DEFAULT_FEATURES, backend.to_rtic_feature());
let features: Option<&str>;
let packages = package_filter(package);
features = if packages.contains(&"rtic".to_owned()) {
Some(&rtic_features)
} else {
None
};
let command = match operation { let command = match operation {
BuildOrCheck::Check => CargoCommand::Check { BuildOrCheck::Check => CargoCommand::Check {
cargoarg, cargoarg,
package: packages, package: package.package,
target: backend.to_target(), target: backend.to_target(),
features, features,
mode: BuildMode::Release, mode: BuildMode::Release,
}, },
BuildOrCheck::Build => CargoCommand::Build { BuildOrCheck::Build => CargoCommand::Build {
cargoarg, cargoarg,
package: packages, package: package.package,
target: backend.to_target(), target: backend.to_target(),
features, features,
mode: BuildMode::Release, mode: BuildMode::Release,
@ -454,10 +542,13 @@ fn cargo_example(
backend: Backends, backend: Backends,
examples: &[String], examples: &[String],
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let s = format!("{},{}", DEFAULT_FEATURES, backend.to_rtic_feature());
let features: Option<&str> = Some(&s);
examples.into_par_iter().for_each(|example| { examples.into_par_iter().for_each(|example| {
let features = Some(format!(
"{},{}",
DEFAULT_FEATURES,
backend.to_rtic_feature()
));
let command = match operation { let command = match operation {
BuildOrCheck::Check => CargoCommand::ExampleCheck { BuildOrCheck::Check => CargoCommand::ExampleCheck {
cargoarg, cargoarg,
@ -485,47 +576,31 @@ fn cargo_example(
fn cargo_clippy( fn cargo_clippy(
cargoarg: &Option<&str>, cargoarg: &Option<&str>,
package: &Package, package: &PackageOpt,
backend: Backends, backend: Backends,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let packages_to_check = package_filter(package); let features = package_feature_extractor(package, backend);
if packages_to_check.contains(&"rtic".to_owned()) {
// rtic crate has features which needs special handling
let s = format!("{},{}", DEFAULT_FEATURES, backend.to_rtic_feature());
let features: Option<&str> = Some(&s);
command_parser( command_parser(
&CargoCommand::Clippy { &CargoCommand::Clippy {
cargoarg, cargoarg,
package: package_filter(package), package: package.package,
target: backend.to_target(), target: backend.to_target(),
features, features,
}, },
false, false,
)?; )?;
} else {
command_parser(
&CargoCommand::Clippy {
cargoarg,
package: package_filter(package),
target: backend.to_target(),
features: None,
},
false,
)?;
}
Ok(()) Ok(())
} }
fn cargo_format( fn cargo_format(
cargoarg: &Option<&str>, cargoarg: &Option<&str>,
package: &Package, package: &PackageOpt,
check_only: bool, check_only: bool,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
command_parser( command_parser(
&CargoCommand::Format { &CargoCommand::Format {
cargoarg, cargoarg,
package: package_filter(package), package: package.package,
check_only, check_only,
}, },
false, false,
@ -534,13 +609,55 @@ fn cargo_format(
} }
fn cargo_doc(cargoarg: &Option<&str>, backend: Backends) -> anyhow::Result<()> { fn cargo_doc(cargoarg: &Option<&str>, backend: Backends) -> anyhow::Result<()> {
let s = format!("{}", backend.to_rtic_feature()); let features = Some(format!(
let features: Option<&str> = Some(&s); "{},{}",
DEFAULT_FEATURES,
backend.to_rtic_feature()
));
command_parser(&CargoCommand::Doc { cargoarg, features }, false)?; command_parser(&CargoCommand::Doc { cargoarg, features }, false)?;
Ok(()) Ok(())
} }
fn cargo_test(package: &PackageOpt, backend: Backends) -> anyhow::Result<()> {
if let Some(package) = package.package {
let cmd = match package {
Package::Rtic => TestMetadata::match_package(package, backend),
Package::RticArbiter => TestMetadata::match_package(package, backend),
Package::RticChannel => TestMetadata::match_package(package, backend),
Package::RticCommon => TestMetadata::match_package(package, backend),
Package::RticMacros => TestMetadata::match_package(package, backend),
Package::RticMonotonics => TestMetadata::match_package(package, backend),
Package::RticTime => TestMetadata::match_package(package, backend),
};
command_parser(&cmd, false)?;
} else {
// Iterate over all workspace packages
for package in [
Package::Rtic,
Package::RticArbiter,
Package::RticChannel,
Package::RticCommon,
Package::RticMacros,
Package::RticMonotonics,
Package::RticTime,
] {
let mut error_messages = vec![];
let cmd = &TestMetadata::match_package(package, backend);
if let Err(err) = command_parser(&cmd, false) {
error_messages.push(err);
}
if !error_messages.is_empty() {
for err in error_messages {
error!("{err}");
}
}
}
}
Ok(())
}
fn cargo_book(cargoarg: &Option<&str>) -> anyhow::Result<()> { fn cargo_book(cargoarg: &Option<&str>) -> anyhow::Result<()> {
command_parser( command_parser(
&CargoCommand::Book { &CargoCommand::Book {
@ -557,15 +674,16 @@ fn run_test(
examples: &[String], examples: &[String],
overwrite: bool, overwrite: bool,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let s = format!("{},{}", DEFAULT_FEATURES, backend.to_rtic_feature());
let features: Option<&str> = Some(&s);
examples.into_par_iter().for_each(|example| { examples.into_par_iter().for_each(|example| {
let cmd = CargoCommand::ExampleBuild { let cmd = CargoCommand::ExampleBuild {
cargoarg: &Some("--quiet"), cargoarg: &Some("--quiet"),
example, example,
target: backend.to_target(), target: backend.to_target(),
features, features: Some(format!(
"{},{}",
DEFAULT_FEATURES,
backend.to_rtic_feature()
)),
mode: BuildMode::Release, mode: BuildMode::Release,
}; };
if let Err(err) = command_parser(&cmd, false) { if let Err(err) = command_parser(&cmd, false) {
@ -576,7 +694,11 @@ fn run_test(
cargoarg, cargoarg,
example, example,
target: backend.to_target(), target: backend.to_target(),
features, features: Some(format!(
"{},{}",
DEFAULT_FEATURES,
backend.to_rtic_feature()
)),
mode: BuildMode::Release, mode: BuildMode::Release,
}; };
@ -594,16 +716,17 @@ fn build_and_check_size(
examples: &[String], examples: &[String],
size_arguments: &Option<Sizearguments>, size_arguments: &Option<Sizearguments>,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let s = format!("{},{}", DEFAULT_FEATURES, backend.to_rtic_feature());
let features: Option<&str> = Some(&s);
examples.into_par_iter().for_each(|example| { examples.into_par_iter().for_each(|example| {
// Make sure the requested example(s) are built // Make sure the requested example(s) are built
let cmd = CargoCommand::ExampleBuild { let cmd = CargoCommand::ExampleBuild {
cargoarg: &Some("--quiet"), cargoarg: &Some("--quiet"),
example, example,
target: backend.to_target(), target: backend.to_target(),
features, features: Some(format!(
"{},{}",
DEFAULT_FEATURES,
backend.to_rtic_feature()
)),
mode: BuildMode::Release, mode: BuildMode::Release,
}; };
if let Err(err) = command_parser(&cmd, false) { if let Err(err) = command_parser(&cmd, false) {
@ -614,7 +737,11 @@ fn build_and_check_size(
cargoarg, cargoarg,
example, example,
target: backend.to_target(), target: backend.to_target(),
features, features: Some(format!(
"{},{}",
DEFAULT_FEATURES,
backend.to_rtic_feature()
)),
mode: BuildMode::Release, mode: BuildMode::Release,
arguments: size_arguments.clone(), arguments: size_arguments.clone(),
}; };
@ -626,38 +753,27 @@ fn build_and_check_size(
Ok(()) Ok(())
} }
fn package_filter(package: &Package) -> Vec<String> { /// Get the features needed given the selected package
// TODO Parse Cargo.toml workspace definition instead? ///
let packages: Vec<String> = [ /// Without package specified the features for RTIC are required
"rtic".to_owned(), /// With only a single package which is not RTIC, no special
"rtic-arbiter".to_owned(), /// features are needed
"rtic-channel".to_owned(), fn package_feature_extractor(package: &PackageOpt, backend: Backends) -> Option<String> {
"rtic-common".to_owned(), let default_features = Some(format!(
"rtic-macros".to_owned(), "{},{}",
"rtic-monotonics".to_owned(), DEFAULT_FEATURES,
"rtic-time".to_owned(), backend.to_rtic_feature()
] ));
.to_vec(); if let Some(package) = package.package {
let package_selected;
if let Some(package) = package.package.clone() {
if packages.contains(&package) {
debug!("\nTesting package: {package}"); debug!("\nTesting package: {package}");
// If we managed to filter, set the packages to test to only this one match package {
package_selected = vec![package] Package::Rtic => default_features,
} else { Package::RticMacros => Some(backend.to_rtic_macros_feature().to_owned()),
error!( _ => None,
"\nThe package you specified is not available. Available packages are:\
\n{packages:#?}\n\
By default all packages are tested.",
);
process::exit(exitcode::USAGE);
} }
} else { } else {
package_selected = packages; default_features
} }
package_selected
} }
// run example binary `example` // run example binary `example`
@ -704,6 +820,7 @@ fn command_parser(command: &CargoCommand, overwrite: bool) -> anyhow::Result<()>
| CargoCommand::Build { .. } | CargoCommand::Build { .. }
| CargoCommand::Clippy { .. } | CargoCommand::Clippy { .. }
| CargoCommand::Doc { .. } | CargoCommand::Doc { .. }
| CargoCommand::Test { .. }
| CargoCommand::Book { .. } | CargoCommand::Book { .. }
| CargoCommand::ExampleSize { .. } => { | CargoCommand::ExampleSize { .. } => {
let cargo_result = run_command(command)?; let cargo_result = run_command(command)?;