1 //! Tests for profiles defined in config files.
2
3 use cargo_test_support::paths::CargoPathExt;
4 use cargo_test_support::registry::Package;
5 use cargo_test_support::{basic_lib_manifest, paths, project};
6
7 #[cargo_test]
profile_config_validate_warnings()8 fn profile_config_validate_warnings() {
9 let p = project()
10 .file("Cargo.toml", &basic_lib_manifest("foo"))
11 .file("src/lib.rs", "")
12 .file(
13 ".cargo/config",
14 r#"
15 [profile.test]
16 opt-level = 3
17
18 [profile.asdf]
19 opt-level = 3
20
21 [profile.dev]
22 bad-key = true
23
24 [profile.dev.build-override]
25 bad-key-bo = true
26
27 [profile.dev.package.bar]
28 bad-key-bar = true
29 "#,
30 )
31 .build();
32
33 p.cargo("build")
34 .with_stderr_unordered(
35 "\
36 [WARNING] unused config key `profile.dev.bad-key` in `[..].cargo/config`
37 [WARNING] unused config key `profile.dev.package.bar.bad-key-bar` in `[..].cargo/config`
38 [WARNING] unused config key `profile.dev.build-override.bad-key-bo` in `[..].cargo/config`
39 [COMPILING] foo [..]
40 [FINISHED] [..]
41 ",
42 )
43 .run();
44 }
45
46 #[cargo_test]
profile_config_error_paths()47 fn profile_config_error_paths() {
48 // Errors in config show where the error is located.
49 let p = project()
50 .file("Cargo.toml", &basic_lib_manifest("foo"))
51 .file("src/lib.rs", "")
52 .file(
53 ".cargo/config",
54 r#"
55 [profile.dev]
56 opt-level = 3
57 "#,
58 )
59 .file(
60 paths::home().join(".cargo/config"),
61 r#"
62 [profile.dev]
63 rpath = "foo"
64 "#,
65 )
66 .build();
67
68 p.cargo("build")
69 .with_status(101)
70 .with_stderr(
71 "\
72 [ERROR] error in [..]/foo/.cargo/config: could not load config key `profile.dev`
73
74 Caused by:
75 error in [..]/home/.cargo/config: `profile.dev.rpath` expected true/false, but found a string
76 ",
77 )
78 .run();
79 }
80
81 #[cargo_test]
profile_config_validate_errors()82 fn profile_config_validate_errors() {
83 let p = project()
84 .file("Cargo.toml", &basic_lib_manifest("foo"))
85 .file("src/lib.rs", "")
86 .file(
87 ".cargo/config",
88 r#"
89 [profile.dev.package.foo]
90 panic = "abort"
91 "#,
92 )
93 .build();
94
95 p.cargo("build")
96 .with_status(101)
97 .with_stderr(
98 "\
99 [ERROR] config profile `dev` is not valid (defined in `[..]/foo/.cargo/config`)
100
101 Caused by:
102 `panic` may not be specified in a `package` profile
103 ",
104 )
105 .run();
106 }
107
108 #[cargo_test]
profile_config_syntax_errors()109 fn profile_config_syntax_errors() {
110 let p = project()
111 .file("Cargo.toml", &basic_lib_manifest("foo"))
112 .file("src/lib.rs", "")
113 .file(
114 ".cargo/config",
115 r#"
116 [profile.dev]
117 codegen-units = "foo"
118 "#,
119 )
120 .build();
121
122 p.cargo("build")
123 .with_status(101)
124 .with_stderr(
125 "\
126 [ERROR] error in [..]/.cargo/config: could not load config key `profile.dev`
127
128 Caused by:
129 error in [..]/foo/.cargo/config: `profile.dev.codegen-units` expected an integer, but found a string
130 ",
131 )
132 .run();
133 }
134
135 #[cargo_test]
profile_config_override_spec_multiple()136 fn profile_config_override_spec_multiple() {
137 let p = project()
138 .file(
139 "Cargo.toml",
140 r#"
141 [package]
142 name = "foo"
143 version = "0.0.1"
144
145 [dependencies]
146 bar = { path = "bar" }
147 "#,
148 )
149 .file(
150 ".cargo/config",
151 r#"
152 [profile.dev.package.bar]
153 opt-level = 3
154
155 [profile.dev.package."bar:0.5.0"]
156 opt-level = 3
157 "#,
158 )
159 .file("src/lib.rs", "")
160 .file("bar/Cargo.toml", &basic_lib_manifest("bar"))
161 .file("bar/src/lib.rs", "")
162 .build();
163
164 // Unfortunately this doesn't tell you which file, hopefully it's not too
165 // much of a problem.
166 p.cargo("build -v")
167 .with_status(101)
168 .with_stderr(
169 "\
170 [ERROR] multiple package overrides in profile `dev` match package `bar v0.5.0 ([..])`
171 found package specs: bar, bar:0.5.0",
172 )
173 .run();
174 }
175
176 #[cargo_test]
profile_config_all_options()177 fn profile_config_all_options() {
178 // Ensure all profile options are supported.
179 let p = project()
180 .file("src/main.rs", "fn main() {}")
181 .file(
182 ".cargo/config",
183 r#"
184 [profile.release]
185 opt-level = 1
186 debug = true
187 debug-assertions = true
188 overflow-checks = false
189 rpath = true
190 lto = true
191 codegen-units = 2
192 panic = "abort"
193 incremental = true
194 "#,
195 )
196 .build();
197
198 p.cargo("build --release -v")
199 .env_remove("CARGO_INCREMENTAL")
200 .with_stderr(
201 "\
202 [COMPILING] foo [..]
203 [RUNNING] `rustc --crate-name foo [..] \
204 -C opt-level=1 \
205 -C panic=abort \
206 -C lto[..]\
207 -C codegen-units=2 \
208 -C debuginfo=2 \
209 -C debug-assertions=on \
210 -C overflow-checks=off [..]\
211 -C rpath [..]\
212 -C incremental=[..]
213 [FINISHED] release [optimized + debuginfo] [..]
214 ",
215 )
216 .run();
217 }
218
219 #[cargo_test]
profile_config_override_precedence()220 fn profile_config_override_precedence() {
221 // Config values take precedence over manifest values.
222 let p = project()
223 .file(
224 "Cargo.toml",
225 r#"
226 [package]
227 name = "foo"
228 version = "0.0.1"
229
230 [dependencies]
231 bar = {path = "bar"}
232
233 [profile.dev]
234 codegen-units = 2
235
236 [profile.dev.package.bar]
237 opt-level = 3
238 "#,
239 )
240 .file("src/lib.rs", "")
241 .file("bar/Cargo.toml", &basic_lib_manifest("bar"))
242 .file("bar/src/lib.rs", "")
243 .file(
244 ".cargo/config",
245 r#"
246 [profile.dev.package.bar]
247 opt-level = 2
248 "#,
249 )
250 .build();
251
252 p.cargo("build -v")
253 .with_stderr(
254 "\
255 [COMPILING] bar [..]
256 [RUNNING] `rustc --crate-name bar [..] -C opt-level=2[..]-C codegen-units=2 [..]
257 [COMPILING] foo [..]
258 [RUNNING] `rustc --crate-name foo [..]-C codegen-units=2 [..]
259 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
260 )
261 .run();
262 }
263
264 #[cargo_test]
profile_config_no_warn_unknown_override()265 fn profile_config_no_warn_unknown_override() {
266 let p = project()
267 .file("Cargo.toml", &basic_lib_manifest("foo"))
268 .file("src/lib.rs", "")
269 .file(
270 ".cargo/config",
271 r#"
272 [profile.dev.package.bar]
273 codegen-units = 4
274 "#,
275 )
276 .build();
277
278 p.cargo("build")
279 .with_stderr_does_not_contain("[..]warning[..]")
280 .run();
281 }
282
283 #[cargo_test]
profile_config_mixed_types()284 fn profile_config_mixed_types() {
285 let p = project()
286 .file("Cargo.toml", &basic_lib_manifest("foo"))
287 .file("src/lib.rs", "")
288 .file(
289 ".cargo/config",
290 r#"
291 [profile.dev]
292 opt-level = 3
293 "#,
294 )
295 .file(
296 paths::home().join(".cargo/config"),
297 r#"
298 [profile.dev]
299 opt-level = 's'
300 "#,
301 )
302 .build();
303
304 p.cargo("build -v")
305 .with_stderr_contains("[..]-C opt-level=3 [..]")
306 .run();
307 }
308
309 #[cargo_test]
named_config_profile()310 fn named_config_profile() {
311 // Exercises config named profies.
312 // foo -> middle -> bar -> dev
313 // middle exists in Cargo.toml, the others in .cargo/config
314 use super::config::ConfigBuilder;
315 use cargo::core::compiler::{CompileKind, CompileMode};
316 use cargo::core::profiles::{Profiles, UnitFor};
317 use cargo::core::{PackageId, Workspace};
318 use cargo::util::interning::InternedString;
319 use std::fs;
320 paths::root().join(".cargo").mkdir_p();
321 fs::write(
322 paths::root().join(".cargo/config"),
323 r#"
324 [profile.foo]
325 inherits = "middle"
326 codegen-units = 2
327 [profile.foo.build-override]
328 codegen-units = 6
329 [profile.foo.package.dep]
330 codegen-units = 7
331
332 [profile.middle]
333 inherits = "bar"
334 codegen-units = 3
335
336 [profile.bar]
337 inherits = "dev"
338 codegen-units = 4
339 debug = 1
340 "#,
341 )
342 .unwrap();
343 fs::write(
344 paths::root().join("Cargo.toml"),
345 r#"
346 [workspace]
347
348 [profile.middle]
349 inherits = "bar"
350 codegen-units = 1
351 opt-level = 1
352 [profile.middle.package.dep]
353 overflow-checks = false
354
355 [profile.foo.build-override]
356 codegen-units = 5
357 debug-assertions = false
358 [profile.foo.package.dep]
359 codegen-units = 8
360 "#,
361 )
362 .unwrap();
363 let config = ConfigBuilder::new().build();
364 let profile_name = InternedString::new("foo");
365 let ws = Workspace::new(&paths::root().join("Cargo.toml"), &config).unwrap();
366 let profiles = Profiles::new(&ws, profile_name).unwrap();
367
368 let crates_io = cargo::core::source::SourceId::crates_io(&config).unwrap();
369 let a_pkg = PackageId::new("a", "0.1.0", crates_io).unwrap();
370 let dep_pkg = PackageId::new("dep", "0.1.0", crates_io).unwrap();
371
372 // normal package
373 let mode = CompileMode::Build;
374 let kind = CompileKind::Host;
375 let p = profiles.get_profile(a_pkg, true, true, UnitFor::new_normal(), mode, kind);
376 assert_eq!(p.name, "foo");
377 assert_eq!(p.codegen_units, Some(2)); // "foo" from config
378 assert_eq!(p.opt_level, "1"); // "middle" from manifest
379 assert_eq!(p.debuginfo, Some(1)); // "bar" from config
380 assert_eq!(p.debug_assertions, true); // "dev" built-in (ignore build-override)
381 assert_eq!(p.overflow_checks, true); // "dev" built-in (ignore package override)
382
383 // build-override
384 let bo = profiles.get_profile(a_pkg, true, true, UnitFor::new_host(false), mode, kind);
385 assert_eq!(bo.name, "foo");
386 assert_eq!(bo.codegen_units, Some(6)); // "foo" build override from config
387 assert_eq!(bo.opt_level, "0"); // default to zero
388 assert_eq!(bo.debuginfo, Some(1)); // SAME as normal
389 assert_eq!(bo.debug_assertions, false); // "foo" build override from manifest
390 assert_eq!(bo.overflow_checks, true); // SAME as normal
391
392 // package overrides
393 let po = profiles.get_profile(dep_pkg, false, true, UnitFor::new_normal(), mode, kind);
394 assert_eq!(po.name, "foo");
395 assert_eq!(po.codegen_units, Some(7)); // "foo" package override from config
396 assert_eq!(po.opt_level, "1"); // SAME as normal
397 assert_eq!(po.debuginfo, Some(1)); // SAME as normal
398 assert_eq!(po.debug_assertions, true); // SAME as normal
399 assert_eq!(po.overflow_checks, false); // "middle" package override from manifest
400 }
401
402 #[cargo_test]
named_env_profile()403 fn named_env_profile() {
404 // Environment variables used to define a named profile.
405 let p = project()
406 .file(
407 "Cargo.toml",
408 r#"
409 [package]
410 name = "foo"
411 version = "0.1.0"
412 "#,
413 )
414 .file("src/lib.rs", "")
415 .build();
416
417 p.cargo("build -v --profile=other")
418 .env("CARGO_PROFILE_OTHER_CODEGEN_UNITS", "1")
419 .env("CARGO_PROFILE_OTHER_INHERITS", "dev")
420 .with_stderr_contains("[..]-C codegen-units=1 [..]")
421 .run();
422 }
423
424 #[cargo_test]
test_with_dev_profile()425 fn test_with_dev_profile() {
426 // The `test` profile inherits from `dev` for both local crates and
427 // dependencies.
428 Package::new("somedep", "1.0.0").publish();
429 let p = project()
430 .file(
431 "Cargo.toml",
432 r#"
433 [package]
434 name = "foo"
435 version = "0.1.0"
436
437 [dependencies]
438 somedep = "1.0"
439 "#,
440 )
441 .file("src/lib.rs", "")
442 .build();
443 p.cargo("test --lib --no-run -v")
444 .env("CARGO_PROFILE_DEV_DEBUG", "0")
445 .with_stderr(
446 "\
447 [UPDATING] [..]
448 [DOWNLOADING] [..]
449 [DOWNLOADED] [..]
450 [COMPILING] somedep v1.0.0
451 [RUNNING] `rustc --crate-name somedep [..]-C debuginfo=0[..]
452 [COMPILING] foo v0.1.0 [..]
453 [RUNNING] `rustc --crate-name foo [..]-C debuginfo=0[..]
454 [FINISHED] [..]
455 ",
456 )
457 .run();
458 }
459