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