3
3
use super :: config:: { assert_error, assert_match, read_output, write_config, ConfigBuilder } ;
4
4
use cargo:: util:: config:: Definition ;
5
5
use cargo_test_support:: { paths, project} ;
6
- use std:: fs ;
6
+ use std:: { collections :: HashMap , fs } ;
7
7
8
8
#[ cargo_test]
9
9
fn config_gated ( ) {
@@ -234,11 +234,64 @@ fn merge_array_mixed_def_paths() {
234
234
}
235
235
236
236
#[ cargo_test]
237
- fn unused_key ( ) {
238
- // Unused key passed on command line .
237
+ fn enforces_format ( ) {
238
+ // These dotted key expressions should all be fine .
239
239
let config = ConfigBuilder :: new ( )
240
- . config_arg ( "build={jobs=1, unused=2}" )
240
+ . config_arg ( "a=true" )
241
+ . config_arg ( " b.a = true " )
242
+ . config_arg ( "c.\" b\" .'a'=true" )
243
+ . config_arg ( "d.\" =\" .'='=true" )
244
+ . config_arg ( "e.\" '\" .'\" '=true" )
241
245
. build ( ) ;
246
+ assert_eq ! ( config. get:: <bool >( "a" ) . unwrap( ) , true ) ;
247
+ assert_eq ! (
248
+ config. get:: <HashMap <String , bool >>( "b" ) . unwrap( ) ,
249
+ HashMap :: from( [ ( "a" . to_string( ) , true ) ] )
250
+ ) ;
251
+ assert_eq ! (
252
+ config
253
+ . get:: <HashMap <String , HashMap <String , bool >>>( "c" )
254
+ . unwrap( ) ,
255
+ HashMap :: from( [ ( "b" . to_string( ) , HashMap :: from( [ ( "a" . to_string( ) , true ) ] ) ) ] )
256
+ ) ;
257
+ assert_eq ! (
258
+ config
259
+ . get:: <HashMap <String , HashMap <String , bool >>>( "d" )
260
+ . unwrap( ) ,
261
+ HashMap :: from( [ ( "=" . to_string( ) , HashMap :: from( [ ( "=" . to_string( ) , true ) ] ) ) ] )
262
+ ) ;
263
+ assert_eq ! (
264
+ config
265
+ . get:: <HashMap <String , HashMap <String , bool >>>( "e" )
266
+ . unwrap( ) ,
267
+ HashMap :: from( [ ( "'" . to_string( ) , HashMap :: from( [ ( "\" " . to_string( ) , true ) ] ) ) ] )
268
+ ) ;
269
+
270
+ // But anything that's not a dotted key expression should be disallowed.
271
+ let _ = ConfigBuilder :: new ( )
272
+ . config_arg ( "[a] foo=true" )
273
+ . build_err ( )
274
+ . unwrap_err ( ) ;
275
+ let _ = ConfigBuilder :: new ( )
276
+ . config_arg ( "a = true\n b = true" )
277
+ . build_err ( )
278
+ . unwrap_err ( ) ;
279
+
280
+ // We also disallow overwriting with tables since it makes merging unclear.
281
+ let _ = ConfigBuilder :: new ( )
282
+ . config_arg ( "a = { first = true, second = false }" )
283
+ . build_err ( )
284
+ . unwrap_err ( ) ;
285
+ let _ = ConfigBuilder :: new ( )
286
+ . config_arg ( "a = { first = true }" )
287
+ . build_err ( )
288
+ . unwrap_err ( ) ;
289
+ }
290
+
291
+ #[ cargo_test]
292
+ fn unused_key ( ) {
293
+ // Unused key passed on command line.
294
+ let config = ConfigBuilder :: new ( ) . config_arg ( "build.unused = 2" ) . build ( ) ;
242
295
243
296
config. build_config ( ) . unwrap ( ) ;
244
297
let output = read_output ( config) ;
@@ -284,7 +337,7 @@ fn bad_parse() {
284
337
assert_error (
285
338
config. unwrap_err ( ) ,
286
339
"\
287
- failed to parse --config argument `abc`
340
+ failed to parse value from --config argument `abc` as a dotted key expression
288
341
289
342
Caused by:
290
343
TOML parse error at line 1, column 4
@@ -295,6 +348,12 @@ Unexpected end of input
295
348
Expected `.` or `=`
296
349
" ,
297
350
) ;
351
+
352
+ let config = ConfigBuilder :: new ( ) . config_arg ( "" ) . build_err ( ) ;
353
+ assert_error (
354
+ config. unwrap_err ( ) ,
355
+ "--config argument `` was not a TOML dotted key expression (such as `build.jobs = 2`)" ,
356
+ ) ;
298
357
}
299
358
300
359
#[ cargo_test]
@@ -305,14 +364,55 @@ fn too_many_values() {
305
364
config. unwrap_err ( ) ,
306
365
"\
307
366
--config argument `a=1
308
- b=2` expected exactly one key=value pair, got 2 keys " ,
367
+ b=2` was not a TOML dotted key expression (such as `build.jobs = 2`) " ,
309
368
) ;
369
+ }
310
370
311
- let config = ConfigBuilder :: new ( ) . config_arg ( "" ) . build_err ( ) ;
371
+ #[ cargo_test]
372
+ fn no_inline_table_value ( ) {
373
+ // Disallow inline tables
374
+ let config = ConfigBuilder :: new ( )
375
+ . config_arg ( "a.b={c = \" d\" }" )
376
+ . build_err ( ) ;
377
+ assert_error (
378
+ config. unwrap_err ( ) ,
379
+ "--config argument `a.b={c = \" d\" }` sets a value to an inline table, which is not accepted"
380
+ ) ;
381
+ }
382
+
383
+ #[ cargo_test]
384
+ fn no_array_of_tables_values ( ) {
385
+ // Disallow array-of-tables when not in dotted form
386
+ let config = ConfigBuilder :: new ( )
387
+ . config_arg ( "[[a.b]]\n c = \" d\" " )
388
+ . build_err ( ) ;
389
+ assert_error (
390
+ config. unwrap_err ( ) ,
391
+ "\
392
+ --config argument `[[a.b]]
393
+ c = \" d\" ` was not a TOML dotted key expression (such as `build.jobs = 2`)" ,
394
+ ) ;
395
+ }
396
+
397
+ #[ cargo_test]
398
+ fn no_comments ( ) {
399
+ // Disallow comments in dotted form.
400
+ let config = ConfigBuilder :: new ( )
401
+ . config_arg ( "a.b = \" c\" # exactly" )
402
+ . build_err ( ) ;
403
+ assert_error (
404
+ config. unwrap_err ( ) ,
405
+ "\
406
+ --config argument `a.b = \" c\" # exactly` includes non-whitespace decoration",
407
+ ) ;
408
+
409
+ let config = ConfigBuilder :: new ( )
410
+ . config_arg ( "# exactly\n a.b = \" c\" " )
411
+ . build_err ( ) ;
312
412
assert_error (
313
413
config. unwrap_err ( ) ,
314
414
"\
315
- --config argument `` expected exactly one key=value pair, got 0 keys ",
415
+ --config argument `# exactly\n a.b = \" c \" ` includes non-whitespace decoration ",
316
416
) ;
317
417
}
318
418
0 commit comments