]> git.proxmox.com Git - cargo.git/blob - tests/testsuite/config_include.rs
ac210b777cb42b44c50bcbdccf4521a50ac867a8
[cargo.git] / tests / testsuite / config_include.rs
1 //! Tests for `include` config field.
2
3 use super::config::{assert_error, write_config, write_config_at, ConfigBuilder};
4 use cargo_test_support::{no_such_file_err_msg, paths, project};
5 use std::fs;
6
7 #[cargo_test]
8 fn gated() {
9 // Requires -Z flag.
10 write_config("include='other'");
11 write_config_at(
12 ".cargo/other",
13 "
14 othervalue = 1
15 ",
16 );
17 let config = ConfigBuilder::new().build();
18 assert_eq!(config.get::<Option<i32>>("othervalue").unwrap(), None);
19 let config = ConfigBuilder::new().unstable_flag("config-include").build();
20 assert_eq!(config.get::<i32>("othervalue").unwrap(), 1);
21 }
22
23 #[cargo_test]
24 fn simple() {
25 // Simple test.
26 write_config_at(
27 ".cargo/config",
28 "
29 include = 'other'
30 key1 = 1
31 key2 = 2
32 ",
33 );
34 write_config_at(
35 ".cargo/other",
36 "
37 key2 = 3
38 key3 = 4
39 ",
40 );
41 let config = ConfigBuilder::new().unstable_flag("config-include").build();
42 assert_eq!(config.get::<i32>("key1").unwrap(), 1);
43 assert_eq!(config.get::<i32>("key2").unwrap(), 2);
44 assert_eq!(config.get::<i32>("key3").unwrap(), 4);
45 }
46
47 #[cargo_test]
48 fn works_with_cli() {
49 write_config_at(
50 ".cargo/config.toml",
51 "
52 include = 'other.toml'
53 [build]
54 rustflags = ['-W', 'unused']
55 ",
56 );
57 write_config_at(
58 ".cargo/other.toml",
59 "
60 [build]
61 rustflags = ['-W', 'unsafe-code']
62 ",
63 );
64 let p = project().file("src/lib.rs", "").build();
65 p.cargo("build -v")
66 .with_stderr(
67 "\
68 [COMPILING] foo v0.0.1 [..]
69 [RUNNING] `rustc [..]-W unused`
70 [FINISHED] [..]
71 ",
72 )
73 .run();
74 p.cargo("build -v -Z config-include")
75 .masquerade_as_nightly_cargo()
76 .with_stderr(
77 "\
78 [COMPILING] foo v0.0.1 [..]
79 [RUNNING] `rustc [..]-W unsafe-code -W unused`
80 [FINISHED] [..]
81 ",
82 )
83 .run();
84 }
85
86 #[cargo_test]
87 fn left_to_right() {
88 // How it merges multiple includes.
89 write_config_at(
90 ".cargo/config",
91 "
92 include = ['one', 'two']
93 primary = 1
94 ",
95 );
96 write_config_at(
97 ".cargo/one",
98 "
99 one = 1
100 primary = 2
101 ",
102 );
103 write_config_at(
104 ".cargo/two",
105 "
106 two = 2
107 primary = 3
108 ",
109 );
110 let config = ConfigBuilder::new().unstable_flag("config-include").build();
111 assert_eq!(config.get::<i32>("primary").unwrap(), 1);
112 assert_eq!(config.get::<i32>("one").unwrap(), 1);
113 assert_eq!(config.get::<i32>("two").unwrap(), 2);
114 }
115
116 #[cargo_test]
117 fn missing_file() {
118 // Error when there's a missing file.
119 write_config("include='missing'");
120 let config = ConfigBuilder::new()
121 .unstable_flag("config-include")
122 .build_err();
123 assert_error(
124 config.unwrap_err(),
125 &format!(
126 "\
127 could not load Cargo configuration
128
129 Caused by:
130 failed to load config include `missing` from `[..]/.cargo/config`
131
132 Caused by:
133 failed to read configuration file `[..]/.cargo/missing`
134
135 Caused by:
136 {}",
137 no_such_file_err_msg()
138 ),
139 );
140 }
141
142 #[cargo_test]
143 fn cycle() {
144 // Detects a cycle.
145 write_config_at(".cargo/config", "include='one'");
146 write_config_at(".cargo/one", "include='two'");
147 write_config_at(".cargo/two", "include='config'");
148 let config = ConfigBuilder::new()
149 .unstable_flag("config-include")
150 .build_err();
151 assert_error(
152 config.unwrap_err(),
153 "\
154 could not load Cargo configuration
155
156 Caused by:
157 failed to load config include `one` from `[..]/.cargo/config`
158
159 Caused by:
160 failed to load config include `two` from `[..]/.cargo/one`
161
162 Caused by:
163 failed to load config include `config` from `[..]/.cargo/two`
164
165 Caused by:
166 config `include` cycle detected with path `[..]/.cargo/config`",
167 );
168 }
169
170 #[cargo_test]
171 fn cli_include() {
172 // Using --config with include.
173 // CLI takes priority over files.
174 write_config_at(
175 ".cargo/config",
176 "
177 foo = 1
178 bar = 2
179 ",
180 );
181 write_config_at(".cargo/config-foo", "foo = 2");
182 let config = ConfigBuilder::new()
183 .unstable_flag("config-include")
184 .config_arg("include='.cargo/config-foo'")
185 .build();
186 assert_eq!(config.get::<i32>("foo").unwrap(), 2);
187 assert_eq!(config.get::<i32>("bar").unwrap(), 2);
188 }
189
190 #[cargo_test]
191 fn bad_format() {
192 // Not a valid format.
193 write_config("include = 1");
194 let config = ConfigBuilder::new()
195 .unstable_flag("config-include")
196 .build_err();
197 assert_error(
198 config.unwrap_err(),
199 "\
200 could not load Cargo configuration
201
202 Caused by:
203 `include` expected a string or list, but found integer in `[..]/.cargo/config`",
204 );
205 }
206
207 #[cargo_test]
208 fn cli_include_failed() {
209 // Error message when CLI include fails to load.
210 let config = ConfigBuilder::new()
211 .unstable_flag("config-include")
212 .config_arg("include='foobar'")
213 .build_err();
214 assert_error(
215 config.unwrap_err(),
216 &format!(
217 "\
218 failed to load --config include
219
220 Caused by:
221 failed to load config include `foobar` from `--config cli option`
222
223 Caused by:
224 failed to read configuration file `[..]/foobar`
225
226 Caused by:
227 {}",
228 no_such_file_err_msg()
229 ),
230 );
231 }
232
233 #[cargo_test]
234 fn cli_merge_failed() {
235 // Error message when CLI include merge fails.
236 write_config("foo = ['a']");
237 write_config_at(
238 ".cargo/other",
239 "
240 foo = 'b'
241 ",
242 );
243 let config = ConfigBuilder::new()
244 .unstable_flag("config-include")
245 .config_arg("include='.cargo/other'")
246 .build_err();
247 // Maybe this error message should mention it was from an include file?
248 assert_error(
249 config.unwrap_err(),
250 "\
251 failed to merge --config key `foo` into `[..]/.cargo/config`
252
253 Caused by:
254 failed to merge config value from `[..]/.cargo/other` into `[..]/.cargo/config`: \
255 expected array, but found string",
256 );
257 }
258
259 #[cargo_test]
260 fn cli_path() {
261 // --config path_to_file
262 fs::write(paths::root().join("myconfig.toml"), "key = 123").unwrap();
263 let config = ConfigBuilder::new()
264 .cwd(paths::root())
265 .unstable_flag("config-include")
266 .config_arg("myconfig.toml")
267 .build();
268 assert_eq!(config.get::<u32>("key").unwrap(), 123);
269
270 let config = ConfigBuilder::new()
271 .unstable_flag("config-include")
272 .config_arg("missing.toml")
273 .build_err();
274 assert_error(
275 config.unwrap_err(),
276 "\
277 failed to parse value from --config argument `missing.toml` as a dotted key expression
278
279 Caused by:
280 TOML parse error at line 1, column 13
281 |
282 1 | missing.toml
283 | ^
284 Unexpected end of input
285 Expected `.` or `=`
286 ",
287 );
288 }