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