Testsuite: Make `cwd()` relative to project root.

It's a fairly common pattern, and it seemed natural to me.
This commit is contained in:
Eric Huss 2019-03-20 16:34:56 -07:00
parent 5c54fcb98b
commit e7124ba262
15 changed files with 97 additions and 92 deletions

View File

@ -29,7 +29,7 @@ fn different_dir() {
assert!(p.build_dir().is_dir());
p.cargo("clean")
.cwd(&p.root().join("src"))
.cwd("src")
.with_stdout("")
.run();
assert!(!p.build_dir().is_dir());
@ -78,7 +78,7 @@ fn clean_multiple_packages() {
assert!(d2_path.is_file());
p.cargo("clean -p d1 -p d2")
.cwd(&p.root().join("src"))
.cwd("src")
.with_stdout("")
.run();
assert!(p.bin("foo").is_file());

View File

@ -29,8 +29,8 @@ fn multiple_installs() {
.file("b/src/main.rs", "fn main() {}");
let p = p.build();
let mut a = p.cargo("install").cwd(p.root().join("a")).build_command();
let mut b = p.cargo("install").cwd(p.root().join("b")).build_command();
let mut a = p.cargo("install").cwd("a").build_command();
let mut b = p.cargo("install").cwd("b").build_command();
a.stdout(Stdio::piped()).stderr(Stdio::piped());
b.stdout(Stdio::piped()).stderr(Stdio::piped());
@ -87,8 +87,8 @@ fn one_install_should_be_bad() {
.file("b/src/main.rs", "fn main() {}");
let p = p.build();
let mut a = p.cargo("install").cwd(p.root().join("a")).build_command();
let mut b = p.cargo("install").cwd(p.root().join("b")).build_command();
let mut a = p.cargo("install").cwd("a").build_command();
let mut b = p.cargo("install").cwd("b").build_command();
a.stdout(Stdio::piped()).stderr(Stdio::piped());
b.stdout(Stdio::piped()).stderr(Stdio::piped());
@ -157,8 +157,8 @@ fn multiple_registry_fetches() {
.file("b/src/main.rs", "fn main() {}");
let p = p.build();
let mut a = p.cargo("build").cwd(p.root().join("a")).build_command();
let mut b = p.cargo("build").cwd(p.root().join("b")).build_command();
let mut a = p.cargo("build").cwd("a").build_command();
let mut b = p.cargo("build").cwd("b").build_command();
a.stdout(Stdio::piped()).stderr(Stdio::piped());
b.stdout(Stdio::piped()).stderr(Stdio::piped());
@ -247,8 +247,8 @@ fn git_same_repo_different_tags() {
);
let p = p.build();
let mut a = p.cargo("build -v").cwd(p.root().join("a")).build_command();
let mut b = p.cargo("build -v").cwd(p.root().join("b")).build_command();
let mut a = p.cargo("build -v").cwd("a").build_command();
let mut b = p.cargo("build -v").cwd("b").build_command();
a.stdout(Stdio::piped()).stderr(Stdio::piped());
b.stdout(Stdio::piped()).stderr(Stdio::piped());
@ -316,7 +316,7 @@ fn git_same_branch_different_revs() {
// Generate a Cargo.lock pointing at the current rev, then clear out the
// target directory
p.cargo("build").cwd(p.root().join("a")).run();
p.cargo("build").cwd("a").run();
fs::remove_dir_all(p.root().join("a/target")).unwrap();
// Make a new commit on the master branch
@ -330,8 +330,8 @@ fn git_same_branch_different_revs() {
// Now run both builds in parallel. The build of `b` should pick up the
// newest commit while the build of `a` should use the locked old commit.
let mut a = p.cargo("build").cwd(p.root().join("a")).build_command();
let mut b = p.cargo("build").cwd(p.root().join("b")).build_command();
let mut a = p.cargo("build").cwd("a").build_command();
let mut b = p.cargo("build").cwd("b").build_command();
a.stdout(Stdio::piped()).stderr(Stdio::piped());
b.stdout(Stdio::piped()).stderr(Stdio::piped());

View File

@ -710,9 +710,9 @@ fn workspace_different_locations() {
)
.build();
p.cargo("build").cwd(p.root().join("foo")).run();
p.cargo("build").cwd("foo").run();
p.cargo("build")
.cwd(p.root().join("bar"))
.cwd("bar")
.with_stderr(
"\
[COMPILING] bar [..]

View File

@ -134,11 +134,11 @@ fn broken_fixes_backed_out() {
.build();
// Build our rustc shim
p.cargo("build").cwd(p.root().join("foo")).run();
p.cargo("build").cwd("foo").run();
// Attempt to fix code, but our shim will always fail the second compile
p.cargo("fix --allow-no-vcs --lib")
.cwd(p.root().join("bar"))
.cwd("bar")
.env("__CARGO_FIX_YOLO", "1")
.env("RUSTC", p.root().join("foo/target/debug/foo"))
.with_stderr_contains(
@ -259,7 +259,7 @@ fn do_not_fix_non_relevant_deps() {
p.cargo("fix --allow-no-vcs")
.env("__CARGO_FIX_YOLO", "1")
.cwd(p.root().join("foo"))
.cwd("foo")
.run();
assert!(p.read_file("bar/src/lib.rs").contains("mut"));
@ -1254,11 +1254,11 @@ fn fix_to_broken_code() {
.build();
// Build our rustc shim
p.cargo("build").cwd(p.root().join("foo")).run();
p.cargo("build").cwd("foo").run();
// Attempt to fix code, but our shim will always fail the second compile
p.cargo("fix --allow-no-vcs --broken-code")
.cwd(p.root().join("bar"))
.cwd("bar")
.env("RUSTC", p.root().join("foo/target/debug/foo"))
.with_status(101)
.with_stderr_contains("[WARNING] failed to automatically apply fixes [..]")
@ -1306,9 +1306,9 @@ fn fix_in_existing_repo_weird_ignore() {
// probably be checking if any source file for the current project is
// ignored.
p.cargo("fix")
.cwd(p.root().join("inner"))
.cwd("inner")
.with_stderr_contains("[ERROR] no VCS found[..]")
.with_status(101)
.run();
p.cargo("fix").cwd(p.root().join("src")).run();
p.cargo("fix").cwd("src").run();
}

View File

@ -339,7 +339,7 @@ fn changing_bin_paths_common_target_features_caches_targets() {
/* Build and rebuild a/. Ensure dep_crate only builds once */
p.cargo("run")
.cwd(p.root().join("a"))
.cwd("a")
.with_stdout("ftest off")
.with_stderr(
"\
@ -350,9 +350,9 @@ fn changing_bin_paths_common_target_features_caches_targets() {
",
)
.run();
p.cargo("clean -p a").cwd(p.root().join("a")).run();
p.cargo("clean -p a").cwd("a").run();
p.cargo("run")
.cwd(p.root().join("a"))
.cwd("a")
.with_stdout("ftest off")
.with_stderr(
"\
@ -365,7 +365,7 @@ fn changing_bin_paths_common_target_features_caches_targets() {
/* Build and rebuild b/. Ensure dep_crate only builds once */
p.cargo("run")
.cwd(p.root().join("b"))
.cwd("b")
.with_stdout("ftest on")
.with_stderr(
"\
@ -376,9 +376,9 @@ fn changing_bin_paths_common_target_features_caches_targets() {
",
)
.run();
p.cargo("clean -p b").cwd(p.root().join("b")).run();
p.cargo("clean -p b").cwd("b").run();
p.cargo("run")
.cwd(p.root().join("b"))
.cwd("b")
.with_stdout("ftest on")
.with_stderr(
"\
@ -391,9 +391,9 @@ fn changing_bin_paths_common_target_features_caches_targets() {
/* Build a/ package again. If we cache different feature dep builds correctly,
* this should not cause a rebuild of dep_crate */
p.cargo("clean -p a").cwd(p.root().join("a")).run();
p.cargo("clean -p a").cwd("a").run();
p.cargo("run")
.cwd(p.root().join("a"))
.cwd("a")
.with_stdout("ftest off")
.with_stderr(
"\
@ -406,9 +406,9 @@ fn changing_bin_paths_common_target_features_caches_targets() {
/* Build b/ package again. If we cache different feature dep builds correctly,
* this should not cause a rebuild */
p.cargo("clean -p b").cwd(p.root().join("b")).run();
p.cargo("clean -p b").cwd("b").run();
p.cargo("run")
.cwd(p.root().join("b"))
.cwd("b")
.with_stdout("ftest on")
.with_stderr(
"\
@ -681,7 +681,7 @@ fn same_build_dir_cached_packages() {
.build();
p.cargo("build")
.cwd(p.root().join("a1"))
.cwd("a1")
.with_stderr(&format!(
"\
[COMPILING] d v0.0.1 ({dir}/d)
@ -694,7 +694,7 @@ fn same_build_dir_cached_packages() {
))
.run();
p.cargo("build")
.cwd(p.root().join("a2"))
.cwd("a2")
.with_stderr(
"\
[COMPILING] a2 v0.0.1 ([CWD])

View File

@ -1311,7 +1311,7 @@ fn workspace_uses_workspace_target_dir() {
.file("bar/src/main.rs", "fn main() {}")
.build();
p.cargo("build --release").cwd(p.root().join("bar")).run();
p.cargo("build --release").cwd("bar").run();
cargo_process("install --path")
.arg(p.root().join("bar"))
.with_stderr(

View File

@ -1096,7 +1096,7 @@ fn no_warnings_when_replace_is_used_in_another_workspace_member() {
.build();
p.cargo("build")
.cwd(p.root().join("first_crate"))
.cwd("first_crate")
.with_stdout("")
.with_stderr(
"\
@ -1108,7 +1108,7 @@ fn no_warnings_when_replace_is_used_in_another_workspace_member() {
.run();
p.cargo("build")
.cwd(p.root().join("second_crate"))
.cwd("second_crate")
.with_stdout("")
.with_stderr(
"\

View File

@ -885,7 +885,7 @@ fn ignore_workspace_specifier() {
.build();
p.cargo("package --no-verify")
.cwd(p.root().join("bar"))
.cwd("bar")
.run();
let f = File::open(&p.root().join("target/package/bar-0.1.0.crate")).unwrap();
@ -1184,7 +1184,7 @@ fn lock_file_and_workspace() {
.build();
p.cargo("package")
.cwd(p.root().join("foo"))
.cwd("foo")
.masquerade_as_nightly_cargo()
.run();

View File

@ -881,7 +881,7 @@ fn override_and_depend() {
.file("b/.cargo/config", r#"paths = ["../a"]"#)
.build();
p.cargo("build")
.cwd(p.root().join("b"))
.cwd("b")
.with_stderr(
"\
[COMPILING] a2 v0.5.0 ([..])

View File

@ -273,7 +273,7 @@ fn profile_in_non_root_manifest_triggers_a_warning() {
.build();
p.cargo("build -v")
.cwd(p.root().join("bar"))
.cwd("bar")
.with_stderr(
"\
[WARNING] profiles for the non root package will be ignored, specify profiles at the workspace root:
@ -315,7 +315,7 @@ fn profile_in_virtual_manifest_works() {
.build();
p.cargo("build -v")
.cwd(p.root().join("bar"))
.cwd("bar")
.with_stderr(
"\
[COMPILING] bar v0.1.0 ([..])

View File

@ -457,7 +457,7 @@ fn publish_in_sub_repo() {
.build();
p.cargo("publish")
.cwd(p.root().join("bar"))
.cwd("bar")
.arg("--index")
.arg(registry_url().to_string())
.run();
@ -531,7 +531,7 @@ fn ignore_when_crate_ignored() {
)
.nocommit_file("bar/src/main.rs", "fn main() {}");
p.cargo("publish")
.cwd(p.root().join("bar"))
.cwd("bar")
.arg("--index")
.arg(registry_url().to_string())
.run();

View File

@ -1029,7 +1029,7 @@ fn run_multiple_packages() {
let cargo = || {
let mut process_builder = p.cargo("run");
process_builder.cwd(p.root().join("foo"));
process_builder.cwd("foo");
process_builder
};

View File

@ -749,7 +749,12 @@ impl Execs {
pub fn cwd<T: AsRef<OsStr>>(&mut self, path: T) -> &mut Self {
if let Some(ref mut p) = self.process_builder {
p.cwd(path);
if let Some(cwd) = p.get_cwd() {
p.cwd(cwd.join(path.as_ref()));
} else {
p.cwd(path);
}
}
self
}

View File

@ -105,7 +105,7 @@ fn relative_tools() {
let prefix = p.root().into_os_string().into_string().unwrap();
p.cargo("build --verbose").cwd(p.root().join("bar")).with_stderr(&format!(
p.cargo("build --verbose").cwd("bar").with_stderr(&format!(
"\
[COMPILING] bar v0.5.0 ([CWD])
[RUNNING] `rustc [..] -C ar={prefix}/./nonexistent-ar -C linker={prefix}/./tools/nonexistent-linker [..]`

View File

@ -39,7 +39,7 @@ fn simple_explicit() {
assert!(p.bin("foo").is_file());
assert!(!p.bin("bar").is_file());
p.cargo("build").cwd(p.root().join("bar")).run();
p.cargo("build").cwd("bar").run();
assert!(p.bin("foo").is_file());
assert!(p.bin("bar").is_file());
@ -106,7 +106,7 @@ fn inferred_root() {
assert!(p.bin("foo").is_file());
assert!(!p.bin("bar").is_file());
p.cargo("build").cwd(p.root().join("bar")).run();
p.cargo("build").cwd("bar").run();
assert!(p.bin("foo").is_file());
assert!(p.bin("bar").is_file());
@ -141,7 +141,7 @@ fn inferred_path_dep() {
assert!(p.bin("foo").is_file());
assert!(!p.bin("bar").is_file());
p.cargo("build").cwd(p.root().join("bar")).run();
p.cargo("build").cwd("bar").run();
assert!(p.bin("foo").is_file());
assert!(p.bin("bar").is_file());
@ -191,12 +191,12 @@ fn transitive_path_dep() {
assert!(!p.bin("bar").is_file());
assert!(!p.bin("baz").is_file());
p.cargo("build").cwd(p.root().join("bar")).run();
p.cargo("build").cwd("bar").run();
assert!(p.bin("foo").is_file());
assert!(p.bin("bar").is_file());
assert!(!p.bin("baz").is_file());
p.cargo("build").cwd(p.root().join("baz")).run();
p.cargo("build").cwd("baz").run();
assert!(p.bin("foo").is_file());
assert!(p.bin("bar").is_file());
assert!(p.bin("baz").is_file());
@ -238,8 +238,8 @@ fn parent_pointer_works() {
.file("bar/src/lib.rs", "");
let p = p.build();
p.cargo("build").cwd(p.root().join("foo")).run();
p.cargo("build").cwd(p.root().join("bar")).run();
p.cargo("build").cwd("foo").run();
p.cargo("build").cwd("bar").run();
assert!(p.root().join("foo/Cargo.lock").is_file());
assert!(!p.root().join("bar/Cargo.lock").is_file());
}
@ -305,7 +305,7 @@ fn parent_doesnt_point_to_child() {
let p = p.build();
p.cargo("build")
.cwd(p.root().join("bar"))
.cwd("bar")
.with_status(101)
.with_stderr(
"\
@ -705,7 +705,7 @@ fn lock_works_for_everyone() {
.run();
p.cargo("build")
.cwd(p.root().join("bar"))
.cwd("bar")
.with_stderr(
"\
[DOWNLOADING] crates ...
@ -731,7 +731,7 @@ fn virtual_works() {
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("bar/src/main.rs", "fn main() {}");
let p = p.build();
p.cargo("build").cwd(p.root().join("bar")).run();
p.cargo("build").cwd("bar").run();
assert!(p.root().join("Cargo.lock").is_file());
assert!(p.bin("bar").is_file());
assert!(!p.root().join("bar/Cargo.lock").is_file());
@ -769,7 +769,7 @@ fn virtual_misconfigure() {
.file("bar/src/main.rs", "fn main() {}");
let p = p.build();
p.cargo("build")
.cwd(p.root().join("bar"))
.cwd("bar")
.with_status(101)
.with_stderr(
"\
@ -938,9 +938,9 @@ fn members_include_path_deps() {
.file("p3/src/lib.rs", "");
let p = p.build();
p.cargo("build").cwd(p.root().join("p1")).run();
p.cargo("build").cwd(p.root().join("p2")).run();
p.cargo("build").cwd(p.root().join("p3")).run();
p.cargo("build").cwd("p1").run();
p.cargo("build").cwd("p2").run();
p.cargo("build").cwd("p3").run();
p.cargo("build").run();
assert!(p.root().join("target").is_dir());
@ -1027,7 +1027,7 @@ fn lock_doesnt_change_depending_on_crate() {
let mut lockfile = String::new();
t!(t!(File::open(p.root().join("Cargo.lock"))).read_to_string(&mut lockfile));
p.cargo("build").cwd(p.root().join("baz")).run();
p.cargo("build").cwd("baz").run();
let mut lockfile2 = String::new();
t!(t!(File::open(p.root().join("Cargo.lock"))).read_to_string(&mut lockfile2));
@ -1075,17 +1075,17 @@ fn rebuild_please() {
);
let p = p.build();
p.cargo("run").cwd(p.root().join("bin")).run();
p.cargo("run").cwd("bin").run();
sleep_ms(1000);
t!(t!(File::create(p.root().join("lib/src/lib.rs")))
.write_all(br#"pub fn foo() -> u32 { 1 }"#));
p.cargo("build").cwd(p.root().join("lib")).run();
p.cargo("build").cwd("lib").run();
p.cargo("run")
.cwd(p.root().join("bin"))
.cwd("bin")
.with_status(101)
.with_stderr_contains("[..]assertion[..]")
.run();
@ -1159,7 +1159,7 @@ fn lockfile_can_specify_nonexistant_members() {
let p = p.build();
p.cargo("build").cwd(p.root().join("a")).run();
p.cargo("build").cwd("a").run();
}
#[test]
@ -1241,7 +1241,7 @@ fn error_if_parent_cargo_toml_is_invalid() {
let p = p.build();
p.cargo("build")
.cwd(p.root().join("bar"))
.cwd("bar")
.with_status(101)
.with_stderr_contains("[ERROR] failed to parse manifest at `[..]`")
.run();
@ -1276,8 +1276,8 @@ fn relative_path_for_member_works() {
.file("bar/src/main.rs", "fn main() {}");
let p = p.build();
p.cargo("build").cwd(p.root().join("foo")).run();
p.cargo("build").cwd(p.root().join("bar")).run();
p.cargo("build").cwd("foo").run();
p.cargo("build").cwd("bar").run();
}
#[test]
@ -1305,7 +1305,7 @@ fn relative_path_for_root_works() {
p.cargo("build --manifest-path ./Cargo.toml").run();
p.cargo("build --manifest-path ../Cargo.toml")
.cwd(p.root().join("subproj"))
.cwd("subproj")
.run();
}
@ -1332,7 +1332,7 @@ fn path_dep_outside_workspace_is_not_member() {
.file("foo/src/lib.rs", "");
let p = p.build();
p.cargo("build").cwd(p.root().join("ws")).run();
p.cargo("build").cwd("ws").run();
}
#[test]
@ -1387,7 +1387,7 @@ fn test_in_and_out_of_workspace() {
.file("bar/src/lib.rs", "pub fn f() { }");
let p = p.build();
p.cargo("build").cwd(p.root().join("ws")).run();
p.cargo("build").cwd("ws").run();
assert!(p.root().join("ws/Cargo.lock").is_file());
assert!(p.root().join("ws/target").is_dir());
@ -1396,7 +1396,7 @@ fn test_in_and_out_of_workspace() {
assert!(!p.root().join("bar/Cargo.lock").is_file());
assert!(!p.root().join("bar/target").is_dir());
p.cargo("build").cwd(p.root().join("foo")).run();
p.cargo("build").cwd("foo").run();
assert!(p.root().join("foo/Cargo.lock").is_file());
assert!(p.root().join("foo/target").is_dir());
assert!(!p.root().join("bar/Cargo.lock").is_file());
@ -1445,12 +1445,12 @@ fn test_path_dependency_under_member() {
.file("foo/bar/src/lib.rs", "pub fn f() { }");
let p = p.build();
p.cargo("build").cwd(p.root().join("ws")).run();
p.cargo("build").cwd("ws").run();
assert!(!p.root().join("foo/bar/Cargo.lock").is_file());
assert!(!p.root().join("foo/bar/target").is_dir());
p.cargo("build").cwd(p.root().join("foo/bar")).run();
p.cargo("build").cwd("foo/bar").run();
assert!(!p.root().join("foo/bar/Cargo.lock").is_file());
assert!(!p.root().join("foo/bar/target").is_dir());
@ -1478,7 +1478,7 @@ fn excluded_simple() {
p.cargo("build").run();
assert!(p.root().join("target").is_dir());
p.cargo("build").cwd(p.root().join("foo")).run();
p.cargo("build").cwd("foo").run();
assert!(p.root().join("foo/target").is_dir());
}
@ -1507,9 +1507,9 @@ fn exclude_members_preferred() {
p.cargo("build").run();
assert!(p.root().join("target").is_dir());
p.cargo("build").cwd(p.root().join("foo")).run();
p.cargo("build").cwd("foo").run();
assert!(p.root().join("foo/target").is_dir());
p.cargo("build").cwd(p.root().join("foo/bar")).run();
p.cargo("build").cwd("foo/bar").run();
assert!(!p.root().join("foo/bar/target").is_dir());
}
@ -1540,9 +1540,9 @@ fn exclude_but_also_depend() {
p.cargo("build").run();
assert!(p.root().join("target").is_dir());
p.cargo("build").cwd(p.root().join("foo")).run();
p.cargo("build").cwd("foo").run();
assert!(p.root().join("foo/target").is_dir());
p.cargo("build").cwd(p.root().join("foo/bar")).run();
p.cargo("build").cwd("foo/bar").run();
assert!(p.root().join("foo/bar/target").is_dir());
}
@ -1602,15 +1602,15 @@ fn glob_syntax() {
assert!(!p.bin("bar").is_file());
assert!(!p.bin("baz").is_file());
p.cargo("build").cwd(p.root().join("crates/bar")).run();
p.cargo("build").cwd("crates/bar").run();
assert!(p.bin("foo").is_file());
assert!(p.bin("bar").is_file());
p.cargo("build").cwd(p.root().join("crates/baz")).run();
p.cargo("build").cwd("crates/baz").run();
assert!(p.bin("foo").is_file());
assert!(p.bin("baz").is_file());
p.cargo("build").cwd(p.root().join("crates/qux")).run();
p.cargo("build").cwd("crates/qux").run();
assert!(!p.bin("qux").is_file());
assert!(p.root().join("Cargo.lock").is_file());
@ -1664,15 +1664,15 @@ fn glob_syntax_2() {
assert!(!p.bin("bar").is_file());
assert!(!p.bin("baz").is_file());
p.cargo("build").cwd(p.root().join("crates/bar")).run();
p.cargo("build").cwd("crates/bar").run();
assert!(p.bin("foo").is_file());
assert!(p.bin("bar").is_file());
p.cargo("build").cwd(p.root().join("crates/baz")).run();
p.cargo("build").cwd("crates/baz").run();
assert!(p.bin("foo").is_file());
assert!(p.bin("baz").is_file());
p.cargo("build").cwd(p.root().join("crates/qux")).run();
p.cargo("build").cwd("crates/qux").run();
assert!(!p.bin("qux").is_file());
assert!(p.root().join("Cargo.lock").is_file());
@ -1795,7 +1795,7 @@ fn dep_used_with_separate_features() {
// Ideally once we solve rust-lang/cargo#3620, then a single Cargo build at the top level
// will be enough.
p.cargo("build")
.cwd(p.root().join("caller1"))
.cwd("caller1")
.with_stderr(
"\
[..]Compiling feat_lib v0.1.0 ([..])
@ -1808,15 +1808,15 @@ fn dep_used_with_separate_features() {
// Alternate building `caller2`/`caller1` a few times, just to make sure
// features are being built separately. Should not rebuild anything.
p.cargo("build")
.cwd(p.root().join("caller2"))
.cwd("caller2")
.with_stderr("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")
.run();
p.cargo("build")
.cwd(p.root().join("caller1"))
.cwd("caller1")
.with_stderr("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")
.run();
p.cargo("build")
.cwd(p.root().join("caller2"))
.cwd("caller2")
.with_stderr("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")
.run();
}
@ -1892,10 +1892,10 @@ fn include_and_exclude() {
.file("foo/bar/src/lib.rs", "");
p.build();
p.cargo("build").cwd(p.root().join("foo")).run();
p.cargo("build").cwd("foo").run();
assert!(p.root().join("target").is_dir());
assert!(!p.root().join("foo/target").is_dir());
p.cargo("build").cwd(p.root().join("foo/bar")).run();
p.cargo("build").cwd("foo/bar").run();
assert!(p.root().join("foo/bar/target").is_dir());
}
*/