Skip to content

Commit fec03d3

Browse files
committed
Auto merge of #3221 - euclio:test-all, r=alexcrichton
Add `--all` flag to `cargo test` Work towards #2878. This flag allows a user to test all members of a workspace by using `cargo test --all`. The command is also supported when using a virtual workspace manifest.
2 parents 333a798 + addbb7e commit fec03d3

20 files changed

+260
-77
lines changed

src/bin/bench.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
8888
features: &options.flag_features,
8989
all_features: options.flag_all_features,
9090
no_default_features: options.flag_no_default_features,
91-
spec: &options.flag_package,
91+
spec: ops::Packages::Packages(&options.flag_package),
9292
release: true,
9393
mode: ops::CompileMode::Bench,
9494
filter: ops::CompileFilter::new(options.flag_lib,

src/bin/build.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
8484
features: &options.flag_features,
8585
all_features: options.flag_all_features,
8686
no_default_features: options.flag_no_default_features,
87-
spec: &options.flag_package,
87+
spec: ops::Packages::Packages(&options.flag_package),
8888
mode: ops::CompileMode::Build,
8989
release: options.flag_release,
9090
filter: ops::CompileFilter::new(options.flag_lib,

src/bin/doc.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use cargo::core::Workspace;
2-
use cargo::ops::{self, MessageFormat};
2+
use cargo::ops::{self, MessageFormat, Packages};
33
use cargo::util::{CliResult, Config};
44
use cargo::util::important_paths::{find_root_manifest_for_wd};
55

@@ -80,7 +80,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
8080
features: &options.flag_features,
8181
all_features: options.flag_all_features,
8282
no_default_features: options.flag_no_default_features,
83-
spec: &options.flag_package,
83+
spec: Packages::Packages(&options.flag_package),
8484
filter: ops::CompileFilter::new(options.flag_lib,
8585
&options.flag_bin,
8686
&empty,

src/bin/install.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
108108
features: &options.flag_features,
109109
all_features: options.flag_all_features,
110110
no_default_features: options.flag_no_default_features,
111-
spec: &[],
111+
spec: ops::Packages::Packages(&[]),
112112
mode: ops::CompileMode::Build,
113113
release: !options.flag_debug,
114114
filter: ops::CompileFilter::new(false, &options.flag_bin, &[],

src/bin/run.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use cargo::core::Workspace;
2-
use cargo::ops::{self, MessageFormat};
2+
use cargo::ops::{self, MessageFormat, Packages};
33
use cargo::util::{CliResult, CliError, Config, Human};
44
use cargo::util::important_paths::{find_root_manifest_for_wd};
55

@@ -81,7 +81,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
8181
features: &options.flag_features,
8282
all_features: options.flag_all_features,
8383
no_default_features: options.flag_no_default_features,
84-
spec: &[],
84+
spec: Packages::Packages(&[]),
8585
release: options.flag_release,
8686
mode: ops::CompileMode::Build,
8787
filter: if examples.is_empty() && bins.is_empty() {

src/bin/rustc.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::env;
22

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

@@ -95,14 +95,16 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
9595
}
9696
};
9797

98+
let spec = options.flag_package.map_or_else(Vec::new, |s| vec![s]);
99+
98100
let opts = CompileOptions {
99101
config: config,
100102
jobs: options.flag_jobs,
101103
target: options.flag_target.as_ref().map(|t| &t[..]),
102104
features: &options.flag_features,
103105
all_features: options.flag_all_features,
104106
no_default_features: options.flag_no_default_features,
105-
spec: &options.flag_package.map_or(Vec::new(), |s| vec![s]),
107+
spec: Packages::Packages(&spec),
106108
mode: mode,
107109
release: options.flag_release,
108110
filter: ops::CompileFilter::new(options.flag_lib,

src/bin/rustdoc.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use cargo::core::Workspace;
2-
use cargo::ops::{self, MessageFormat};
2+
use cargo::ops::{self, MessageFormat, Packages};
33
use cargo::util::{CliResult, Config};
44
use cargo::util::important_paths::{find_root_manifest_for_wd};
55

@@ -80,6 +80,8 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
8080
let root = find_root_manifest_for_wd(options.flag_manifest_path,
8181
config.cwd())?;
8282

83+
let spec = options.flag_package.map_or_else(Vec::new, |s| vec![s]);
84+
8385
let doc_opts = ops::DocOptions {
8486
open_result: options.flag_open,
8587
compile_opts: ops::CompileOptions {
@@ -89,7 +91,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
8991
features: &options.flag_features,
9092
all_features: options.flag_all_features,
9193
no_default_features: options.flag_no_default_features,
92-
spec: &options.flag_package.map_or(Vec::new(), |s| vec![s]),
94+
spec: Packages::Packages(&spec),
9395
release: options.flag_release,
9496
filter: ops::CompileFilter::new(options.flag_lib,
9597
&options.flag_bin,

src/bin/test.rs

+15-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use cargo::core::Workspace;
2-
use cargo::ops::{self, MessageFormat};
2+
use cargo::ops::{self, MessageFormat, Packages};
33
use cargo::util::{CliResult, CliError, Human, human, Config};
4-
use cargo::util::important_paths::{find_root_manifest_for_wd};
4+
use cargo::util::important_paths::find_root_manifest_for_wd;
55

66
#[derive(RustcDecodable)]
77
pub struct Options {
@@ -28,6 +28,7 @@ pub struct Options {
2828
flag_no_fail_fast: bool,
2929
flag_frozen: bool,
3030
flag_locked: bool,
31+
flag_all: bool,
3132
}
3233

3334
pub const USAGE: &'static str = "
@@ -46,6 +47,7 @@ Options:
4647
--bench NAME Test only the specified benchmark target
4748
--no-run Compile, but don't run tests
4849
-p SPEC, --package SPEC ... Package to run tests for
50+
--all Test all packages in the workspace
4951
-j N, --jobs N Number of parallel jobs, defaults to # of CPUs
5052
--release Build artifacts in release mode, with optimizations
5153
--features FEATURES Space-separated list of features to also build
@@ -72,6 +74,9 @@ which indicates which package should be tested. If it is not given, then the
7274
current package is tested. For more information on SPEC and its format, see the
7375
`cargo help pkgid` command.
7476
77+
All packages in the workspace are tested if the `--all` flag is supplied. The
78+
`--all` flag may be supplied in the presence of a virtual manifest.
79+
7580
The --jobs argument affects the building of the test executable but does
7681
not affect how many jobs are used when running the tests.
7782
@@ -111,6 +116,12 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
111116
&options.flag_bench);
112117
}
113118

119+
let spec = if options.flag_all {
120+
Packages::All
121+
} else {
122+
Packages::Packages(&options.flag_package)
123+
};
124+
114125
let ops = ops::TestOptions {
115126
no_run: options.flag_no_run,
116127
no_fail_fast: options.flag_no_fail_fast,
@@ -122,7 +133,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
122133
features: &options.flag_features,
123134
all_features: options.flag_all_features,
124135
no_default_features: options.flag_no_default_features,
125-
spec: &options.flag_package,
136+
spec: spec,
126137
release: options.flag_release,
127138
mode: mode,
128139
filter: filter,
@@ -139,7 +150,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
139150
Some(err) => {
140151
Err(match err.exit.as_ref().and_then(|e| e.code()) {
141152
Some(i) => CliError::new(human("test failed"), i),
142-
None => CliError::new(Box::new(Human(err)), 101)
153+
None => CliError::new(Box::new(Human(err)), 101),
143154
})
144155
}
145156
}

src/cargo/core/resolver/encode.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -283,10 +283,10 @@ impl<'a, 'cfg> Encodable for WorkspaceResolve<'a, 'cfg> {
283283

284284
let root = self.ws.members().max_by_key(|member| {
285285
member.name()
286-
}).unwrap().package_id();
286+
}).map(Package::package_id);
287287

288288
let encodable = ids.iter().filter_map(|&id| {
289-
if self.use_root_key && root == id {
289+
if self.use_root_key && root.unwrap() == id {
290290
return None
291291
}
292292

@@ -307,10 +307,9 @@ impl<'a, 'cfg> Encodable for WorkspaceResolve<'a, 'cfg> {
307307

308308
let metadata = if metadata.len() == 0 {None} else {Some(metadata)};
309309

310-
let root = if self.use_root_key {
311-
Some(encodable_resolve_node(&root, self.resolve))
312-
} else {
313-
None
310+
let root = match root {
311+
Some(root) if self.use_root_key => Some(encodable_resolve_node(&root, self.resolve)),
312+
_ => None,
314313
};
315314
EncodableResolve {
316315
package: Some(encodable),

src/cargo/ops/cargo_compile.rs

+42-26
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ pub struct CompileOptions<'a> {
4747
pub all_features: bool,
4848
/// Flag if the default feature should be built for the root package
4949
pub no_default_features: bool,
50-
/// Root package to build (if None it's the current one)
51-
pub spec: &'a [String],
50+
/// Root package to build (if empty it's the current one)
51+
pub spec: Packages<'a>,
5252
/// Filter to apply to the root package to select which targets will be
5353
/// built.
5454
pub filter: CompileFilter<'a>,
@@ -79,6 +79,12 @@ pub enum MessageFormat {
7979
Json
8080
}
8181

82+
#[derive(Clone, Copy, PartialEq, Eq)]
83+
pub enum Packages<'a> {
84+
All,
85+
Packages(&'a [String]),
86+
}
87+
8288
pub enum CompileFilter<'a> {
8389
Everything,
8490
Only {
@@ -92,8 +98,10 @@ pub enum CompileFilter<'a> {
9298

9399
pub fn compile<'a>(ws: &Workspace<'a>, options: &CompileOptions<'a>)
94100
-> CargoResult<ops::Compilation<'a>> {
95-
for key in ws.current()?.manifest().warnings().iter() {
96-
options.config.shell().warn(key)?
101+
for member in ws.members() {
102+
for key in member.manifest().warnings().iter() {
103+
options.config.shell().warn(key)?
104+
}
97105
}
98106
compile_ws(ws, None, options)
99107
}
@@ -103,17 +111,18 @@ pub fn resolve_dependencies<'a>(ws: &Workspace<'a>,
103111
features: &[String],
104112
all_features: bool,
105113
no_default_features: bool,
106-
specs: &[PackageIdSpec])
107-
-> CargoResult<(PackageSet<'a>, Resolve)> {
114+
specs: &Packages<'a>)
115+
-> CargoResult<(Vec<PackageIdSpec>, PackageSet<'a>, Resolve)> {
108116
let features = features.iter().flat_map(|s| {
109117
s.split_whitespace()
110118
}).map(|s| s.to_string()).collect::<Vec<String>>();
111119

112120
let mut registry = PackageRegistry::new(ws.config())?;
113121

114122
if let Some(source) = source {
115-
registry.add_preloaded(ws.current()?.package_id().source_id(),
116-
source);
123+
if let Some(root_package) = ws.current_opt() {
124+
registry.add_preloaded(root_package.package_id().source_id(), source);
125+
}
117126
}
118127

119128
// First, resolve the root_package's *listed* dependencies, as well as
@@ -137,22 +146,33 @@ pub fn resolve_dependencies<'a>(ws: &Workspace<'a>,
137146
}
138147
};
139148

149+
let specs = match *specs {
150+
Packages::All => {
151+
ws.members()
152+
.map(Package::package_id)
153+
.map(PackageIdSpec::from_package_id)
154+
.collect()
155+
}
156+
Packages::Packages(packages) => {
157+
packages.iter().map(|p| PackageIdSpec::parse(&p)).collect::<CargoResult<Vec<_>>>()?
158+
}
159+
};
160+
140161
let resolved_with_overrides =
141162
ops::resolve_with_previous(&mut registry, ws,
142163
method, Some(&resolve), None,
143-
specs)?;
164+
&specs)?;
144165

145166
let packages = ops::get_resolved_packages(&resolved_with_overrides,
146167
registry);
147168

148-
Ok((packages, resolved_with_overrides))
169+
Ok((specs, packages, resolved_with_overrides))
149170
}
150171

151172
pub fn compile_ws<'a>(ws: &Workspace<'a>,
152173
source: Option<Box<Source + 'a>>,
153174
options: &CompileOptions<'a>)
154175
-> CargoResult<ops::Compilation<'a>> {
155-
let root_package = ws.current()?;
156176
let CompileOptions { config, jobs, target, spec, features,
157177
all_features, no_default_features,
158178
release, mode, message_format,
@@ -167,27 +187,23 @@ pub fn compile_ws<'a>(ws: &Workspace<'a>,
167187
}
168188

169189
let profiles = ws.profiles();
170-
if spec.len() == 0 {
171-
generate_targets(root_package, profiles, mode, filter, release)?;
172-
}
173-
174-
let specs = spec.iter().map(|p| PackageIdSpec::parse(p))
175-
.collect::<CargoResult<Vec<_>>>()?;
176190

177-
let pair = resolve_dependencies(ws,
178-
source,
179-
features,
180-
all_features,
181-
no_default_features,
182-
&specs)?;
183-
let (packages, resolve_with_overrides) = pair;
191+
let resolve = resolve_dependencies(ws,
192+
source,
193+
features,
194+
all_features,
195+
no_default_features,
196+
&spec)?;
197+
let (spec, packages, resolve_with_overrides) = resolve;
184198

185199
let mut pkgids = Vec::new();
186200
if spec.len() > 0 {
187-
for p in spec {
188-
pkgids.push(resolve_with_overrides.query(&p)?);
201+
for p in spec.iter() {
202+
pkgids.push(p.query(resolve_with_overrides.iter())?);
189203
}
190204
} else {
205+
let root_package = ws.current()?;
206+
generate_targets(root_package, profiles, mode, filter, release)?;
191207
pkgids.push(root_package.package_id());
192208
};
193209

src/cargo/ops/cargo_doc.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,18 @@ pub struct DocOptions<'a> {
1515
pub fn doc(ws: &Workspace, options: &DocOptions) -> CargoResult<()> {
1616
let package = ws.current()?;
1717

18+
let spec = match options.compile_opts.spec {
19+
ops::Packages::Packages(packages) => packages,
20+
_ => {
21+
// This should not happen, because the `doc` binary is hard-coded to pass
22+
// the `Packages::Packages` variant.
23+
bail!("`cargo doc` does not support the `--all` flag")
24+
},
25+
};
26+
1827
let mut lib_names = HashSet::new();
1928
let mut bin_names = HashSet::new();
20-
if options.compile_opts.spec.is_empty() {
29+
if spec.is_empty() {
2130
for target in package.targets().iter().filter(|t| t.documented()) {
2231
if target.is_lib() {
2332
assert!(lib_names.insert(target.crate_name()));
@@ -37,10 +46,10 @@ pub fn doc(ws: &Workspace, options: &DocOptions) -> CargoResult<()> {
3746
ops::compile(ws, &options.compile_opts)?;
3847

3948
if options.open_result {
40-
let name = if options.compile_opts.spec.len() > 1 {
49+
let name = if spec.len() > 1 {
4150
bail!("Passing multiple packages and `open` is not supported")
42-
} else if options.compile_opts.spec.len() == 1 {
43-
PackageIdSpec::parse(&options.compile_opts.spec[0])?
51+
} else if spec.len() == 1 {
52+
PackageIdSpec::parse(&spec[0])?
4453
.name()
4554
.replace("-", "_")
4655
} else {

0 commit comments

Comments
 (0)