Skip to content

Commit 8be175e

Browse files
committed
Auto merge of #4592 - ehuss:check_test, r=alexcrichton
Add unit test checking to `cargo check` This is an extension of PR #4039, fixing #3431, #4003, #4059, #4330. The fixes for #4059 can potentially be separated into a separate PR, though there may be some overlap. The general gist of the changes: - Add `--profile test` flag to `cargo check` that will enable checking of unit tests. - `--tests` will implicitly enable checking of unit tests within the lib (checks the same targets as `cargo test`). This affects the `check`, `test`, and `build` commands. - `--benches` behaves similarly by using the same targets as `cargo bench`. - Fix erroneously linking tests when run with `--test`. There is one thing I did not do because I wanted more feedback on what others think the expected behavior should be. What should the behavior of `--all-targets` be? This patch does not (yet) make any changes to its behavior. My initial thinking is that it should *add* a target of `--lib --bins --profile test`, but that essentially means the lib and bin targets will be checked twice (and thus any errors/warnings outside of `#[cfg(test)]` will appear twice, which may be confusing, and generally take twice as long to run). I can add that, but I think it would require adding a new `All` variant to `CompileFilter` so that the code in `generate_targets` can detect this scenario. I wanted feedback before making a more extensive change like that. The downside of not adding it is that `--all-targets` will ignore unit tests (if you don't specify `--profile test`). Summary of the profiles used with this patch: Command | Lib | Bin foo | Test t1 | Example e1 | Bench b1 | ------- | --- | ------- | ------- | ---------- | -------- | `check` | check | check | - | - | - | `check --profile test` | check_test† | check_test† | - | - | - | `check --lib` | check | - | - | - | - | `check --lib --profile test` | check_test† | - | - | - | - | `check --bin foo` | check | check | - | - | - | `check -–bin foo –profile test` | check_test† | check_test† | - | - | - | `check --bins` | check | check | - | - | - | `check --test t1` | check | check | check_test | - | - | `check --tests` | check, check_test† | check, check_test† | check_test | check†, check_test† | - | `check --all-targets` | check, check_test† | check, check_test† | check_test | check, check_test† | check_test | † = different behavior from today
2 parents 37c1b90 + efc0dd1 commit 8be175e

File tree

13 files changed

+339
-24
lines changed

13 files changed

+339
-24
lines changed

src/bin/check.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::env;
22

33
use cargo::core::Workspace;
44
use cargo::ops::{self, CompileOptions, MessageFormat, Packages};
5-
use cargo::util::{CliResult, Config};
5+
use cargo::util::{CliResult, CliError, Config};
66
use cargo::util::important_paths::find_root_manifest_for_wd;
77

88
pub const USAGE: &'static str = "
@@ -28,6 +28,7 @@ Options:
2828
--benches Check all benches
2929
--all-targets Check all targets (lib and bin targets by default)
3030
--release Check artifacts in release mode, with optimizations
31+
--profile PROFILE Profile to build the selected target for
3132
--features FEATURES Space-separated list of features to also check
3233
--all-features Check all available features
3334
--no-default-features Do not check the `default` feature
@@ -53,6 +54,9 @@ Note that `--exclude` has to be specified in conjunction with the `--all` flag.
5354
Compilation can be configured via the use of profiles which are configured in
5455
the manifest. The default profile for this command is `dev`, but passing
5556
the --release flag will use the `release` profile instead.
57+
58+
The `--profile test` flag can be used to check unit tests with the
59+
`#[cfg(test)]` attribute.
5660
";
5761

5862
#[derive(Deserialize)]
@@ -83,6 +87,7 @@ pub struct Options {
8387
flag_frozen: bool,
8488
flag_all: bool,
8589
flag_exclude: Vec<String>,
90+
flag_profile: Option<String>,
8691
#[serde(rename = "flag_Z")]
8792
flag_z: Vec<String>,
8893
}
@@ -106,6 +111,16 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
106111
&options.flag_exclude,
107112
&options.flag_package)?;
108113

