]> git.proxmox.com Git - cargo.git/blame - tests/testsuite/cargo_command.rs
Replace .exec_with_output() usage with .run()
[cargo.git] / tests / testsuite / cargo_command.rs
CommitLineData
ee5e24ff 1use std::env;
a6dad622
AC
2use std::fs::{self, File};
3use std::io::prelude::*;
4use std::path::{Path, PathBuf};
8cce8996 5use std::str;
8cce8996 6
98f17bcc 7use cargo;
43b42d6f 8use support::cargo_process;
85984a87 9use support::hamcrest::{assert_that, existing_file};
43b42d6f
DW
10use support::paths::{self, CargoPathExt};
11use support::registry::Package;
85984a87 12use support::{basic_bin_manifest, basic_manifest, cargo_exe, project, Project};
a3f6a404 13
1e682848 14#[cfg_attr(windows, allow(dead_code))]
974d5834
JB
15enum FakeKind<'a> {
16 Executable,
1e682848 17 Symlink { target: &'a Path },
974d5834
JB
18}
19
a3f6a404 20/// Add an empty file with executable flags (and platform-dependent suffix).
d43ee1dd
NK
21/// TODO: move this to `Project` if other cases using this emerge.
22fn fake_file(proj: Project, dir: &Path, name: &str, kind: &FakeKind) -> Project {
85984a87
DW
23 let path = proj
24 .root()
1e682848
AC
25 .join(dir)
26 .join(&format!("{}{}", name, env::consts::EXE_SUFFIX));
763ba535 27 path.parent().unwrap().mkdir_p();
23591fe5 28 match *kind {
974d5834
JB
29 FakeKind::Executable => {
30 File::create(&path).unwrap();
31 make_executable(&path);
1e682848
AC
32 }
33 FakeKind::Symlink { target } => {
34 make_symlink(&path, target);
974d5834
JB
35 }
36 }
a6dad622
AC
37 return proj;
38
39 #[cfg(unix)]
40 fn make_executable(p: &Path) {
41 use std::os::unix::prelude::*;
42
53cc3ce8 43 let mut perms = fs::metadata(p).unwrap().permissions();
a6dad622
AC
44 let mode = perms.mode();
45 perms.set_mode(mode | 0o111);
46 fs::set_permissions(p, perms).unwrap();
47 }
48 #[cfg(windows)]
49 fn make_executable(_: &Path) {}
974d5834
JB
50 #[cfg(unix)]
51 fn make_symlink(p: &Path, t: &Path) {
1e682848 52 ::std::os::unix::fs::symlink(t, p).expect("Failed to create symlink");
974d5834
JB
53 }
54 #[cfg(windows)]
55 fn make_symlink(_: &Path, _: &Path) {
56 panic!("Not supported")
57 }
a3f6a404 58}
59
a6dad622 60fn path() -> Vec<PathBuf> {
23591fe5 61 env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect()
db3823a8 62}
ee5e24ff 63
af2c3555
DW
64#[test]
65fn list_commands_with_descriptions() {
66 let p = project().build();
67 let output = p.cargo("--list").exec_with_output().unwrap();
68 let output = str::from_utf8(&output.stdout).unwrap();
69 assert!(
85984a87
DW
70 output.contains(
71 "\n build Compile a local package and all of its dependencies"
72 ),
af2c3555
DW
73 "missing build, with description: {}",
74 output
75 );
a838f8fa
DW
76 // assert read-manifest prints the right one-line description followed by another command, indented.
77 assert!(
78 output.contains("\n read-manifest Print a JSON representation of a Cargo.toml manifest.\n "),
79 "missing build, with description: {}",
80 output
81 );
af2c3555
DW
82}
83
6950bbb0
AC
84#[test]
85fn list_command_looks_at_path() {
f8c9928c 86 let proj = project().build();
1e682848
AC
87 let proj = fake_file(
88 proj,
89 Path::new("path-test"),
90 "cargo-1",
91 &FakeKind::Executable,
92 );
a3f6a404 93
5d0cb3f2 94 let mut path = path();
db3823a8 95 path.push(proj.root().join("path-test"));
ee5e24ff 96 let path = env::join_paths(path.iter()).unwrap();
8940d306
DW
97 let mut p = cargo_process("-v --list");
98 let output = p.env("PATH", &path);
9ed3a6ea 99 let output = output.exec_with_output().unwrap();
a6dad622 100 let output = str::from_utf8(&output.stdout).unwrap();
1e682848
AC
101 assert!(
102 output.contains("\n 1 "),
103 "missing 1: {}",
104 output
105 );
6950bbb0 106}
12f5de8e 107
974d5834
JB
108// windows and symlinks don't currently agree that well
109#[cfg(unix)]
6950bbb0
AC
110#[test]
111fn list_command_resolves_symlinks() {
f8c9928c 112 let proj = project().build();
1e682848
AC
113 let proj = fake_file(
114 proj,
115 Path::new("path-test"),
116 "cargo-2",
117 &FakeKind::Symlink {
118 target: &cargo_exe(),
119 },
120 );
974d5834
JB
121
122 let mut path = path();
123 path.push(proj.root().join("path-test"));
124 let path = env::join_paths(path.iter()).unwrap();
8940d306
DW
125 let mut p = cargo_process("-v --list");
126 let output = p.env("PATH", &path);
974d5834
JB
127 let output = output.exec_with_output().unwrap();
128 let output = str::from_utf8(&output.stdout).unwrap();
1e682848
AC
129 assert!(
130 output.contains("\n 2 "),
131 "missing 2: {}",
132 output
133 );
6950bbb0 134}
974d5834 135
6950bbb0
AC
136#[test]
137fn find_closest_biuld_to_build() {
85984a87
DW
138 cargo_process("biuld")
139 .with_status(101)
140 .with_stderr_contains(
1e682848 141 "\
a1735c7a
AK
142error: no such subcommand: `biuld`
143
144<tab>Did you mean `build`?
1e682848 145",
85984a87 146 ).run();
a1735c7a
AK
147
148 // But, if we actually have `biuld`, it must work!
149 // https://github.com/rust-lang/cargo/issues/5201
150 Package::new("cargo-biuld", "1.0.0")
151 .file(
152 "src/main.rs",
153 r#"
154 fn main() {
155 println!("Similar, but not identical to, build");
156 }
157 "#,
85984a87
DW
158 ).publish();
159
160 cargo_process("install cargo-biuld").run();
161 cargo_process("biuld")
162 .with_stdout("Similar, but not identical to, build\n")
163 .run();
164 cargo_process("--list")
165 .with_stdout_contains(
166 " build Compile a local package and all of its dependencies\n",
167 ).with_stdout_contains(" biuld\n")
168 .run();
6950bbb0 169}
12f5de8e
PW
170
171// if a subcommand is more than 3 edit distance away, we don't make a suggestion
6950bbb0
AC
172#[test]
173fn find_closest_dont_correct_nonsense() {
85984a87
DW
174 cargo_process("there-is-no-way-that-there-is-a-command-close-to-this")
175 .cwd(&paths::root())
176 .with_status(101)
177 .with_stderr(
1e682848 178 "[ERROR] no such subcommand: \
1671630b 179 `there-is-no-way-that-there-is-a-command-close-to-this`
1e682848 180",
85984a87 181 ).run();
79858995
KA
182}
183
184#[test]
185fn displays_subcommand_on_error() {
85984a87
DW
186 cargo_process("invalid-command")
187 .with_status(101)
188 .with_stderr("[ERROR] no such subcommand: `invalid-command`\n")
189 .run();
6950bbb0 190}
2badab8c 191
6950bbb0
AC
192#[test]
193fn override_cargo_home() {
2badab8c
BA
194 let root = paths::root();
195 let my_home = root.join("my_home");
a6dad622 196 fs::create_dir(&my_home).unwrap();
1e682848
AC
197 File::create(&my_home.join("config"))
198 .unwrap()
199 .write_all(
200 br#"
2badab8c
BA
201 [cargo-new]
202 name = "foo"
203 email = "bar"
204 git = false
1e682848 205 "#,
85984a87 206 ).unwrap();
2badab8c 207
85984a87
DW
208 cargo_process("new foo")
209 .env("USER", "foo")
210 .env("CARGO_HOME", &my_home)
211 .run();
2badab8c
BA
212
213 let toml = paths::root().join("foo/Cargo.toml");
a6dad622 214 let mut contents = String::new();
1e682848
AC
215 File::open(&toml)
216 .unwrap()
217 .read_to_string(&mut contents)
218 .unwrap();
a6dad622 219 assert!(contents.contains(r#"authors = ["foo <bar>"]"#));
6950bbb0 220}
2ff5f53b 221
015a08a0
VK
222#[test]
223fn cargo_subcommand_env() {
1e682848
AC
224 let src = format!(
225 r#"
015a08a0
VK
226 use std::env;
227
228 fn main() {{
229 println!("{{}}", env::var("{}").unwrap());
230 }}
1e682848
AC
231 "#,
232 cargo::CARGO_ENV
233 );
015a08a0 234
85984a87
DW
235 let p = project()
236 .at("cargo-envtest")
015a08a0 237 .file("Cargo.toml", &basic_bin_manifest("cargo-envtest"))
d43ee1dd
NK
238 .file("src/main.rs", &src)
239 .build();
015a08a0
VK
240
241 let target_dir = p.target_debug_dir();
242
85984a87 243 p.cargo("build").run();
015a08a0
VK
244 assert_that(&p.bin("cargo-envtest"), existing_file());
245
015a08a0
VK
246 let cargo = cargo_exe().canonicalize().unwrap();
247 let mut path = path();
248 path.push(target_dir);
249 let path = env::join_paths(path.iter()).unwrap();
250
85984a87
DW
251 cargo_process("envtest")
252 .env("PATH", &path)
253 .with_stdout(cargo.to_str().unwrap())
254 .run();
015a08a0
VK
255}
256
deb1c1e1
AK
257#[test]
258fn cargo_subcommand_args() {
85984a87
DW
259 let p = project()
260 .at("cargo-foo")
ab19c483 261 .file("Cargo.toml", &basic_manifest("cargo-foo", "0.0.1"))
deb1c1e1
AK
262 .file(
263 "src/main.rs",
264 r#"
265 fn main() {
266 let args: Vec<_> = ::std::env::args().collect();
267 println!("{:?}", args);
268 }
269 "#,
85984a87 270 ).build();
deb1c1e1 271
85984a87 272 p.cargo("build").run();
deb1c1e1
AK
273 let cargo_foo_bin = p.bin("cargo-foo");
274 assert_that(&cargo_foo_bin, existing_file());
275
276 let mut path = path();
277 path.push(p.target_debug_dir());
278 let path = env::join_paths(path.iter()).unwrap();
279
85984a87
DW
280 cargo_process("foo bar -v --help")
281 .env("PATH", &path)
282 .with_stdout(format!(
deb1c1e1
AK
283 r#"[{:?}, "foo", "bar", "-v", "--help"]"#,
284 cargo_foo_bin
85984a87 285 )).run();
deb1c1e1
AK
286}
287
6950bbb0
AC
288#[test]
289fn cargo_help() {
85984a87
DW
290 cargo_process("").run();
291 cargo_process("help").run();
292 cargo_process("-h").run();
293 cargo_process("help build").run();
294 cargo_process("build -h").run();
295 cargo_process("help help").run();
6950bbb0 296}
8dad57e8 297
9e41e383
AR
298#[test]
299fn cargo_help_external_subcommand() {
300 Package::new("cargo-fake-help", "1.0.0")
301 .file(
302 "src/main.rs",
303 r#"
304 fn main() {
305 if ::std::env::args().nth(2) == Some(String::from("--help")) {
306 println!("fancy help output");
307 }
308 }"#,
85984a87
DW
309 ).publish();
310 cargo_process("install cargo-fake-help").run();
311 cargo_process("help fake-help")
312 .with_stdout("fancy help output\n")
313 .run();
9e41e383
AR
314}
315
6950bbb0
AC
316#[test]
317fn explain() {
85984a87
DW
318 cargo_process("--explain E0001")
319 .with_stdout_contains(
b0c181d9 320 "This error suggests that the expression arm corresponding to the noted pattern",
85984a87 321 ).run();
6950bbb0 322}
a4104914
KP
323
324// Test that the output of 'cargo -Z help' shows a different help screen with
325// all the -Z flags.
326#[test]
327fn z_flags_help() {
85984a87
DW
328 cargo_process("-Z help")
329 .with_stdout_contains(
9af095ad 330 " -Z unstable-options -- Allow the usage of unstable options such as --registry",
85984a87 331 ).run();
a4104914 332}