]> git.proxmox.com Git - cargo.git/blame - tests/testsuite/cargo_command.rs
Auto merge of #9764 - djmitche:issue8486, r=alexcrichton
[cargo.git] / tests / testsuite / cargo_command.rs
CommitLineData
83571aee
EH
1//! Tests for custom cargo commands and other global command features.
2
ee5e24ff 3use std::env;
dde290e6 4use std::fs;
7274307a 5use std::io::Read;
a6dad622 6use std::path::{Path, PathBuf};
7274307a 7use std::process::Stdio;
8cce8996 8use std::str;
8cce8996 9
9115b2c3 10use cargo_test_support::cargo_process;
dde290e6 11use cargo_test_support::paths;
9115b2c3 12use cargo_test_support::registry::Package;
1c5e68b4 13use cargo_test_support::{basic_bin_manifest, basic_manifest, cargo_exe, project, project_in_home};
a3f6a404 14
a6dad622 15fn path() -> Vec<PathBuf> {
23591fe5 16 env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect()
db3823a8 17}
ee5e24ff 18
0e0d9688 19#[cargo_test]
af2c3555
DW
20fn list_commands_with_descriptions() {
21 let p = project().build();
a173fc0a 22 p.cargo("--list")
fecb7246
AC
23 .with_stdout_contains(
24 " build Compile a local package and all of its dependencies",
25 )
f7c91ba6
AR
26 // Assert that `read-manifest` prints the right one-line description followed by another
27 // command, indented.
fecb7246
AC
28 .with_stdout_contains(
29 " read-manifest Print a JSON representation of a Cargo.toml manifest.",
30 )
a173fc0a 31 .run();
af2c3555
DW
32}
33
7b16c7c1 34#[cargo_test]
1c5e68b4 35fn list_builtin_aliases_with_descriptions() {
7b16c7c1
C
36 let p = project().build();
37 p.cargo("--list")
38 .with_stdout_contains(" b alias: build")
39 .with_stdout_contains(" c alias: check")
40 .with_stdout_contains(" r alias: run")
41 .with_stdout_contains(" t alias: test")
42 .run();
43}
44
1c5e68b4
DM
45#[cargo_test]
46fn list_custom_aliases_with_descriptions() {
47 let p = project_in_home("proj")
48 .file(
49 &paths::home().join(".cargo").join("config"),
50 r#"
51 [alias]
52 myaliasstr = "foo --bar"
53 myaliasvec = ["foo", "--bar"]
54 "#,
55 )
56 .build();
57
58 p.cargo("--list")
59 .with_stdout_contains(" myaliasstr foo --bar")
60 .with_stdout_contains(" myaliasvec foo --bar")
61 .run();
62}
63
0e0d9688 64#[cargo_test]
6950bbb0 65fn list_command_looks_at_path() {
dde290e6
NK
66 let proj = project()
67 .executable(Path::new("path-test").join("cargo-1"), "")
68 .build();
a3f6a404 69
5d0cb3f2 70 let mut path = path();
db3823a8 71 path.push(proj.root().join("path-test"));
ee5e24ff 72 let path = env::join_paths(path.iter()).unwrap();
fecb7246
AC
73 let output = cargo_process("-v --list")
74 .env("PATH", &path)
75 .exec_with_output()
76 .unwrap();
63b34b64
DW
77 let output = str::from_utf8(&output.stdout).unwrap();
78 assert!(
79 output.contains("\n 1 "),
80 "missing 1: {}",
81 output
82 );
6950bbb0 83}
12f5de8e 84
0e0d9688 85#[cargo_test]
6950bbb0 86fn list_command_resolves_symlinks() {
dde290e6
NK
87 let proj = project()
88 .symlink(cargo_exe(), Path::new("path-test").join("cargo-2"))
89 .build();
974d5834
JB
90
91 let mut path = path();
92 path.push(proj.root().join("path-test"));
93 let path = env::join_paths(path.iter()).unwrap();
fecb7246
AC
94 let output = cargo_process("-v --list")
95 .env("PATH", &path)
96 .exec_with_output()
97 .unwrap();
63b34b64
DW
98 let output = str::from_utf8(&output.stdout).unwrap();
99 assert!(
100 output.contains("\n 2 "),
101 "missing 2: {}",
102 output
103 );
6950bbb0 104}
974d5834 105
0e0d9688 106#[cargo_test]
6950bbb0 107fn find_closest_biuld_to_build() {
85984a87
DW
108 cargo_process("biuld")
109 .with_status(101)
110 .with_stderr_contains(
1e682848 111 "\
a1735c7a
AK
112error: no such subcommand: `biuld`
113
114<tab>Did you mean `build`?
1e682848 115",
fecb7246
AC
116 )
117 .run();
a1735c7a
AK
118
119 // But, if we actually have `biuld`, it must work!
120 // https://github.com/rust-lang/cargo/issues/5201
121 Package::new("cargo-biuld", "1.0.0")
122 .file(
123 "src/main.rs",
124 r#"
6f8c7d5a
EH
125 fn main() {
126 println!("Similar, but not identical to, build");
127 }
128 "#,
fecb7246
AC
129 )
130 .publish();
85984a87
DW
131
132 cargo_process("install cargo-biuld").run();
133 cargo_process("biuld")
134 .with_stdout("Similar, but not identical to, build\n")
135 .run();
136 cargo_process("--list")
137 .with_stdout_contains(
138 " build Compile a local package and all of its dependencies\n",
fecb7246
AC
139 )
140 .with_stdout_contains(" biuld\n")
85984a87 141 .run();
6950bbb0 142}
12f5de8e 143
ff3e880c
ZL
144#[cargo_test]
145fn find_closest_alias() {
146 let root = paths::root();
147 let my_home = root.join("my_home");
148 fs::create_dir(&my_home).unwrap();
4ae79d2f
EH
149 fs::write(
150 &my_home.join("config"),
151 r#"
152 [alias]
153 myalias = "build"
154 "#,
155 )
156 .unwrap();
ff3e880c
ZL
157
158 cargo_process("myalais")
159 .env("CARGO_HOME", &my_home)
160 .with_status(101)
161 .with_stderr_contains(
162 "\
163error: no such subcommand: `myalais`
164
165<tab>Did you mean `myalias`?
166",
167 )
168 .run();
169
170 // But, if no alias is defined, it must not suggest one!
171 cargo_process("myalais")
172 .with_status(101)
173 .with_stderr_contains(
174 "\
175error: no such subcommand: `myalais`
176",
177 )
178 .with_stderr_does_not_contain(
179 "\
180<tab>Did you mean `myalias`?
181",
182 )
183 .run();
184}
185
f7c91ba6 186// If a subcommand is more than an edit distance of 3 away, we don't make a suggestion.
0e0d9688 187#[cargo_test]
6950bbb0 188fn find_closest_dont_correct_nonsense() {
85984a87
DW
189 cargo_process("there-is-no-way-that-there-is-a-command-close-to-this")
190 .cwd(&paths::root())
191 .with_status(101)
192 .with_stderr(
1e682848 193 "[ERROR] no such subcommand: \
1671630b 194 `there-is-no-way-that-there-is-a-command-close-to-this`
1e682848 195",
fecb7246
AC
196 )
197 .run();
79858995
KA
198}
199
0e0d9688 200#[cargo_test]
79858995 201fn displays_subcommand_on_error() {
85984a87
DW
202 cargo_process("invalid-command")
203 .with_status(101)
204 .with_stderr("[ERROR] no such subcommand: `invalid-command`\n")
205 .run();
6950bbb0 206}
2badab8c 207
b0998864
J
208#[cargo_test]
209fn override_cargo_home() {
210 let root = paths::root();
211 let my_home = root.join("my_home");
212 fs::create_dir(&my_home).unwrap();
213 fs::write(
214 &my_home.join("config"),
215 r#"
216 [cargo-new]
217 vcs = "none"
218 "#,
219 )
220 .unwrap();
221
222 cargo_process("new foo").env("CARGO_HOME", &my_home).run();
223
224 assert!(!paths::root().join("foo/.git").is_dir());
225
226 cargo_process("new foo2").run();
227
228 assert!(paths::root().join("foo2/.git").is_dir());
229}
230
0e0d9688 231#[cargo_test]
015a08a0 232fn cargo_subcommand_env() {
1e682848
AC
233 let src = format!(
234 r#"
015a08a0
VK
235 use std::env;
236
237 fn main() {{
238 println!("{{}}", env::var("{}").unwrap());
239 }}
1e682848
AC
240 "#,
241 cargo::CARGO_ENV
242 );
015a08a0 243
85984a87
DW
244 let p = project()
245 .at("cargo-envtest")
015a08a0 246 .file("Cargo.toml", &basic_bin_manifest("cargo-envtest"))
d43ee1dd
NK
247 .file("src/main.rs", &src)
248 .build();
015a08a0
VK
249
250 let target_dir = p.target_debug_dir();
251
85984a87 252 p.cargo("build").run();
570fe892 253 assert!(p.bin("cargo-envtest").is_file());
015a08a0 254
015a08a0
VK
255 let cargo = cargo_exe().canonicalize().unwrap();
256 let mut path = path();
257 path.push(target_dir);
258 let path = env::join_paths(path.iter()).unwrap();
259
85984a87
DW
260 cargo_process("envtest")
261 .env("PATH", &path)
262 .with_stdout(cargo.to_str().unwrap())
263 .run();
015a08a0
VK
264}
265
0e0d9688 266#[cargo_test]
deb1c1e1 267fn cargo_subcommand_args() {
85984a87
DW
268 let p = project()
269 .at("cargo-foo")
ab19c483 270 .file("Cargo.toml", &basic_manifest("cargo-foo", "0.0.1"))
deb1c1e1
AK
271 .file(
272 "src/main.rs",
273 r#"
6f8c7d5a
EH
274 fn main() {
275 let args: Vec<_> = ::std::env::args().collect();
aea5ca3c 276 println!("{}", args.join(" "));
6f8c7d5a
EH
277 }
278 "#,
fecb7246
AC
279 )
280 .build();
deb1c1e1 281
85984a87 282 p.cargo("build").run();
deb1c1e1 283 let cargo_foo_bin = p.bin("cargo-foo");
570fe892 284 assert!(cargo_foo_bin.is_file());
deb1c1e1
AK
285
286 let mut path = path();
287 path.push(p.target_debug_dir());
288 let path = env::join_paths(path.iter()).unwrap();
289
85984a87
DW
290 cargo_process("foo bar -v --help")
291 .env("PATH", &path)
aea5ca3c 292 .with_stdout("[CWD]/cargo-foo/target/debug/cargo-foo[EXE] foo bar -v --help")
49f73b9c 293 .run();
deb1c1e1
AK
294}
295
0e0d9688 296#[cargo_test]
6950bbb0 297fn explain() {
85984a87
DW
298 cargo_process("--explain E0001")
299 .with_stdout_contains(
b0c181d9 300 "This error suggests that the expression arm corresponding to the noted pattern",
fecb7246
AC
301 )
302 .run();
6950bbb0 303}
a4104914 304
7274307a
EH
305#[cargo_test]
306fn closed_output_ok() {
307 // Checks that closed output doesn't cause an error.
308 let mut p = cargo_process("--list").build_command();
309 p.stdout(Stdio::piped()).stderr(Stdio::piped());
310 let mut child = p.spawn().unwrap();
311 // Close stdout
312 drop(child.stdout.take());
313 // Read stderr
314 let mut s = String::new();
315 child
316 .stderr
317 .as_mut()
318 .unwrap()
319 .read_to_string(&mut s)
320 .unwrap();
321 let status = child.wait().unwrap();
322 assert!(status.success());
f5a3d559 323 assert!(s.is_empty(), "{}", s);
7274307a 324}