cargo/tests/testsuite/config_include.rs
2021-03-24 20:21:09 -07:00

283 lines
6.6 KiB
Rust

//! Tests for `include` config field.
use super::config::{assert_error, write_config, write_config_at, ConfigBuilder};
use cargo_test_support::{no_such_file_err_msg, paths, project};
use std::fs;
#[cargo_test]
fn gated() {
// Requires -Z flag.
write_config("include='other'");
write_config_at(
".cargo/other",
"
othervalue = 1
",
);
let config = ConfigBuilder::new().build();
assert_eq!(config.get::<Option<i32>>("othervalue").unwrap(), None);
let config = ConfigBuilder::new().unstable_flag("config-include").build();
assert_eq!(config.get::<i32>("othervalue").unwrap(), 1);
}
#[cargo_test]
fn simple() {
// Simple test.
write_config_at(
".cargo/config",
"
include = 'other'
key1 = 1
key2 = 2
",
);
write_config_at(
".cargo/other",
"
key2 = 3
key3 = 4
",
);
let config = ConfigBuilder::new().unstable_flag("config-include").build();
assert_eq!(config.get::<i32>("key1").unwrap(), 1);
assert_eq!(config.get::<i32>("key2").unwrap(), 2);
assert_eq!(config.get::<i32>("key3").unwrap(), 4);
}
#[cargo_test]
fn works_with_cli() {
write_config_at(
".cargo/config.toml",
"
include = 'other.toml'
[build]
rustflags = ['-W', 'unused']
",
);
write_config_at(
".cargo/other.toml",
"
[build]
rustflags = ['-W', 'unsafe-code']
",
);
let p = project().file("src/lib.rs", "").build();
p.cargo("build -v")
.with_stderr(
"\
[COMPILING] foo v0.0.1 [..]
[RUNNING] `rustc [..]-W unused`
[FINISHED] [..]
",
)
.run();
p.cargo("build -v -Z config-include")
.masquerade_as_nightly_cargo()
.with_stderr(
"\
[COMPILING] foo v0.0.1 [..]
[RUNNING] `rustc [..]-W unsafe-code -W unused`
[FINISHED] [..]
",
)
.run();
}
#[cargo_test]
fn left_to_right() {
// How it merges multiple includes.
write_config_at(
".cargo/config",
"
include = ['one', 'two']
primary = 1
",
);
write_config_at(
".cargo/one",
"
one = 1
primary = 2
",
);
write_config_at(
".cargo/two",
"
two = 2
primary = 3
",
);
let config = ConfigBuilder::new().unstable_flag("config-include").build();
assert_eq!(config.get::<i32>("primary").unwrap(), 1);
assert_eq!(config.get::<i32>("one").unwrap(), 1);
assert_eq!(config.get::<i32>("two").unwrap(), 2);
}
#[cargo_test]
fn missing_file() {
// Error when there's a missing file.
write_config("include='missing'");
let config = ConfigBuilder::new()
.unstable_flag("config-include")
.build_err();
assert_error(
config.unwrap_err(),
&format!(
"\
could not load Cargo configuration
Caused by:
failed to load config include `missing` from `[..]/.cargo/config`
Caused by:
failed to read configuration file `[..]/.cargo/missing`
Caused by:
{}",
no_such_file_err_msg()
),
);
}
#[cargo_test]
fn cycle() {
// Detects a cycle.
write_config_at(".cargo/config", "include='one'");
write_config_at(".cargo/one", "include='two'");
write_config_at(".cargo/two", "include='config'");
let config = ConfigBuilder::new()
.unstable_flag("config-include")
.build_err();
assert_error(
config.unwrap_err(),
"\
could not load Cargo configuration
Caused by:
failed to load config include `one` from `[..]/.cargo/config`
Caused by:
failed to load config include `two` from `[..]/.cargo/one`
Caused by:
failed to load config include `config` from `[..]/.cargo/two`
Caused by:
config `include` cycle detected with path `[..]/.cargo/config`",
);
}
#[cargo_test]
fn cli_include() {
// Using --config with include.
// CLI takes priority over files.
write_config_at(
".cargo/config",
"
foo = 1
bar = 2
",
);
write_config_at(".cargo/config-foo", "foo = 2");
let config = ConfigBuilder::new()
.unstable_flag("config-include")
.config_arg("include='.cargo/config-foo'")
.build();
assert_eq!(config.get::<i32>("foo").unwrap(), 2);
assert_eq!(config.get::<i32>("bar").unwrap(), 2);
}
#[cargo_test]
fn bad_format() {
// Not a valid format.
write_config("include = 1");
let config = ConfigBuilder::new()
.unstable_flag("config-include")
.build_err();
assert_error(
config.unwrap_err(),
"\
could not load Cargo configuration
Caused by:
`include` expected a string or list, but found integer in `[..]/.cargo/config`",
);
}
#[cargo_test]
fn cli_include_failed() {
// Error message when CLI include fails to load.
let config = ConfigBuilder::new()
.unstable_flag("config-include")
.config_arg("include='foobar'")
.build_err();
assert_error(
config.unwrap_err(),
&format!(
"\
failed to load --config include
Caused by:
failed to load config include `foobar` from `--config cli option`
Caused by:
failed to read configuration file `[..]/foobar`
Caused by:
{}",
no_such_file_err_msg()
),
);
}
#[cargo_test]
fn cli_merge_failed() {
// Error message when CLI include merge fails.
write_config("foo = ['a']");
write_config_at(
".cargo/other",
"
foo = 'b'
",
);
let config = ConfigBuilder::new()
.unstable_flag("config-include")
.config_arg("include='.cargo/other'")
.build_err();
// Maybe this error message should mention it was from an include file?
assert_error(
config.unwrap_err(),
"\
failed to merge --config key `foo` into `[..]/.cargo/config`
Caused by:
failed to merge config value from `[..]/.cargo/other` into `[..]/.cargo/config`: \
expected array, but found string",
);
}
#[cargo_test]
fn cli_path() {
// --config path_to_file
fs::write(paths::root().join("myconfig.toml"), "key = 123").unwrap();
let config = ConfigBuilder::new()
.cwd(paths::root())
.unstable_flag("config-include")
.config_arg("myconfig.toml")
.build();
assert_eq!(config.get::<u32>("key").unwrap(), 123);
let config = ConfigBuilder::new()
.unstable_flag("config-include")
.config_arg("missing.toml")
.build_err();
assert_error(
config.unwrap_err(),
"\
failed to parse --config argument `missing.toml`
Caused by:
expected an equals, found eof at line 1 column 13",
);
}