Skip to content

Commit 58790d3

Browse files
committed
Auto merge of #10305 - weihanglo:issue-10268, r=alexcrichton
do not compile test for bins flagged as `test = false` ### What does this PR try to resolve? Fixes #10268 #6683 introduced a behavior that compiles all bin targets, but for bins with `test = false` they shouldn't be compiled with `--test` as testbins. ### How should we test and review this PR? In the first commit of this PR, I refines the test `test_filtered_excludes_compiling_examples` to reflect the current wrong behavior (test passed). The following two commits correct the behavior and the test accordingly. The last few commits encapsulate scattered target selection logic into functions on `CompileFilter`.
2 parents bb96b3a + 2f5b303 commit 58790d3

File tree

5 files changed

+115
-62
lines changed

5 files changed

+115
-62
lines changed

src/bin/cargo/commands/fix.rs

+4-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::command_prelude::*;
22

3-
use cargo::ops::{self, CompileFilter, FilterRule, LibRule};
3+
use cargo::ops;
44

55
pub fn cli() -> App {
66
subcommand("fix")
@@ -76,15 +76,9 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
7676
let mut opts =
7777
args.compile_options(config, mode, Some(&ws), ProfileChecking::LegacyTestOnly)?;
7878

79-
if let CompileFilter::Default { .. } = opts.filter {
80-
opts.filter = CompileFilter::Only {
81-
all_targets: true,
82-
lib: LibRule::Default,
83-
bins: FilterRule::All,
84-
examples: FilterRule::All,
85-
benches: FilterRule::All,
86-
tests: FilterRule::All,
87-
}
79+
if !opts.filter.is_specific() {
80+
// cargo fix with no target selection implies `--all-targets`.
81+
opts.filter = ops::CompileFilter::new_all_targets();
8882
}
8983

9084
ops::fix(

src/bin/cargo/commands/run.rs

+2-13
Original file line numberDiff line numberDiff line change
@@ -62,19 +62,8 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
6262
.iter()
6363
.filter_map(|pkg| pkg.manifest().default_run())
6464
.collect();
65-
if default_runs.len() == 1 {
66-
compile_opts.filter = CompileFilter::from_raw_arguments(
67-
false,
68-
vec![default_runs[0].to_owned()],
69-
false,
70-
vec![],
71-
false,
72-
vec![],
73-
false,
74-
vec![],
75-
false,
76-
false,
77-
);
65+
if let [bin] = &default_runs[..] {
66+
compile_opts.filter = CompileFilter::single_bin(bin.to_string());
7867
} else {
7968
// ops::run will take care of errors if len pkgs != 1.
8069
compile_opts.filter = CompileFilter::Default {

src/bin/cargo/commands/test.rs

+14-28
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::command_prelude::*;
22
use anyhow::Error;
3-
use cargo::ops::{self, CompileFilter, FilterRule, LibRule};
3+
use cargo::ops;
44

55
pub fn cli() -> App {
66
subcommand("test")
@@ -77,44 +77,30 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
7777

7878
// `TESTNAME` is actually an argument of the test binary, but it's
7979
// important, so we explicitly mention it and reconfigure.
80-
let test_name: Option<&str> = args.value_of("TESTNAME");
80+
let test_name = args.value_of("TESTNAME");
8181
let test_args = args.value_of("TESTNAME").into_iter();
8282
let test_args = test_args.chain(args.values_of("args").unwrap_or_default());
8383
let test_args = test_args.collect::<Vec<_>>();
8484

8585
let no_run = args.is_present("no-run");
8686
let doc = args.is_present("doc");
8787
if doc {
88-
if let CompileFilter::Only { .. } = compile_opts.filter {
89-
return Err(CliError::new(
90-
anyhow::format_err!("Can't mix --doc with other target selecting options"),
91-
101,
92-
));
88+
if compile_opts.filter.is_specific() {
89+
return Err(
90+
anyhow::format_err!("Can't mix --doc with other target selecting options").into(),
91+
);
9392
}
9493
if no_run {
95-
return Err(CliError::new(
96-
anyhow::format_err!("Can't skip running doc tests with --no-run"),
97-
101,
98-
));
94+
return Err(anyhow::format_err!("Can't skip running doc tests with --no-run").into());
9995
}
10096
compile_opts.build_config.mode = CompileMode::Doctest;
101-
compile_opts.filter = ops::CompileFilter::new(
102-
LibRule::True,
103-
FilterRule::none(),
104-
FilterRule::none(),
105-
FilterRule::none(),
106-
FilterRule::none(),
107-
);
108-
} else if test_name.is_some() {
109-
if let CompileFilter::Default { .. } = compile_opts.filter {
110-
compile_opts.filter = ops::CompileFilter::new(
111-
LibRule::Default, // compile the library, so the unit tests can be run filtered
112-
FilterRule::All, // compile the binaries, so the unit tests in binaries can be run filtered
113-
FilterRule::All, // compile the tests, so the integration tests can be run filtered
114-
FilterRule::none(), // specify --examples to unit test binaries filtered
115-
FilterRule::none(), // specify --benches to unit test benchmarks filtered
116-
); // also, specify --doc to run doc tests filtered
117-
}
97+
compile_opts.filter = ops::CompileFilter::lib_only();
98+
} else if test_name.is_some() && !compile_opts.filter.is_specific() {
99+
// If arg `TESTNAME` is provided, assumed that the user knows what
100+
// exactly they wants to test, so we use `all_test_targets` to
101+
// avoid compiling unnecessary targets such as examples, which are
102+
// included by the logic of default target filter.
103+
compile_opts.filter = ops::CompileFilter::all_test_targets();
118104
}
119105

120106
let ops = ops::TestOptions {

src/cargo/ops/cargo_compile.rs

+50-4
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,7 @@ impl FilterRule {
759759
}
760760

761761
impl CompileFilter {
762-
/// Construct a CompileFilter from raw command line arguments.
762+
/// Constructs a filter from raw command line arguments.
763763
pub fn from_raw_arguments(
764764
lib_only: bool,
765765
bins: Vec<String>,
@@ -788,7 +788,7 @@ impl CompileFilter {
788788
CompileFilter::new(rule_lib, rule_bins, rule_tsts, rule_exms, rule_bens)
789789
}
790790

791-
/// Construct a CompileFilter from underlying primitives.
791+
/// Constructs a filter from underlying primitives.
792792
pub fn new(
793793
rule_lib: LibRule,
794794
rule_bins: FilterRule,
@@ -817,6 +817,7 @@ impl CompileFilter {
817817
}
818818
}
819819

820+
/// Constructs a filter that includes all targets.
820821
pub fn new_all_targets() -> CompileFilter {
821822
CompileFilter::Only {
822823
all_targets: true,
@@ -828,6 +829,51 @@ impl CompileFilter {
828829
}
829830
}
830831

832+
/// Constructs a filter that includes all test targets.
833+
///
834+
/// Being different from the behavior of [`CompileFilter::Default`], this
835+
/// function only recongnizes test targets, which means cargo might compile
836+
/// all targets with `tested` flag on, whereas [`CompileFilter::Default`]
837+
/// may include additional example targets to ensure they can be compiled.
838+
///
839+
/// Note that the actual behavior is subject to `filter_default_targets`
840+
/// and `generate_targets` though.
841+
pub fn all_test_targets() -> Self {
842+
Self::Only {
843+
all_targets: false,
844+
lib: LibRule::Default,
845+
bins: FilterRule::none(),
846+
examples: FilterRule::none(),
847+
tests: FilterRule::All,
848+
benches: FilterRule::none(),
849+
}
850+
}
851+
852+
/// Constructs a filter that includes lib target only.
853+
pub fn lib_only() -> Self {
854+
Self::Only {
855+
all_targets: false,
856+
lib: LibRule::True,
857+
bins: FilterRule::none(),
858+
examples: FilterRule::none(),
859+
tests: FilterRule::none(),
860+
benches: FilterRule::none(),
861+
}
862+
}
863+
864+
/// Constructs a filter that includes the given binary. No more. No less.
865+
pub fn single_bin(bin: String) -> Self {
866+
Self::Only {
867+
all_targets: false,
868+
lib: LibRule::False,
869+
bins: FilterRule::new(vec![bin], false),
870+
examples: FilterRule::none(),
871+
tests: FilterRule::none(),
872+
benches: FilterRule::none(),
873+
}
874+
}
875+
876+
/// Indicates if Cargo needs to build any dev dependency.
831877
pub fn need_dev_deps(&self, mode: CompileMode) -> bool {
832878
match mode {
833879
CompileMode::Test | CompileMode::Doctest | CompileMode::Bench => true,
@@ -848,8 +894,8 @@ impl CompileFilter {
848894
}
849895
}
850896

851-
// this selects targets for "cargo run". for logic to select targets for
852-
// other subcommands, see generate_targets and filter_default_targets
897+
/// Selects targets for "cargo run". for logic to select targets for other
898+
/// subcommands, see `generate_targets` and `filter_default_targets`.
853899
pub fn target_run(&self, target: &Target) -> bool {
854900
match *self {
855901
CompileFilter::Default { .. } => true,

tests/testsuite/test.rs

+45-7
Original file line numberDiff line numberDiff line change
@@ -1606,32 +1606,70 @@ fn test_run_implicit_example_target() {
16061606
#[cargo_test]
16071607
fn test_filtered_excludes_compiling_examples() {
16081608
let p = project()
1609+
.file(
1610+
"Cargo.toml",
1611+
r#"
1612+
[package]
1613+
name = "foo"
1614+
version = "0.0.1"
1615+
authors = []
1616+
1617+
[[bin]]
1618+
name = "mybin"
1619+
test = false
1620+
"#,
1621+
)
16091622
.file(
16101623
"src/lib.rs",
1611-
"#[cfg(test)] mod tests { #[test] fn foo() { assert!(true); } }",
1624+
"#[cfg(test)] mod tests { #[test] fn test_in_lib() { } }",
1625+
)
1626+
.file(
1627+
"src/bin/mybin.rs",
1628+
"#[test] fn test_in_bin() { }
1629+
fn main() { panic!(\"Don't execute me!\"); }",
1630+
)
1631+
.file("tests/mytest.rs", "#[test] fn test_in_test() { }")
1632+
.file(
1633+
"benches/mybench.rs",
1634+
"#[test] fn test_in_bench() { assert!(false) }",
1635+
)
1636+
.file(
1637+
"examples/myexm1.rs",
1638+
"#[test] fn test_in_exm() { assert!(false) }
1639+
fn main() { panic!(\"Don't execute me!\"); }",
16121640
)
1613-
.file("examples/ex1.rs", "fn main() {}")
16141641
.build();
16151642

1616-
p.cargo("test -v foo")
1643+
p.cargo("test -v test_in_")
16171644
.with_stdout(
16181645
"
16191646
running 1 test
1620-
test tests::foo ... ok
1647+
test tests::test_in_lib ... ok
1648+
1649+
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out[..]
1650+
1651+
1652+
running 1 test
1653+
test test_in_test ... ok
16211654
16221655
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out[..]
16231656
16241657
",
16251658
)
1626-
.with_stderr(
1659+
.with_stderr_unordered(
16271660
"\
16281661
[COMPILING] foo v0.0.1 ([CWD])
1662+
[RUNNING] `rustc --crate-name foo src/lib.rs [..] --crate-type lib [..]`
16291663
[RUNNING] `rustc --crate-name foo src/lib.rs [..] --test [..]`
1664+
[RUNNING] `rustc --crate-name mybin src/bin/mybin.rs [..] --crate-type bin [..]`
1665+
[RUNNING] `rustc --crate-name mytest tests/mytest.rs [..] --test [..]`
16301666
[FINISHED] test [unoptimized + debuginfo] target(s) in [..]
1631-
[RUNNING] `[CWD]/target/debug/deps/foo-[..] foo`
1667+
[RUNNING] `[CWD]/target/debug/deps/foo-[..] test_in_`
1668+
[RUNNING] `[CWD]/target/debug/deps/mytest-[..] test_in_`
16321669
",
16331670
)
1634-
.with_stderr_does_not_contain("[RUNNING][..]rustc[..]ex1[..]")
1671+
.with_stderr_does_not_contain("[RUNNING][..]rustc[..]myexm1[..]")
1672+
.with_stderr_does_not_contain("[RUNNING][..]deps/mybin-[..] test_in_")
16351673
.run();
16361674
}
16371675

0 commit comments

Comments
 (0)