114+
let test = match options.flag_profile.as_ref().map(|t| &t[..]) {
115+
Some("test") => true,
116+
None => false,
117+
Some(profile) => {
118+
let err = format!("unknown profile: `{}`, only `test` is currently supported",
119+
profile).into();
120+
return Err(CliError::new(err, 101))
121+
}
122+
};
123+
109124
let opts = CompileOptions {
110125
config: config,
111126
jobs: options.flag_jobs,
@@ -114,7 +129,7 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
114129
all_features: options.flag_all_features,
115130
no_default_features: options.flag_no_default_features,
116131
spec: spec,
117-
mode: ops::CompileMode::Check,
132+
mode: ops::CompileMode::Check{test:test},
118133
release: options.flag_release,
119134
filter: ops::CompileFilter::new(options.flag_lib,
120135
&options.flag_bin, options.flag_bins,

src/bin/rustc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
102102
Some("dev") | None => CompileMode::Build,
103103
Some("test") => CompileMode::Test,
104104
Some("bench") => CompileMode::Bench,
105-
Some("check") => CompileMode::Check,
105+
Some("check") => CompileMode::Check {test: false},
106106
Some(mode) => {
107107
let err = format!("unknown profile: `{}`, use dev,
108108
test, or bench", mode).into();

src/cargo/core/manifest.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ pub struct Profiles {
189189
pub doc: Profile,
190190
pub custom_build: Profile,
191191
pub check: Profile,
192+
pub check_test: Profile,
192193
pub doctest: Profile,
193194
}
194195

@@ -661,6 +662,14 @@ impl Profile {
661662
}
662663
}
663664

665+
pub fn default_check_test() -> Profile {
666+
Profile {
667+
check: true,
668+
test: true,
669+
..Profile::default_dev()
670+
}
671+
}
672+
664673
pub fn default_doctest() -> Profile {
665674
Profile {
666675
doc: true,

src/cargo/core/workspace.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ impl<'cfg> Workspace<'cfg> {
545545
doc: Profile::default_doc(),
546546
custom_build: Profile::default_custom_build(),
547547
check: Profile::default_check(),
548+
check_test: Profile::default_check_test(),
548549
doctest: Profile::default_doctest(),
549550
};
550551

src/cargo/ops/cargo_clean.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ pub fn clean(ws: &Workspace, opts: &CleanOptions) -> CargoResult<()> {
5454
let Profiles {
5555
ref release, ref dev, ref test, ref bench, ref doc,
5656
ref custom_build, ref test_deps, ref bench_deps, ref check,
57-
ref doctest,
57+
ref check_test, ref doctest,
5858
} = *profiles;
5959
let profiles = [release, dev, test, bench, doc, custom_build,
60-
test_deps, bench_deps, check, doctest];
60+
test_deps, bench_deps, check, check_test, doctest];
6161
for profile in profiles.iter() {
6262
units.push(Unit {
6363
pkg,

src/cargo/ops/cargo_compile.rs

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ impl<'a> CompileOptions<'a> {
9292
pub enum CompileMode {
9393
Test,
9494
Build,
95-
Check,
95+
Check { test: bool },
9696
Bench,
9797
Doc { deps: bool },
9898
Doctest,
@@ -478,7 +478,7 @@ fn generate_auto_targets<'a>(mode: CompileMode, targets: &'a [Target],
478478
}
479479
base
480480
}
481-
CompileMode::Build | CompileMode::Check => {
481+
CompileMode::Build | CompileMode::Check{..} => {
482482
targets.iter().filter(|t| {
483483
t.is_bin() || t.is_lib()
484484
}).map(|t| BuildProposal {
@@ -606,11 +606,28 @@ fn generate_targets<'a>(pkg: &'a Package,
606606
CompileMode::Test => test,
607607
CompileMode::Bench => &profiles.bench,
608608
CompileMode::Build => build,
609-
CompileMode::Check => &profiles.check,
609+
CompileMode::Check {test: false} => &profiles.check,
610+
CompileMode::Check {test: true} => &profiles.check_test,
610611
CompileMode::Doc { .. } => &profiles.doc,
611612
CompileMode::Doctest => &profiles.doctest,
612613
};
613614

615+
let test_profile = if profile.check {
616+
&profiles.check_test
617+
} else if mode == CompileMode::Build {
618+
test
619+
} else {
620+
profile
621+
};
622+
623+
let bench_profile = if profile.check {
624+
&profiles.check_test
625+
} else if mode == CompileMode::Build {
626+
&profiles.bench
627+
} else {
628+
profile
629+
};
630+
614631
let targets = match *filter {
615632
CompileFilter::Default { required_features_filterable } => {
616633
let deps = if release {
@@ -634,15 +651,26 @@ fn generate_targets<'a>(pkg: &'a Package,
634651
bail!("no library targets found")
635652
}
636653
}
637-
638654
targets.append(&mut propose_indicated_targets(
639655
pkg, bins, "bin", Target::is_bin, profile)?);
640656
targets.append(&mut propose_indicated_targets(
641-
pkg, examples, "example", Target::is_example, build)?);
657+
pkg, examples, "example", Target::is_example, profile)?);
658+
// If --tests was specified, add all targets that would be
659+
// generated by `cargo test`.
660+
let test_filter = match tests {
661+
FilterRule::All => Target::tested,
662+
FilterRule::Just(_) => Target::is_test
663+
};
642664
targets.append(&mut propose_indicated_targets(
643-
pkg, tests, "test", Target::is_test, test)?);
665+
pkg, tests, "test", test_filter, test_profile)?);
666+
// If --benches was specified, add all targets that would be
667+
// generated by `cargo bench`.
668+
let bench_filter = match benches {
669+
FilterRule::All => Target::benched,
670+
FilterRule::Just(_) => Target::is_bench
671+
};
644672
targets.append(&mut propose_indicated_targets(
645-
pkg, benches, "bench", Target::is_bench, &profiles.bench)?);
673+
pkg, benches, "bench", bench_filter, bench_profile)?);
646674
targets
647675
}
648676
};

src/cargo/ops/cargo_rustc/context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
876876
Unit {
877877
pkg: unit.pkg,
878878
target: t,
879-
profile: self.lib_profile(),
879+
profile: self.lib_or_check_profile(unit, t),
880880
kind: unit.kind.for_target(t),
881881
}
882882
}));

src/cargo/util/toml/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,6 +1059,8 @@ fn build_profiles(profiles: &Option<TomlProfiles>) -> Profiles {
10591059
custom_build: Profile::default_custom_build(),
10601060
check: merge(Profile::default_check(),
10611061
profiles.and_then(|p| p.dev.as_ref())),
1062+
check_test: merge(Profile::default_check_test(),
1063+
profiles.and_then(|p| p.dev.as_ref())),
10621064
doctest: Profile::default_doctest(),
10631065
};
10641066
// The test/bench targets cannot have panic=abort because they'll all get

tests/bench.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ fn bench_bench_implicit() {
8181
.with_stderr(format!("\
8282
[COMPILING] foo v0.0.1 ({dir})
8383
[FINISHED] release [optimized] target(s) in [..]
84+
[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]
8485
[RUNNING] target[/]release[/]deps[/]mybench-[..][EXE]
8586
", dir = p.url()))
8687
.with_stdout_contains("test run2 ... bench: [..]"));
@@ -1323,7 +1324,7 @@ fn bench_virtual_manifest_all_implied() {
13231324
.build();
13241325

13251326
// The order in which foo and bar are built is not guaranteed
1326-
1327+
13271328
assert_that(p.cargo("bench"),
13281329
execs().with_status(0)
13291330
.with_stderr_contains("\

tests/build.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3887,3 +3887,59 @@ fn uplift_dsym_of_bin_on_mac() {
38873887
assert_that(&p.bin("c.dSYM"), is_not(existing_dir()));
38883888
assert_that(&p.bin("d.dSYM"), is_not(existing_dir()));
38893889
}
3890+
3891+
// Make sure that `cargo build` chooses the correct profile for building
3892+
// targets based on filters (assuming --profile is not specified).
3893+
#[test]
3894+
fn build_filter_infer_profile() {
3895+
let p = project("foo")
3896+
.file("Cargo.toml", r#"
3897+
[package]
3898+
name = "foo"
3899+
version = "0.1.0"
3900+
authors = []
3901+
"#)
3902+
.file("src/lib.rs", "")
3903+
.file("src/main.rs", "fn main() {}")
3904+
.file("tests/t1.rs", "")
3905+
.file("benches/b1.rs", "")
3906+
.file("examples/ex1.rs", "fn main() {}")
3907+
.build();
3908+
3909+
assert_that(p.cargo("build").arg("-v"),
3910+
execs().with_status(0)
3911+
.with_stderr_contains("\
3912+
[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
3913+
--emit=dep-info,link[..]")
3914+
.with_stderr_contains("\
3915+
[RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin \
3916+
--emit=dep-info,link[..]")
3917+
);
3918+
3919+
p.root().join("target").rm_rf();
3920+
assert_that(p.cargo("build").arg("-v").arg("--test=t1"),
3921+
execs().with_status(0)
3922+
.with_stderr_contains("\
3923+
[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
3924+
--emit=dep-info,link[..]")
3925+
.with_stderr_contains("\
3926+
[RUNNING] `rustc --crate-name t1 tests[/]t1.rs --emit=dep-info,link[..]")
3927+
.with_stderr_contains("\
3928+
[RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin \
3929+
--emit=dep-info,link[..]")
3930+
);
3931+
3932+
p.root().join("target").rm_rf();
3933+
assert_that(p.cargo("build").arg("-v").arg("--bench=b1"),
3934+
execs().with_status(0)
3935+
.with_stderr_contains("\
3936+
[RUNNING] `rustc --crate-name foo src[/]lib.rs --crate-type lib \
3937+
--emit=dep-info,link[..]")
3938+
.with_stderr_contains("\
3939+
[RUNNING] `rustc --crate-name b1 benches[/]b1.rs --emit=dep-info,link \
3940+
-C opt-level=3[..]")
3941+
.with_stderr_contains("\
3942+
[RUNNING] `rustc --crate-name foo src[/]main.rs --crate-type bin \
3943+
--emit=dep-info,link[..]")
3944+
);
3945+
}

tests/cargotest/install.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub fn cargo_home() -> PathBuf {
1212

1313
pub struct InstalledExe(pub &'static str);
1414

15-
fn exe(name: &str) -> String {
15+
pub fn exe(name: &str) -> String {
1616
if cfg!(windows) {format!("{}.exe", name)} else {name.to_string()}
1717
}
1818

0 commit comments

Comments
 (0)