add --all flag to cargo-test

This commit is contained in:
Andy Russell 2016-10-20 16:14:54 -04:00
parent 25518da782
commit 62c0497912
16 changed files with 213 additions and 36 deletions

View file

@ -88,7 +88,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
spec: &options.flag_package,
spec: ops::Packages::Packages(&options.flag_package),
release: true,
mode: ops::CompileMode::Bench,
filter: ops::CompileFilter::new(options.flag_lib,

View file

@ -84,7 +84,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
spec: &options.flag_package,
spec: ops::Packages::Packages(&options.flag_package),
mode: ops::CompileMode::Build,
release: options.flag_release,
filter: ops::CompileFilter::new(options.flag_lib,

View file

@ -1,5 +1,5 @@
use cargo::core::Workspace;
use cargo::ops::{self, MessageFormat};
use cargo::ops::{self, MessageFormat, Packages};
use cargo::util::{CliResult, Config};
use cargo::util::important_paths::{find_root_manifest_for_wd};
@ -80,7 +80,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
spec: &options.flag_package,
spec: Packages::Packages(&options.flag_package),
filter: ops::CompileFilter::new(options.flag_lib,
&options.flag_bin,
&empty,

View file

@ -108,7 +108,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
spec: &[],
spec: ops::Packages::Packages(&[]),
mode: ops::CompileMode::Build,
release: !options.flag_debug,
filter: ops::CompileFilter::new(false, &options.flag_bin, &[],

View file

@ -1,5 +1,5 @@
use cargo::core::Workspace;
use cargo::ops::{self, MessageFormat};
use cargo::ops::{self, MessageFormat, Packages};
use cargo::util::{CliResult, CliError, Config, Human};
use cargo::util::important_paths::{find_root_manifest_for_wd};
@ -81,7 +81,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
spec: &[],
spec: Packages::Packages(&[]),
release: options.flag_release,
mode: ops::CompileMode::Build,
filter: if examples.is_empty() && bins.is_empty() {

View file

@ -1,7 +1,7 @@
use std::env;
use cargo::core::Workspace;
use cargo::ops::{self, CompileOptions, CompileMode, MessageFormat};
use cargo::ops::{self, CompileOptions, CompileMode, MessageFormat, Packages};
use cargo::util::important_paths::{find_root_manifest_for_wd};
use cargo::util::{CliResult, CliError, Config, human};
@ -95,6 +95,8 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
}
};
let spec = options.flag_package.map_or_else(Vec::new, |s| vec![s]);
let opts = CompileOptions {
config: config,
jobs: options.flag_jobs,
@ -102,7 +104,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
spec: &options.flag_package.map_or(Vec::new(), |s| vec![s]),
spec: Packages::Packages(&spec),
mode: mode,
release: options.flag_release,
filter: ops::CompileFilter::new(options.flag_lib,

View file

@ -1,5 +1,5 @@
use cargo::core::Workspace;
use cargo::ops::{self, MessageFormat};
use cargo::ops::{self, MessageFormat, Packages};
use cargo::util::{CliResult, Config};
use cargo::util::important_paths::{find_root_manifest_for_wd};
@ -80,6 +80,8 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
let root = find_root_manifest_for_wd(options.flag_manifest_path,
config.cwd())?;
let spec = options.flag_package.map_or_else(Vec::new, |s| vec![s]);
let doc_opts = ops::DocOptions {
open_result: options.flag_open,
compile_opts: ops::CompileOptions {
@ -89,7 +91,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
spec: &options.flag_package.map_or(Vec::new(), |s| vec![s]),
spec: Packages::Packages(&spec),
release: options.flag_release,
filter: ops::CompileFilter::new(options.flag_lib,
&options.flag_bin,

View file

@ -1,7 +1,7 @@
use cargo::core::Workspace;
use cargo::ops::{self, MessageFormat};
use cargo::ops::{self, MessageFormat, Packages};
use cargo::util::{CliResult, CliError, Human, human, Config};
use cargo::util::important_paths::{find_root_manifest_for_wd};
use cargo::util::important_paths::find_root_manifest_for_wd;
#[derive(RustcDecodable)]
pub struct Options {
@ -28,6 +28,7 @@ pub struct Options {
flag_no_fail_fast: bool,
flag_frozen: bool,
flag_locked: bool,
flag_all: bool,
}
pub const USAGE: &'static str = "
@ -46,6 +47,7 @@ Options:
--bench NAME Test only the specified benchmark target
--no-run Compile, but don't run tests
-p SPEC, --package SPEC ... Package to run tests for
--all Test all packages in the workspace
-j N, --jobs N Number of parallel jobs, defaults to # of CPUs
--release Build artifacts in release mode, with optimizations
--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
current package is tested. For more information on SPEC and its format, see the
`cargo help pkgid` command.
All packages in the workspace are tested if the `--all` flag is supplied. The
`--all` flag may be supplied in the presence of a virtual manifest.
The --jobs argument affects the building of the test executable but does
not affect how many jobs are used when running the tests.
@ -111,6 +116,12 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
&options.flag_bench);
}
let spec = if options.flag_all {
Packages::All
} else {
Packages::Packages(&options.flag_package)
};
let ops = ops::TestOptions {
no_run: options.flag_no_run,
no_fail_fast: options.flag_no_fail_fast,
@ -122,7 +133,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
features: &options.flag_features,
all_features: options.flag_all_features,
no_default_features: options.flag_no_default_features,
spec: &options.flag_package,
spec: spec,
release: options.flag_release,
mode: mode,
filter: filter,
@ -139,7 +150,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
Some(err) => {
Err(match err.exit.as_ref().and_then(|e| e.code()) {
Some(i) => CliError::new(human("test failed"), i),
None => CliError::new(Box::new(Human(err)), 101)
None => CliError::new(Box::new(Human(err)), 101),
})
}
}

View file

@ -22,6 +22,7 @@
//! previously compiled dependency
//!
use std::borrow::Cow;
use std::collections::HashMap;
use std::path::PathBuf;
@ -47,8 +48,8 @@ pub struct CompileOptions<'a> {
pub all_features: bool,
/// Flag if the default feature should be built for the root package
pub no_default_features: bool,
/// Root package to build (if None it's the current one)
pub spec: &'a [String],
/// Root package to build (if empty it's the current one)
pub spec: Packages<'a>,
/// Filter to apply to the root package to select which targets will be
/// built.
pub filter: CompileFilter<'a>,
@ -79,6 +80,12 @@ pub enum MessageFormat {
Json
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Packages<'a> {
All,
Packages(&'a [String]),
}
pub enum CompileFilter<'a> {
Everything,
Only {
@ -92,8 +99,10 @@ pub enum CompileFilter<'a> {
pub fn compile<'a>(ws: &Workspace<'a>, options: &CompileOptions<'a>)
-> CargoResult<ops::Compilation<'a>> {
for key in ws.current()?.manifest().warnings().iter() {
options.config.shell().warn(key)?
if let Some(root_package) = ws.current_opt() {
for key in root_package.manifest().warnings().iter() {
options.config.shell().warn(key)?
}
}
compile_ws(ws, None, options)
}
@ -112,8 +121,9 @@ pub fn resolve_dependencies<'a>(ws: &Workspace<'a>,
let mut registry = PackageRegistry::new(ws.config())?;
if let Some(source) = source {
registry.add_preloaded(ws.current()?.package_id().source_id(),
source);
if let Some(root_package) = ws.current_opt() {
registry.add_preloaded(root_package.package_id().source_id(), source);
}
}
// First, resolve the root_package's *listed* dependencies, as well as
@ -152,7 +162,6 @@ pub fn compile_ws<'a>(ws: &Workspace<'a>,
source: Option<Box<Source + 'a>>,
options: &CompileOptions<'a>)
-> CargoResult<ops::Compilation<'a>> {
let root_package = ws.current()?;
let CompileOptions { config, jobs, target, spec, features,
all_features, no_default_features,
release, mode, message_format,
@ -166,8 +175,19 @@ pub fn compile_ws<'a>(ws: &Workspace<'a>,
bail!("jobs must be at least 1")
}
let spec: Cow<'a, [String]> = match spec {
Packages::Packages(spec) => spec.into(),
Packages::All => ws.members()
.map(|package| {
let package_id = package.package_id();
PackageIdSpec::from_package_id(package_id).to_string()
})
.collect()
};
let profiles = ws.profiles();
if spec.len() == 0 {
let root_package = ws.current()?;
generate_targets(root_package, profiles, mode, filter, release)?;
}
@ -184,10 +204,11 @@ pub fn compile_ws<'a>(ws: &Workspace<'a>,
let mut pkgids = Vec::new();
if spec.len() > 0 {
for p in spec {
for p in spec.iter() {
pkgids.push(resolve_with_overrides.query(&p)?);
}
} else {
let root_package = ws.current()?;
pkgids.push(root_package.package_id());
};

View file

@ -15,9 +15,18 @@ pub struct DocOptions<'a> {
pub fn doc(ws: &Workspace, options: &DocOptions) -> CargoResult<()> {
let package = ws.current()?;
let spec = match options.compile_opts.spec {
ops::Packages::Packages(packages) => packages,
_ => {
// This should not happen, because the `doc` binary is hard-coded to pass
// the `Packages::Packages` variant.
bail!("`cargo doc` does not support the `--all` flag")
},
};
let mut lib_names = HashSet::new();
let mut bin_names = HashSet::new();
if options.compile_opts.spec.is_empty() {
if spec.is_empty() {
for target in package.targets().iter().filter(|t| t.documented()) {
if target.is_lib() {
assert!(lib_names.insert(target.crate_name()));
@ -37,10 +46,10 @@ pub fn doc(ws: &Workspace, options: &DocOptions) -> CargoResult<()> {
ops::compile(ws, &options.compile_opts)?;
if options.open_result {
let name = if options.compile_opts.spec.len() > 1 {
let name = if spec.len() > 1 {
bail!("Passing multiple packages and `open` is not supported")
} else if options.compile_opts.spec.len() == 1 {
PackageIdSpec::parse(&options.compile_opts.spec[0])?
} else if spec.len() == 1 {
PackageIdSpec::parse(&spec[0])?
.name()
.replace("-", "_")
} else {

View file

@ -291,7 +291,7 @@ fn run_verify(ws: &Workspace, tar: &File, opts: &PackageOpts) -> CargoResult<()>
features: &[],
no_default_features: false,
all_features: false,
spec: &[],
spec: ops::Packages::Packages(&[]),
filter: ops::CompileFilter::Everything,
release: false,
message_format: ops::MessageFormat::Human,

View file

@ -31,7 +31,7 @@ pub struct Unit<'a> {
pub struct Context<'a, 'cfg: 'a> {
pub config: &'cfg Config,
pub resolve: &'a Resolve,
pub current_package: PackageId,
pub current_package: Option<PackageId>,
pub compilation: Compilation<'cfg>,
pub packages: &'a PackageSet<'cfg>,
pub build_state: Arc<BuildState>,
@ -76,7 +76,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
None => None,
};
let current_package = ws.current()?.package_id().clone();
let current_package = ws.current_opt().map(Package::package_id).cloned();
Ok(Context {
host: host_layout,
target: target_layout,
@ -450,7 +450,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
// we don't want to link it up.
if src_dir.ends_with("deps") {
// Don't lift up library dependencies
if unit.pkg.package_id() != &self.current_package && !unit.target.is_bin() {
if self.current_package.as_ref().map_or(false, |p| unit.pkg.package_id() != p)
&& !unit.target.is_bin() {
None
} else {
Some((
@ -836,8 +837,9 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
}
pub fn show_warnings(&self, pkg: &PackageId) -> bool {
pkg == &self.current_package || pkg.source_id().is_path() ||
self.config.extra_verbose()
self.current_package.as_ref().map_or(false, |p| *pkg == *p)
|| pkg.source_id().is_path()
|| self.config.extra_verbose()
}
}

View file

@ -198,7 +198,9 @@ impl<'a> JobQueue<'a> {
}
let build_type = if self.is_release { "release" } else { "debug" };
let profile = cx.lib_profile(&cx.current_package);
let profile = cx.current_package.as_ref().map_or_else(Profile::default, |p| {
cx.lib_profile(p).to_owned()
});
let mut opt_type = String::from(if profile.opt_level == "0" { "unoptimized" }
else { "optimized" });
if profile.debuginfo {

View file

@ -557,7 +557,9 @@ fn build_base_args(cx: &mut Context,
let prefer_dynamic = (unit.target.for_host() &&
!unit.target.is_custom_build()) ||
(crate_types.contains(&"dylib") &&
unit.pkg.package_id() != &cx.current_package);
cx.current_package.as_ref().map_or(false, |p| {
*p != *unit.pkg.package_id()
}));
if prefer_dynamic {
cmd.arg("-C").arg("prefer-dynamic");
}

View file

@ -1,6 +1,6 @@
pub use self::cargo_clean::{clean, CleanOptions};
pub use self::cargo_compile::{compile, compile_ws, resolve_dependencies, CompileOptions};
pub use self::cargo_compile::{CompileFilter, CompileMode, MessageFormat};
pub use self::cargo_compile::{CompileFilter, CompileMode, MessageFormat, Packages};
pub use self::cargo_read_manifest::{read_manifest,read_package,read_packages};
pub use self::cargo_rustc::{compile_targets, Compilation, Kind, Unit};
pub use self::cargo_rustc::Context;

View file

@ -9,6 +9,7 @@ use std::str;
use cargotest::{sleep_ms, is_nightly};
use cargotest::support::{project, execs, basic_bin_manifest, basic_lib_manifest};
use cargotest::support::paths::CargoPathExt;
use cargotest::support::registry::Package;
use hamcrest::{assert_that, existing_file, is_not};
use cargo::util::process;
@ -2398,3 +2399,128 @@ fn test_many_with_features() {
.arg("--features").arg("foo"),
execs().with_status(0));
}
#[test]
fn test_all_workspace() {
let p = project("foo")
.file("Cargo.toml", r#"
[project]
name = "foo"
version = "0.1.0"
[dependencies]
bar = { path = "bar" }
[workspace]
"#)
.file("src/main.rs", r#"
#[test]
fn foo_test() {}
"#)
.file("bar/Cargo.toml", r#"
[project]
name = "bar"
version = "0.1.0"
"#)
.file("bar/src/lib.rs", r#"
#[test]
fn bar_test() {}
"#);
p.build();
assert_that(p.cargo_process("test")
.arg("--all"),
execs().with_stdout_contains("\
running 1 test
test foo_test ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
")
.with_stdout_contains("\
running 1 test
test bar_test ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
"));
}
#[test]
fn test_all_virtual_manifest() {
let p = project("workspace")
.file("Cargo.toml", r#"
[workspace]
members = ["a", "b"]
"#)
.file("a/Cargo.toml", r#"
[project]
name = "a"
version = "0.1.0"
"#)
.file("a/src/lib.rs", r#"
#[test]
fn a() {}
"#)
.file("b/Cargo.toml", r#"
[project]
name = "b"
version = "0.1.0"
"#)
.file("b/src/lib.rs", r#"
#[test]
fn b() {}
"#);
p.build();
assert_that(p.cargo_process("test")
.arg("--all"),
execs().with_stdout_contains("\
running 1 test
test b ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
")
.with_stdout_contains("\
running 1 test
test b ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
"));
}
#[test]
fn test_all_member_dependency_same_name() {
let p = project("workspace")
.file("Cargo.toml", r#"
[workspace]
members = ["a"]
"#)
.file("a/Cargo.toml", r#"
[project]
name = "a"
version = "0.1.0"
[dependencies]
a = "0.1.0"
"#)
.file("a/src/lib.rs", r#"
#[test]
fn a() {}
"#);
p.build();
Package::new("a", "0.1.0").publish();
assert_that(p.cargo_process("test")
.arg("--all"),
execs().with_stdout_contains("\
running 1 test
test a ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
"));
}