Skip to content

Commit 235712f

Browse files
committed
Add unit test checking to cargo check
- 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. - Don't implicitly compile binaries when using just `--test` filters. - Fix erroneously linking tests when run with `--test`. Fixes #3431, #4003, #4059, #4330.
1 parent c1dd25a commit 235712f

File tree

10 files changed

+238
-23
lines changed

10 files changed

+238
-23
lines changed

src/bin/check.rs

Lines changed: 20 additions & 4 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,17 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
106111
&options.flag_exclude,
107112
&options.flag_package)?;
108113

114+
let test = options.flag_tests ||
115+
match options.flag_profile.as_ref().map(|t| &t[..]) {
116+
Some("test") => true,
117+
None => false,
118+
Some(profile) => {
119+
let err = format!("unknown profile: `{}`, only `test` is currently supported",
120+
profile).into();
121+
return Err(CliError::new(err, 101))
122+
}
123+
};
124+
109125
let opts = CompileOptions {
110126
config: config,
111127
jobs: options.flag_jobs,
@@ -114,10 +130,10 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
114130
all_features: options.flag_all_features,
115131
no_default_features: options.flag_no_default_features,
116132
spec: spec,
117-
mode: ops::CompileMode::Check,
133+
mode: ops::CompileMode::Check{test:test},
118134
release: options.flag_release,
119-
filter: ops::CompileFilter::new(options.flag_lib,
120-
&options.flag_bin, options.flag_bins,
135+
filter: ops::CompileFilter::new(options.flag_lib || options.flag_tests,
136+
&options.flag_bin, options.flag_bins || options.flag_tests,
121137
&options.flag_test, options.flag_tests,
122138
&options.flag_example, options.flag_examples,
123139
&options.flag_bench, options.flag_benches,

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: 13 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 {
@@ -603,11 +603,18 @@ fn generate_targets<'a>(pkg: &'a Package,
603603
CompileMode::Test => test,
604604
CompileMode::Bench => &profiles.bench,
605605
CompileMode::Build => build,
606-
CompileMode::Check => &profiles.check,
606+
CompileMode::Check {test: false} => &profiles.check,
607+
CompileMode::Check {test: true} => &profiles.check_test,
607608
CompileMode::Doc { .. } => &profiles.doc,
608609
CompileMode::Doctest => &profiles.doctest,
609610
};
610611

612+
let test_profile = if profile.check {
613+
&profiles.check_test
614+
} else {
615+
profile
616+
};
617+
611618
let targets = match *filter {
612619
CompileFilter::Default { required_features_filterable } => {
613620
let deps = if release {
@@ -631,15 +638,14 @@ fn generate_targets<'a>(pkg: &'a Package,
631638
bail!("no library targets found")
632639
}
633640
}
634-
635641
targets.append(&mut propose_indicated_targets(
636642
pkg, bins, "bin", Target::is_bin, profile)?);
637643
targets.append(&mut propose_indicated_targets(
638-
pkg, examples, "example", Target::is_example, build)?);
644+
pkg, examples, "example", Target::is_example, profile)?);
639645
targets.append(&mut propose_indicated_targets(
640-
pkg, tests, "test", Target::is_test, test)?);
646+
pkg, tests, "test", Target::is_test, test_profile)?);
641647
targets.append(&mut propose_indicated_targets(
642-
pkg, benches, "bench", Target::is_bench, &profiles.bench)?);
648+
pkg, benches, "bench", Target::is_bench, test_profile)?);
643649
targets
644650
}
645651
};

src/cargo/ops/cargo_rustc/context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
862862
ret.extend(self.maybe_lib(unit));
863863

864864
// Integration tests/benchmarks require binaries to be built
865-
if unit.profile.test &&
865+
if unit.profile.test && !unit.profile.check &&
866866
(unit.target.is_test() || unit.target.is_bench()) {
867867
ret.extend(unit.pkg.targets().iter().filter(|t| {
868868
let no_required_features = Vec::new();

src/cargo/util/toml/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,6 +1041,8 @@ fn build_profiles(profiles: &Option<TomlProfiles>) -> Profiles {
10411041
custom_build: Profile::default_custom_build(),
10421042
check: merge(Profile::default_check(),
10431043
profiles.and_then(|p| p.dev.as_ref())),
1044+
check_test: merge(Profile::default_check_test(),
1045+
profiles.and_then(|p| p.dev.as_ref())),
10441046
doctest: Profile::default_doctest(),
10451047
};
10461048
// The test/bench targets cannot have panic=abort because they'll all get

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)