Add `--all` flag to `cargo test` #3221

Merged
merged 11 commits into from Dec 9, 2016

Projects

None yet

6 participants

@euclio
Contributor
euclio commented Oct 21, 2016

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.

@brson brson was assigned by rust-highfive Oct 21, 2016
@rust-highfive

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @brson (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see the contribution instructions for more information.

@alexcrichton
Member

Thanks for the PR! Unfortunately I'll be pretty busy this week so it may take awhile to get back to this, but I haven't forgotten it!

@alexcrichton

Ok, looking good! We may need a few cleanups along the way to really land this, but I think this is a great start.

@@ -281,14 +281,15 @@ impl<'a, 'cfg> Encodable for WorkspaceResolve<'a, 'cfg> {
let root = self.ws.members().max_by_key(|member| {
member.name()
- }).unwrap().package_id();
+ }).map(Package::package_id);
@alexcrichton
alexcrichton Oct 26, 2016 Member

Hm were the changes in this file required to get tests to pass? Or just cleaning things up?

@euclio
euclio Oct 26, 2016 edited Contributor

Yes, that panic is triggered when running test on a virtual manifest. It is currently prevented by the "error: manifest path ... is a virtual manifest, but this command requires running against an actual package in this workspace" error.

@alexcrichton
alexcrichton Nov 4, 2016 Member

Ok, sounds good to me

src/cargo/ops/cargo_compile.rs
+ Packages::All => ws.members()
+ .map(|package| {
+ let package_id = package.package_id();
+ PackageIdSpec::from_package_id(package_id).to_string()
@alexcrichton
alexcrichton Oct 26, 2016 Member

Instead of round-tripping through PackageIdSpec, perhaps the resolution to a list of local packages could be done sooner?

@euclio
euclio Oct 26, 2016 Contributor

Where would be the right place to do that? I didn't want to place it too high up so that future --all commands could share this logic.

@alexcrichton
alexcrichton Nov 4, 2016 Member

Maybe the concept of "all" could be plumbed farther down as an enum?

@euclio
euclio Nov 8, 2016 Contributor

Plumbed down where? It makes sense to me to pass Packages down through resolve_dependencies but don't you still need to get the PackageIdSpecs of the workspace here to resolve the targets?

@alexcrichton
alexcrichton Nov 8, 2016 Member

Yeah let's pass this down to resolve_dependencies, and perhaps that can also return a list of specs?

src/cargo/ops/cargo_compile.rs
+ doc: Profile::default_doc(),
+ custom_build: Profile::default_custom_build(),
+ },
+ };
@alexcrichton
alexcrichton Oct 26, 2016 Member

Hm this is somewhat worrisome to me. This is where I think we'll want to learn about the profiles from the workspace root crate instead of whatever the current crate happens to be.

@euclio
euclio Oct 26, 2016 Contributor

Does the workspace have a root crate in a virtual manifest?

@matklad
matklad Nov 3, 2016 Contributor

Not exactly yet, see #3249 :)

@euclio
euclio Nov 4, 2016 Contributor

@matklad Awesome! I can rebase on top of your PR.

@alexcrichton
alexcrichton Nov 4, 2016 Member

Ah yeah #3249 is exactly what I had in mind here

src/cargo/ops/cargo_compile.rs
+ let root_package = try!(ws.current());
+ if spec.len() == 0 {
+ try!(generate_targets(root_package, &profiles, mode, filter, release));
+ }
@alexcrichton
alexcrichton Oct 26, 2016 Member

This kinda sent me spinning for a bit. I think this if statement isn't necessary, right? It's implied to always be true given the above condition.

@euclio
euclio Oct 26, 2016 Contributor

Fixed.

src/cargo/ops/cargo_rustc/context.rs
@@ -28,7 +28,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>,
@alexcrichton
alexcrichton Oct 26, 2016 Member

Hm so I think this is a code smell we need to clean up (not your fault, a historical one). The concept of a "current package" is basically no longer valid in today's world of workspaces and such. Could this field get outright removed as part of this change?

@euclio
euclio Oct 26, 2016 Contributor

I can try that, sure.

@euclio
euclio Oct 27, 2016 Contributor

I think I need some clarification. What does "current package" mean in this context? Isn't it the package of the directory that we issue the compile in? Why is that not needed?

@alexcrichton
alexcrichton Nov 4, 2016 Member

Yeah the intention is there really is not right question to what the "current package" means. It has different interpretations depending on where you are asking it from, so that's why I figure it'd be best to remove and we can answer that question on a case-by-case basis.

@euclio
euclio Nov 8, 2016 Contributor

