From c5119aae835060dff0a1932e247336609ee4709a Mon Sep 17 00:00:00 2001 From: Arthur Pastel Date: Fri, 3 Mar 2023 12:56:34 +0100 Subject: [PATCH] feat: support --features build flag --- crates/cargo-codspeed/src/app.rs | 16 +++++++- crates/cargo-codspeed/src/build.rs | 24 +++++++++--- .../tests/features.in/.gitignore | 2 + .../tests/features.in/Cargo.toml | 20 ++++++++++ .../tests/features.in/benches/bench.rs | 18 +++++++++ crates/cargo-codspeed/tests/features.rs | 39 +++++++++++++++++++ crates/cargo-codspeed/tests/helpers.rs | 3 +- 7 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 crates/cargo-codspeed/tests/features.in/.gitignore create mode 100644 crates/cargo-codspeed/tests/features.in/Cargo.toml create mode 100644 crates/cargo-codspeed/tests/features.in/benches/bench.rs create mode 100644 crates/cargo-codspeed/tests/features.rs diff --git a/crates/cargo-codspeed/src/app.rs b/crates/cargo-codspeed/src/app.rs index 9f1c2076..3f3cf0f5 100644 --- a/crates/cargo-codspeed/src/app.rs +++ b/crates/cargo-codspeed/src/app.rs @@ -25,6 +25,9 @@ enum Commands { /// Package to build benchmarks for (if using a workspace) #[arg(short, long)] package: Option, + /// Space or comma separated list of features to activate + #[arg(short = 'F', long)] + features: Option, }, /// Run the previously built benchmarks Run { @@ -50,7 +53,18 @@ pub fn run(args: impl Iterator) -> Result<()> { let workspace = Workspace::new(&manifest_path, &cargo_config)?; let res = match cli.command { - Commands::Build { benches, package } => build_benches(&workspace, benches, package), + Commands::Build { + benches, + package, + features, + } => { + let features = features.map(|f| { + f.split(|c| c == ' ' || c == ',') + .map(|s| s.to_string()) + .collect_vec() + }); + build_benches(&workspace, benches, package, features) + } Commands::Run { benches, package } => run_benches(&workspace, benches, package), }; diff --git a/crates/cargo-codspeed/src/build.rs b/crates/cargo-codspeed/src/build.rs index 94aa472c..ca319e64 100644 --- a/crates/cargo-codspeed/src/build.rs +++ b/crates/cargo-codspeed/src/build.rs @@ -3,19 +3,32 @@ use crate::{ prelude::*, }; -use std::fs::create_dir_all; +use std::{collections::BTreeSet, fs::create_dir_all, rc::Rc}; use cargo::{ - core::{Package, Workspace}, + core::{FeatureValue, Package, Workspace}, ops::{CompileFilter, CompileOptions, Packages}, - util::command_prelude::CompileMode, + util::{command_prelude::CompileMode, interning::InternedString}, Config, }; use termcolor::Color; -fn get_compile_options(config: &Config, package: &Package, bench: &str) -> Result { +fn get_compile_options( + config: &Config, + features: &Option>, + package: &Package, + bench: &str, +) -> Result { let mut compile_opts = CompileOptions::new(config, CompileMode::Build)?; compile_opts.spec = Packages::Packages(vec![package.name().to_string()]); + if let Some(features) = features { + compile_opts.cli_features.features = Rc::new( + features + .iter() + .map(|s| FeatureValue::Feature(InternedString::new(s.as_str()))) + .collect::>(), + ); + } compile_opts.build_config.requested_profile = "release".into(); compile_opts.filter = CompileFilter::from_raw_arguments( false, @@ -36,6 +49,7 @@ pub fn build_benches( ws: &Workspace, selected_benches: Option>, package_name: Option, + features: Option>, ) -> Result<()> { let package = match package_name.as_ref() { Some(package_name) => ws @@ -82,7 +96,7 @@ pub fn build_benches( ws.config() .shell() .status_with_color("Building", bench.name(), Color::Yellow)?; - let compile_opts = get_compile_options(config, package, bench.name())?; + let compile_opts = get_compile_options(config, &features, package, bench.name())?; let result = cargo::ops::compile(ws, &compile_opts)?; let built_targets = result .tests diff --git a/crates/cargo-codspeed/tests/features.in/.gitignore b/crates/cargo-codspeed/tests/features.in/.gitignore new file mode 100644 index 00000000..1e7caa9e --- /dev/null +++ b/crates/cargo-codspeed/tests/features.in/.gitignore @@ -0,0 +1,2 @@ +Cargo.lock +target/ diff --git a/crates/cargo-codspeed/tests/features.in/Cargo.toml b/crates/cargo-codspeed/tests/features.in/Cargo.toml new file mode 100644 index 00000000..7cd04a89 --- /dev/null +++ b/crates/cargo-codspeed/tests/features.in/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "features" +version = "0.0.0" +edition = "2021" +publish = false + +[dependencies] +bencher = "0.1.5" +codspeed = { path = "../../../codspeed" } +codspeed-bencher-compat = { path = "../../../bencher_compat" } + +[features] +sample_feature = [] + +[workspace] + + +[[bench]] +name = "bench" +harness = false diff --git a/crates/cargo-codspeed/tests/features.in/benches/bench.rs b/crates/cargo-codspeed/tests/features.in/benches/bench.rs new file mode 100644 index 00000000..ada6bce7 --- /dev/null +++ b/crates/cargo-codspeed/tests/features.in/benches/bench.rs @@ -0,0 +1,18 @@ +use codspeed::codspeed::black_box; +use codspeed_bencher_compat::{benchmark_group, benchmark_main, Bencher}; + +#[cfg(not(feature = "sample_feature"))] +pub fn without_feature(bench: &mut Bencher) { + bench.iter(|| (0..100).fold(0, |x, y| black_box(x + y))) +} +#[cfg(not(feature = "sample_feature"))] +benchmark_group!(benches, without_feature); + +#[cfg(feature = "sample_feature")] +pub fn with_feature(bench: &mut Bencher) { + bench.iter(|| (0..100).fold(0, |x, y| black_box(x + y))) +} +#[cfg(feature = "sample_feature")] +benchmark_group!(benches, with_feature); + +benchmark_main!(benches); diff --git a/crates/cargo-codspeed/tests/features.rs b/crates/cargo-codspeed/tests/features.rs new file mode 100644 index 00000000..5ec857ca --- /dev/null +++ b/crates/cargo-codspeed/tests/features.rs @@ -0,0 +1,39 @@ +use predicates::{prelude::PredicateBooleanExt, str::contains}; + +mod helpers; +use helpers::*; + +const DIR: &str = "tests/features.in"; + +#[test] +fn test_without_feature() { + let dir = setup(DIR, Project::Features); + cargo_codspeed(&dir).arg("build").assert().success(); + cargo_codspeed(&dir) + .arg("run") + .assert() + .success() + .stderr(contains("Finished running 1 benchmark suite(s)")) + .stdout(contains("without_feature")) + .stdout(contains("with_feature").not()); + teardown(dir); +} + +#[test] +fn test_with_feature() { + let dir = setup(DIR, Project::Features); + cargo_codspeed(&dir) + .arg("build") + .arg("-F") + .arg("sample_feature") + .assert() + .success(); + cargo_codspeed(&dir) + .arg("run") + .assert() + .success() + .stderr(contains("Finished running 1 benchmark suite(s)")) + .stdout(contains("with_feature")) + .stdout(contains("without_feature").not()); + teardown(dir); +} diff --git a/crates/cargo-codspeed/tests/helpers.rs b/crates/cargo-codspeed/tests/helpers.rs index f47c0975..b68267b6 100644 --- a/crates/cargo-codspeed/tests/helpers.rs +++ b/crates/cargo-codspeed/tests/helpers.rs @@ -18,6 +18,7 @@ fn replace_in_file(path: &str, from: &str, to: &str) { #[allow(dead_code)] pub enum Project { Simple, + Features, Workspace, } @@ -35,7 +36,7 @@ pub fn setup(dir: &str, project: Project) -> String { let package_root = PathBuf::from_str(env!("CARGO_MANIFEST_DIR")).unwrap(); let workspace_root = package_root.parent().unwrap().parent().unwrap(); match project { - Project::Simple => { + Project::Simple | Project::Features => { replace_in_file( tmp_dir.join("Cargo.toml").to_str().unwrap(), "../../..",