blob: 9f451a64c6b843d76a12a25887a69bdb49c311ec [file] [log] [blame]
Chris Wailese3116c42021-07-13 14:40:48 -07001//! Tests for future-incompat-report messages
Chris Wailes54272ac2021-09-09 16:08:13 -07002//!
3//! Note that these tests use the -Zfuture-incompat-test for rustc.
4//! This causes rustc to treat *every* lint as future-incompatible.
5//! This is done because future-incompatible lints are inherently
6//! ephemeral, but we don't want to continually update these tests.
7//! So we pick some random lint that will likely always be the same
8//! over time.
Chris Wailese3116c42021-07-13 14:40:48 -07009
Chris Wailesbcf972c2021-10-21 11:03:28 -070010use super::config::write_config_toml;
Chris Wailese3116c42021-07-13 14:40:48 -070011use cargo_test_support::registry::Package;
Chariseeb1d32802022-09-22 15:38:41 +000012use cargo_test_support::{basic_manifest, project, Project};
Chris Wailes54272ac2021-09-09 16:08:13 -070013
14// An arbitrary lint (unused_variables) that triggers a lint.
15// We use a special flag to force it to generate a report.
16const FUTURE_EXAMPLE: &'static str = "fn main() { let x = 1; }";
17// Some text that will be displayed when the lint fires.
18const FUTURE_OUTPUT: &'static str = "[..]unused_variables[..]";
19
20fn simple_project() -> Project {
21 project()
22 .file("Cargo.toml", &basic_manifest("foo", "0.0.0"))
23 .file("src/main.rs", FUTURE_EXAMPLE)
24 .build()
25}
Chris Wailese3116c42021-07-13 14:40:48 -070026
Chariseeb1d32802022-09-22 15:38:41 +000027#[cargo_test(
28 nightly,
29 reason = "-Zfuture-incompat-test requires nightly (permanently)"
30)]
Charisee7878d542022-02-24 18:21:36 +000031fn output_on_stable() {
Chris Wailes54272ac2021-09-09 16:08:13 -070032 let p = simple_project();
Chris Wailese3116c42021-07-13 14:40:48 -070033
Chris Wailes54272ac2021-09-09 16:08:13 -070034 p.cargo("check")
Chris Wailes54272ac2021-09-09 16:08:13 -070035 .env("RUSTFLAGS", "-Zfuture-incompat-test")
36 .with_stderr_contains(FUTURE_OUTPUT)
Charisee7878d542022-02-24 18:21:36 +000037 .with_stderr_contains("[..]cargo report[..]")
Chris Wailese3116c42021-07-13 14:40:48 -070038 .run();
39}
40
Charisee7878d542022-02-24 18:21:36 +000041// This feature is stable, and should not be gated
Chris Wailese3116c42021-07-13 14:40:48 -070042#[cargo_test]
Charisee7878d542022-02-24 18:21:36 +000043fn no_gate_future_incompat_report() {
Chris Wailes54272ac2021-09-09 16:08:13 -070044 let p = simple_project();
Chris Wailese3116c42021-07-13 14:40:48 -070045
Chris Wailes5c0824a2023-04-24 16:30:59 -070046 p.cargo("check --future-incompat-report")
Charisee7878d542022-02-24 18:21:36 +000047 .with_status(0)
Chris Wailese3116c42021-07-13 14:40:48 -070048 .run();
49
Chris Wailes2f3fdfe2021-07-29 10:56:18 -070050 p.cargo("report future-incompatibilities --id foo")
Charisee7878d542022-02-24 18:21:36 +000051 .with_stderr_contains("error: no reports are currently available")
Chris Wailese3116c42021-07-13 14:40:48 -070052 .with_status(101)
53 .run();
54}
55
Chariseeb1d32802022-09-22 15:38:41 +000056#[cargo_test(
57 nightly,
58 reason = "-Zfuture-incompat-test requires nightly (permanently)"
59)]
Chris Wailes32f78352021-07-20 14:04:55 -070060fn test_zero_future_incompat() {
Chris Wailes32f78352021-07-20 14:04:55 -070061 let p = project()
62 .file("Cargo.toml", &basic_manifest("foo", "0.0.0"))
63 .file("src/main.rs", "fn main() {}")
64 .build();
65
Chris Wailes54272ac2021-09-09 16:08:13 -070066 // No note if --future-incompat-report is not specified.
Chris Wailes5c0824a2023-04-24 16:30:59 -070067 p.cargo("check")
Chris Wailes54272ac2021-09-09 16:08:13 -070068 .env("RUSTFLAGS", "-Zfuture-incompat-test")
69 .with_stderr(
70 "\
Chris Wailes5c0824a2023-04-24 16:30:59 -070071[CHECKING] foo v0.0.0 [..]
Chris Wailes54272ac2021-09-09 16:08:13 -070072[FINISHED] [..]
73",
74 )
75 .run();
76
Chris Wailes5c0824a2023-04-24 16:30:59 -070077 p.cargo("check --future-incompat-report")
Chris Wailes54272ac2021-09-09 16:08:13 -070078 .env("RUSTFLAGS", "-Zfuture-incompat-test")
79 .with_stderr(
80 "\
81[FINISHED] [..]
82note: 0 dependencies had future-incompatible warnings
83",
84 )
Chris Wailes32f78352021-07-20 14:04:55 -070085 .run();
86}
87
Chariseeb1d32802022-09-22 15:38:41 +000088#[cargo_test(
89 nightly,
90 reason = "-Zfuture-incompat-test requires nightly (permanently)"
91)]
Chris Wailese3116c42021-07-13 14:40:48 -070092fn test_single_crate() {
Chris Wailes54272ac2021-09-09 16:08:13 -070093 let p = simple_project();
Chris Wailese3116c42021-07-13 14:40:48 -070094
95 for command in &["build", "check", "rustc", "test"] {
Chris Wailesbcf972c2021-10-21 11:03:28 -070096 let check_has_future_compat = || {
Charisee7878d542022-02-24 18:21:36 +000097 p.cargo(command)
Chris Wailesbcf972c2021-10-21 11:03:28 -070098 .env("RUSTFLAGS", "-Zfuture-incompat-test")
99 .with_stderr_contains(FUTURE_OUTPUT)
100 .with_stderr_contains("warning: the following packages contain code that will be rejected by a future version of Rust: foo v0.0.0 [..]")
101 .with_stderr_does_not_contain("[..]incompatibility[..]")
102 .run();
103 };
104
105 // Check that we show a message with no [future-incompat-report] config section
106 write_config_toml("");
107 check_has_future_compat();
108
Charisee9cf67802022-06-30 20:04:09 +0000109 // Check that we show a message with `frequency = "always"`
Chris Wailesbcf972c2021-10-21 11:03:28 -0700110 write_config_toml(
111 "\
112[future-incompat-report]
113frequency = 'always'
114",
115 );
116 check_has_future_compat();
117
118 // Check that we do not show a message with `frequency = "never"`
119 write_config_toml(
120 "\
121[future-incompat-report]
122frequency = 'never'
123",
124 );
125 p.cargo(command)
Chris Wailes54272ac2021-09-09 16:08:13 -0700126 .env("RUSTFLAGS", "-Zfuture-incompat-test")
127 .with_stderr_contains(FUTURE_OUTPUT)
Chris Wailesbcf972c2021-10-21 11:03:28 -0700128 .with_stderr_does_not_contain("[..]rejected[..]")
Chris Wailese3116c42021-07-13 14:40:48 -0700129 .with_stderr_does_not_contain("[..]incompatibility[..]")
130 .run();
131
Chris Wailesbcf972c2021-10-21 11:03:28 -0700132 // Check that passing `--future-incompat-report` overrides `frequency = 'never'`
Charisee7878d542022-02-24 18:21:36 +0000133 p.cargo(command).arg("--future-incompat-report")
Chris Wailes54272ac2021-09-09 16:08:13 -0700134 .env("RUSTFLAGS", "-Zfuture-incompat-test")
135 .with_stderr_contains(FUTURE_OUTPUT)
136 .with_stderr_contains("warning: the following packages contain code that will be rejected by a future version of Rust: foo v0.0.0 [..]")
Charisee9cf67802022-06-30 20:04:09 +0000137 .with_stderr_contains(" - foo@0.0.0[..]")
Chris Wailese3116c42021-07-13 14:40:48 -0700138 .run();
139 }
140}
141
Chariseeb1d32802022-09-22 15:38:41 +0000142#[cargo_test(
143 nightly,
144 reason = "-Zfuture-incompat-test requires nightly (permanently)"
145)]
Chris Wailese3116c42021-07-13 14:40:48 -0700146fn test_multi_crate() {
Chris Wailese3116c42021-07-13 14:40:48 -0700147 Package::new("first-dep", "0.0.1")
Chris Wailes54272ac2021-09-09 16:08:13 -0700148 .file("src/lib.rs", FUTURE_EXAMPLE)
Chris Wailese3116c42021-07-13 14:40:48 -0700149 .publish();
150 Package::new("second-dep", "0.0.2")
Chris Wailes54272ac2021-09-09 16:08:13 -0700151 .file("src/lib.rs", FUTURE_EXAMPLE)
Chris Wailese3116c42021-07-13 14:40:48 -0700152 .publish();
153
154 let p = project()
155 .file(
156 "Cargo.toml",
157 r#"
158 [package]
159 name = "foo"
160 version = "0.0.0"
161
162 [dependencies]
163 first-dep = "*"
164 second-dep = "*"
165 "#,
166 )
167 .file("src/main.rs", "fn main() {}")
168 .build();
169
170 for command in &["build", "check", "rustc", "test"] {
Charisee7878d542022-02-24 18:21:36 +0000171 p.cargo(command)
Chris Wailes54272ac2021-09-09 16:08:13 -0700172 .env("RUSTFLAGS", "-Zfuture-incompat-test")
173 .with_stderr_does_not_contain(FUTURE_OUTPUT)
174 .with_stderr_contains("warning: the following packages contain code that will be rejected by a future version of Rust: first-dep v0.0.1, second-dep v0.0.2")
Chris Wailes356b57e2022-01-13 10:08:24 -0800175 // Check that we don't have the 'triggers' message shown at the bottom of this loop,
176 // and that we don't explain how to show a per-package report
Chris Wailese3116c42021-07-13 14:40:48 -0700177 .with_stderr_does_not_contain("[..]triggers[..]")
Chris Wailes356b57e2022-01-13 10:08:24 -0800178 .with_stderr_does_not_contain("[..]--package[..]")
179 .with_stderr_does_not_contain("[..]-p[..]")
Chris Wailese3116c42021-07-13 14:40:48 -0700180 .run();
181
Charisee7878d542022-02-24 18:21:36 +0000182 p.cargo(command).arg("--future-incompat-report")
Chris Wailes54272ac2021-09-09 16:08:13 -0700183 .env("RUSTFLAGS", "-Zfuture-incompat-test")
184 .with_stderr_contains("warning: the following packages contain code that will be rejected by a future version of Rust: first-dep v0.0.1, second-dep v0.0.2")
Charisee9cf67802022-06-30 20:04:09 +0000185 .with_stderr_contains(" - first-dep@0.0.1")
186 .with_stderr_contains(" - second-dep@0.0.2")
Chris Wailes356b57e2022-01-13 10:08:24 -0800187 .run();
188
Charisee9cf67802022-06-30 20:04:09 +0000189 p.cargo("report future-incompatibilities").arg("--package").arg("first-dep@0.0.1")
Chris Wailes356b57e2022-01-13 10:08:24 -0800190 .with_stdout_contains("The package `first-dep v0.0.1` currently triggers the following future incompatibility lints:")
191 .with_stdout_contains(FUTURE_OUTPUT)
192 .with_stdout_does_not_contain("[..]second-dep-0.0.2/src[..]")
193 .run();
194
Charisee9cf67802022-06-30 20:04:09 +0000195 p.cargo("report future-incompatibilities").arg("--package").arg("second-dep@0.0.2")
Chris Wailes356b57e2022-01-13 10:08:24 -0800196 .with_stdout_contains("The package `second-dep v0.0.2` currently triggers the following future incompatibility lints:")
197 .with_stdout_contains(FUTURE_OUTPUT)
198 .with_stdout_does_not_contain("[..]first-dep-0.0.1/src[..]")
Chris Wailese3116c42021-07-13 14:40:48 -0700199 .run();
200 }
201
202 // Test that passing the correct id via '--id' doesn't generate a warning message
203 let output = p
Chris Wailes5c0824a2023-04-24 16:30:59 -0700204 .cargo("check")
Chris Wailes54272ac2021-09-09 16:08:13 -0700205 .env("RUSTFLAGS", "-Zfuture-incompat-test")
Chris Wailese3116c42021-07-13 14:40:48 -0700206 .exec_with_output()
207 .unwrap();
208
209 // Extract the 'id' from the stdout. We are looking
Chris Wailes2f3fdfe2021-07-29 10:56:18 -0700210 // for the id in a line of the form "run `cargo report future-incompatibilities --id yZ7S`"
Chris Wailese3116c42021-07-13 14:40:48 -0700211 // which is generated by Cargo to tell the user what command to run
212 // This is just to test that passing the id suppresses the warning mesasge. Any users needing
213 // access to the report from a shell script should use the `--future-incompat-report` flag
214 let stderr = std::str::from_utf8(&output.stderr).unwrap();
215
216 // Find '--id <ID>' in the output
Chris Wailes32f78352021-07-20 14:04:55 -0700217 let mut iter = stderr.split(' ');
Chris Wailese3116c42021-07-13 14:40:48 -0700218 iter.find(|w| *w == "--id").unwrap();
219 let id = iter
220 .next()
221 .unwrap_or_else(|| panic!("Unexpected output:\n{}", stderr));
222 // Strip off the trailing '`' included in the output
223 let id: String = id.chars().take_while(|c| *c != '`').collect();
224
Charisee7878d542022-02-24 18:21:36 +0000225 p.cargo(&format!("report future-incompatibilities --id {}", id))
Chris Wailes54272ac2021-09-09 16:08:13 -0700226 .with_stdout_contains("The package `first-dep v0.0.1` currently triggers the following future incompatibility lints:")
227 .with_stdout_contains("The package `second-dep v0.0.2` currently triggers the following future incompatibility lints:")
228 .run();
229
230 // Test without --id, and also the full output of the report.
231 let output = p
Charisee7878d542022-02-24 18:21:36 +0000232 .cargo("report future-incompat")
Chris Wailes54272ac2021-09-09 16:08:13 -0700233 .exec_with_output()
234 .unwrap();
235 let output = std::str::from_utf8(&output.stdout).unwrap();
236 assert!(output.starts_with("The following warnings were discovered"));
237 let mut lines = output
238 .lines()
239 // Skip the beginning of the per-package information.
240 .skip_while(|line| !line.starts_with("The package"));
241 for expected in &["first-dep v0.0.1", "second-dep v0.0.2"] {
242 assert_eq!(
243 &format!(
244 "The package `{}` currently triggers the following future incompatibility lints:",
245 expected
246 ),
Chris Wailes356b57e2022-01-13 10:08:24 -0800247 lines.next().unwrap(),
248 "Bad output:\n{}",
249 output
Chris Wailes54272ac2021-09-09 16:08:13 -0700250 );
251 let mut count = 0;
252 while let Some(line) = lines.next() {
253 if line.is_empty() {
254 break;
255 }
256 count += 1;
257 }
258 assert!(count > 0);
259 }
260 assert_eq!(lines.next(), None);
261}
262
Chariseeb1d32802022-09-22 15:38:41 +0000263#[cargo_test(
264 nightly,
265 reason = "-Zfuture-incompat-test requires nightly (permanently)"
266)]
Chris Wailes54272ac2021-09-09 16:08:13 -0700267fn color() {
Chris Wailes54272ac2021-09-09 16:08:13 -0700268 let p = simple_project();
269
Charisee7878d542022-02-24 18:21:36 +0000270 p.cargo("check")
Chris Wailes54272ac2021-09-09 16:08:13 -0700271 .env("RUSTFLAGS", "-Zfuture-incompat-test")
Chariseeb1d32802022-09-22 15:38:41 +0000272 .masquerade_as_nightly_cargo(&["future-incompat-test"])
Chris Wailes54272ac2021-09-09 16:08:13 -0700273 .run();
274
Charisee7878d542022-02-24 18:21:36 +0000275 p.cargo("report future-incompatibilities")
Chris Wailes54272ac2021-09-09 16:08:13 -0700276 .with_stdout_does_not_contain("[..]\x1b[[..]")
277 .run();
278
Charisee7878d542022-02-24 18:21:36 +0000279 p.cargo("report future-incompatibilities")
Chris Wailes54272ac2021-09-09 16:08:13 -0700280 .env("CARGO_TERM_COLOR", "always")
281 .with_stdout_contains("[..]\x1b[[..]")
282 .run();
283}
284
Chariseeb1d32802022-09-22 15:38:41 +0000285#[cargo_test(
286 nightly,
287 reason = "-Zfuture-incompat-test requires nightly (permanently)"
288)]
Chris Wailes54272ac2021-09-09 16:08:13 -0700289fn bad_ids() {
Chris Wailes54272ac2021-09-09 16:08:13 -0700290 let p = simple_project();
291
Charisee7878d542022-02-24 18:21:36 +0000292 p.cargo("report future-incompatibilities --id 1")
Chris Wailes54272ac2021-09-09 16:08:13 -0700293 .with_status(101)
294 .with_stderr("error: no reports are currently available")
295 .run();
296
Charisee7878d542022-02-24 18:21:36 +0000297 p.cargo("check")
Chris Wailes54272ac2021-09-09 16:08:13 -0700298 .env("RUSTFLAGS", "-Zfuture-incompat-test")
Chariseeb1d32802022-09-22 15:38:41 +0000299 .masquerade_as_nightly_cargo(&["future-incompat-test"])
Chris Wailes54272ac2021-09-09 16:08:13 -0700300 .run();
301
Charisee7878d542022-02-24 18:21:36 +0000302 p.cargo("report future-incompatibilities --id foo")
Chris Wailes54272ac2021-09-09 16:08:13 -0700303 .with_status(1)
304 .with_stderr("error: Invalid value: could not parse `foo` as a number")
305 .run();
306
Charisee7878d542022-02-24 18:21:36 +0000307 p.cargo("report future-incompatibilities --id 7")
Chris Wailes54272ac2021-09-09 16:08:13 -0700308 .with_status(101)
309 .with_stderr(
310 "\
311error: could not find report with ID 7
312Available IDs are: 1
313",
314 )
315 .run();
316}
317
Chariseeb1d32802022-09-22 15:38:41 +0000318#[cargo_test(
319 nightly,
320 reason = "-Zfuture-incompat-test requires nightly (permanently)"
321)]
Chris Wailes54272ac2021-09-09 16:08:13 -0700322fn suggestions_for_updates() {
Chris Wailes54272ac2021-09-09 16:08:13 -0700323 Package::new("with_updates", "1.0.0")
324 .file("src/lib.rs", FUTURE_EXAMPLE)
325 .publish();
326 Package::new("big_update", "1.0.0")
327 .file("src/lib.rs", FUTURE_EXAMPLE)
328 .publish();
329 Package::new("without_updates", "1.0.0")
330 .file("src/lib.rs", FUTURE_EXAMPLE)
331 .publish();
332
333 let p = project()
334 .file(
335 "Cargo.toml",
336 r#"
337 [package]
338 name = "foo"
339 version = "0.1.0"
340
341 [dependencies]
342 with_updates = "1"
343 big_update = "1"
344 without_updates = "1"
345 "#,
346 )
347 .file("src/lib.rs", "")
348 .build();
349
350 p.cargo("generate-lockfile").run();
351
352 Package::new("with_updates", "1.0.1")
353 .file("src/lib.rs", "")
354 .publish();
355 Package::new("with_updates", "1.0.2")
356 .file("src/lib.rs", "")
357 .publish();
Chris Wailes356b57e2022-01-13 10:08:24 -0800358 Package::new("with_updates", "3.0.1")
359 .file("src/lib.rs", "")
360 .publish();
Chris Wailes54272ac2021-09-09 16:08:13 -0700361 Package::new("big_update", "2.0.0")
362 .file("src/lib.rs", "")
363 .publish();
364
365 // This is a hack to force cargo to update the index. Cargo can't do this
366 // automatically because doing a network update on every build would be a
367 // bad idea. Under normal circumstances, we'll hope the user has done
368 // something else along the way to trigger an update (building some other
369 // project or something). This could use some more consideration of how to
370 // handle this better (maybe only trigger an update if it hasn't updated
371 // in a long while?).
372 p.cargo("update -p without_updates").run();
373
Chris Wailes356b57e2022-01-13 10:08:24 -0800374 let update_message = "\
375- Some affected dependencies have newer versions available.
376You may want to consider updating them to a newer version to see if the issue has been fixed.
377
378big_update v1.0.0 has the following newer versions available: 2.0.0
379with_updates v1.0.0 has the following newer versions available: 1.0.1, 1.0.2, 3.0.1
380";
381
Charisee7878d542022-02-24 18:21:36 +0000382 p.cargo("check --future-incompat-report")
Chariseeb1d32802022-09-22 15:38:41 +0000383 .masquerade_as_nightly_cargo(&["future-incompat-test"])
Chris Wailes54272ac2021-09-09 16:08:13 -0700384 .env("RUSTFLAGS", "-Zfuture-incompat-test")
Chris Wailes356b57e2022-01-13 10:08:24 -0800385 .with_stderr_contains(update_message)
Chris Wailes54272ac2021-09-09 16:08:13 -0700386 .run();
387
388 p.cargo("report future-incompatibilities")
Chris Wailes356b57e2022-01-13 10:08:24 -0800389 .with_stdout_contains(update_message)
390 .run()
Chris Wailese3116c42021-07-13 14:40:48 -0700391}