I see. Digging into this more, I'm noticing that the places that use Context don't have a Workspace available to pull a root package from (if one exists). So, doesn't making this an Option essentially handle this (i.e., a workspace either has a current package, or it's virtual, so it doesn't). Thank you for your patience :)

@bors
Contributor
bors commented Nov 2, 2016

☔️ The latest upstream changes (presumably #3242) made this pull request unmergeable. Please resolve the merge conflicts.

@brson brson assigned alexcrichton and unassigned brson Nov 3, 2016
@bors bors added a commit that referenced this pull request Nov 4, 2016
@bors bors Auto merge of #3249 - matklad:workspace-profiles, r=alexcrichton
Use a single profile set per workspace

This aims to close #3206.

I have not figured out how to do this 100% backward compatibly, that's why I want to discuss this separately, although a related PR (#3221) is already in flight.

The problem is this: suppose that you have a workspace with two members, A and B and that A includes a profiles section and B does not. Now, mentally `cd` inside B and run `cargo build`. Today, Cargo will use a default profile. We want it to use a profile from A. So here the silent behavior switch will inevitably occur :( Looks like we can't detect this situation.

So this PR just switches the behavior to always use root profiles, and to print a warning if a non-root package specifies profiles. Feel free to reuse it in any form for #3221 if that's convenient!
f9ddf56
@euclio
Contributor
euclio commented Nov 6, 2016

Rebased. Hopefully will get a chance to work on this more later this week.

src/cargo/ops/cargo_compile.rs
@@ -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 try!(ws.current()).manifest().warnings().iter() {
- try!(options.config.shell().warn(key))
+ if let Some(root_package) = ws.current_opt() {
@alexcrichton
alexcrichton Nov 8, 2016 Member

Random drive-by comment, but could this actually iterate over all members of the workspace? That's the intention here, at least

@bors
Contributor
bors commented Nov 11, 2016

☔️ The latest upstream changes (presumably #3280) made this pull request unmergeable. Please resolve the merge conflicts.

@euclio
Contributor
euclio commented Nov 16, 2016

Rebased, and ready for another round of review, @alexcrichton

src/cargo/core/resolver/encode.rs
}
-
- Some(encodable_resolve_node(id, self.resolve))
@alexcrichton
alexcrichton Nov 17, 2016 Member

Hm ok to sanity check this (changes to resolve are very subtle).

I don't think this change is needed, right? The change above (unwrap -> map) is purely for cargo test against an empty virtual manifest, right? If there exists any crates at all (e.g. ids is a non-empty list) then I'd hope there's at least one workspace member.

src/cargo/ops/cargo_compile.rs
- .collect::<CargoResult<Vec<_>>>()?;
-
- let pair = resolve_dependencies(ws,
+ let resolve = resolve_dependencies(ws,
source,
@alexcrichton
alexcrichton Nov 17, 2016 Member

Some indentation to match up here

src/cargo/ops/cargo_compile.rs
- for p in spec {
- pkgids.push(resolve_with_overrides.query(&p)?);
+ for p in spec.iter() {
+ pkgids.push(resolve_with_overrides.query(&p.to_string())?);
@alexcrichton
alexcrichton Nov 17, 2016 Member

I think this can just be:

pkgids.push(p.query(resolve_with_overrides.iter()));

(avoid going through a string)

src/cargo/ops/cargo_compile.rs
}
} else {
+ let root_package = ws.current()?;
+ generate_targets(root_package, profiles, mode, filter, release)?;
@alexcrichton
alexcrichton Nov 17, 2016 Member

I think this was special cased above to get these errors before the resolution process happened (which may involve downloads and such). Perhaps that logic could still be special cased?

@euclio
euclio Dec 2, 2016 Contributor

Putting this logic the old way caused my tests to fail, but I'm not sure why.

src/cargo/ops/cargo_rustc/context.rs
@@ -273,7 +272,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
/// Returns the appropriate directory layout for either a plugin or not.
pub fn layout(&self, unit: &Unit) -> LayoutProxy {
- let primary = unit.pkg.package_id() == &self.current_package;
+ let primary = self.ws.current_opt().map_or(false, |p| unit.pkg.package_id() == p.package_id());
@alexcrichton
alexcrichton Nov 17, 2016 Member

I think this can be replaced with:

let primary = is_member_of_current_workspace(self, unit);
src/cargo/ops/cargo_rustc/context.rs
@@ -417,7 +416,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.ws.current_opt().map_or(false, |p| unit.pkg.package_id() != p.package_id())
@alexcrichton
alexcrichton Nov 17, 2016 Member

I think here we can actually just test:

if !unit.pkg.package_id().source_id().is_path() && !unit.target.is_bin() {
    // ...
}

That is, all path dependencies should hit the code path of Some below

@alexcrichton
alexcrichton Nov 17, 2016 Member

er actually, we should replace the current_package check with a check if the crate is in the workspace rather than all path dependencies.

@euclio
euclio Dec 2, 2016 Contributor

What's the correct way to check this?

ws.members().find(|&p| p == unit.pkg).is_some() causes test failures.

@alexcrichton
alexcrichton Dec 8, 2016 Member

Hm yeah that should work, but is that not working? What do the test failures look like?

@euclio
euclio Dec 8, 2016 Contributor

Hm, on a second look I think I might have just been reversing the conditional. Pushed a fix.

src/cargo/ops/cargo_rustc/context.rs
- self.config.extra_verbose()
+ self.ws.current_opt().map_or(false, |p| *pkg == *p.package_id())
+ || pkg.source_id().is_path()
+ || self.config.extra_verbose()
@alexcrichton
alexcrichton Nov 17, 2016 Member

I think this can be updated to just the clause:

pkg.source_id().is_path() || self.config.extra_verbose()
@alexcrichton
alexcrichton Nov 17, 2016 Member

Well technically actually, we should show warnings for all workspace members, not not all path dependencies.

src/cargo/ops/cargo_rustc/job_queue.rs
- let profile = cx.lib_profile(&cx.current_package);
+ let profile = cx.ws.current_opt().map_or_else(Profile::default, |p| {
+ cx.lib_profile(p.package_id()).to_owned()
+ });
@alexcrichton
alexcrichton Nov 17, 2016 Member

The package argument here to lib_profile is actually ignored (long story), so let's just go ahead and remove that argument and then we can avoid the workaround here.

src/cargo/ops/cargo_rustc/mod.rs
- unit.pkg.package_id() != &cx.current_package);
+ cx.ws.current_opt().map_or(false, |p| {
+ *p.package_id() != *unit.pkg.package_id()
+ }));
@alexcrichton
alexcrichton Nov 17, 2016 Member

Wow I have absolutely no clue what this clause is doing (the old one).

Let's just replace it though with, like above, a test whether the package is in the current workspace.

@euclio
euclio Dec 2, 2016 Contributor

Same as above.

@euclio
euclio Dec 8, 2016 Contributor

Ditto.

@euclio
Contributor
euclio commented Nov 29, 2016

Still working on this, haven't had much time for open source lately! Hoping to finish up by the weekend.

@alexcrichton
Member

Ah no worries, let me know if you need any help getting it over the finish line!

@bors
Contributor
bors commented Dec 2, 2016

☔️ The latest upstream changes (presumably #3310) made this pull request unmergeable. Please resolve the merge conflicts.

@euclio
Contributor
euclio commented Dec 2, 2016

@alexcrichton Most comments addressed, I commented on the remaining issues.

@alexcrichton
Member

Sorry for taking awhile to get back to this! I just want to dig into the "is a member" issue a bit and then we should be able to land this.

@euclio
Contributor
euclio commented Dec 8, 2016 edited

@alexcrichton, no problem! Everything should be addressed now. There are failing tests, but those are due to #879.

@alexcrichton
Member

@bors: r+

Awesome, thanks!

@bors
Contributor
bors commented Dec 8, 2016

📌 Commit addbb7e has been approved by alexcrichton

@bors
Contributor
bors commented Dec 8, 2016

⌛️ Testing commit addbb7e with merge fec03d3...

@bors bors added a commit that referenced this pull request Dec 8, 2016
@bors bors 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.
fec03d3
@bors
Contributor
bors commented Dec 9, 2016

☀️ Test successful - status-appveyor, status-travis
Approved by: alexcrichton
Pushing fec03d3 to master...

@bors bors merged commit addbb7e into rust-lang:master Dec 9, 2016

3 checks passed

continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
homu Test successful
Details
@bors bors added a commit that referenced this pull request Dec 13, 2016
@bors bors Auto merge of #3385 - matklad:package-test, r=alexcrichton
Add test for --package and virtual manifest

closes #3194

The issue was actually fixed by #3221 (thanks @euclio !), so let's just add a test (a copy of `virtual_works` basically).
8f8bead
@bors bors added a commit that referenced this pull request Dec 13, 2016
@bors bors Auto merge of #3385 - matklad:package-test, r=alexcrichton
Add test for --package and virtual manifest

closes #3194

The issue was actually fixed by #3221 (thanks @euclio !), so let's just add a test (a copy of `virtual_works` basically).
6b818f4
@bors bors added a commit that referenced this pull request Dec 13, 2016
@bors bors Auto merge of #3385 - matklad:package-test, r=alexcrichton
Add test for --package and virtual manifest

closes #3194

The issue was actually fixed by #3221 (thanks @euclio !), so let's just add a test (a copy of `virtual_works` basically).
020df94
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment