summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRadosław Kot <rdkt13@gmail.com>2021-04-24 19:44:27 +0200
committerRadosław Kot <rdkt13@gmail.com>2021-05-08 17:43:16 +0200
commit98662dd899d4eaab5dc2da07d5bb658960b588a6 (patch)
treec7513c9038ee817c62e444ff02507bca2da363bc
parent82d23c76a8637360e03c0b43d9a1c0c26d820d9f (diff)
Modify tests to use both ConfigBuilder and Config
-rw-r--r--src/builder.rs6
-rw-r--r--src/config.rs8
-rw-r--r--src/ser.rs2
-rw-r--r--src/source.rs20
-rw-r--r--tests/datetime.rs27
-rw-r--r--tests/errors.rs19
-rw-r--r--tests/file.rs28
-rw-r--r--tests/file_hjson.rs13
-rw-r--r--tests/file_ini.rs12
-rw-r--r--tests/file_json.rs27
-rw-r--r--tests/file_ron.rs13
-rw-r--r--tests/file_toml.rs13
-rw-r--r--tests/file_yaml.rs13
-rw-r--r--tests/get.rs8
-rw-r--r--tests/legacy/datetime.rs137
-rw-r--r--tests/legacy/errors.rs132
-rw-r--r--tests/legacy/file.rs56
-rw-r--r--tests/legacy/file_hjson.rs78
-rw-r--r--tests/legacy/file_ini.rs69
-rw-r--r--tests/legacy/file_json.rs102
-rw-r--r--tests/legacy/file_ron.rs80
-rw-r--r--tests/legacy/file_toml.rs92
-rw-r--r--tests/legacy/file_yaml.rs82
-rw-r--r--tests/legacy/get.rs272
-rw-r--r--tests/legacy/merge.rs49
-rw-r--r--tests/legacy/mod.rs12
-rw-r--r--tests/legacy/set.rs93
-rw-r--r--tests/legacy_tests.rs5
-rw-r--r--tests/merge.rs40
-rw-r--r--tests/set.rs111
30 files changed, 1456 insertions, 163 deletions
diff --git a/src/builder.rs b/src/builder.rs
index 8f3081c..8c0e82d 100644
--- a/src/builder.rs
+++ b/src/builder.rs
@@ -1,9 +1,7 @@
use std::str::FromStr;
use std::{collections::HashMap, iter::IntoIterator};
-use crate::{
- config::Config, error, error::ConfigError, path::Expression, source::Source, value::Value,
-};
+use crate::{config::Config, error, path::Expression, source::Source, value::Value};
/// A configuration builder
///
@@ -142,7 +140,7 @@ impl ConfigBuilder {
fn build_internal(
defaults: HashMap<Expression, Value>,
overrides: HashMap<Expression, Value>,
- sources: &Vec<Box<dyn Source + Send + Sync>>,
+ sources: &[Box<dyn Source + Send + Sync>],
) -> error::Result<Config> {
let mut cache: Value = HashMap::<String, Value>::new().into();
diff --git a/src/config.rs b/src/config.rs
index 5b4d40e..7b7da2d 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -56,6 +56,8 @@ impl Config {
T: Source + Send + Sync,
{
self.sources.push(Box::new(source));
+
+ #[allow(deprecated)]
self.refresh()
}
@@ -67,6 +69,8 @@ impl Config {
T: Source + Send + Sync,
{
self.sources.push(Box::new(source));
+
+ #[allow(deprecated)]
self.refresh()?;
Ok(self)
}
@@ -107,6 +111,8 @@ impl Config {
T: Into<Value>,
{
self.defaults.insert(key.parse()?, value.into());
+
+ #[allow(deprecated)]
self.refresh()
}
@@ -124,6 +130,8 @@ impl Config {
T: Into<Value>,
{
self.overrides.insert(key.parse()?, value.into());
+
+ #[allow(deprecated)]
self.refresh()
}
diff --git a/src/ser.rs b/src/ser.rs
index a303408..b5c7f4f 100644
--- a/src/ser.rs
+++ b/src/ser.rs
@@ -27,6 +27,8 @@ impl ConfigSerializer {
)))
}
};
+
+ #[allow(deprecated)]
self.output.set(&key, value.into())?;
Ok(())
}
diff --git a/src/source.rs b/src/source.rs
index 2b0eb30..dc5f3b5 100644
--- a/src/source.rs
+++ b/src/source.rs
@@ -55,6 +55,26 @@ impl Source for Vec<Box<dyn Source + Send + Sync>> {
}
}
+impl Source for [Box<dyn Source + Send + Sync>] {
+ fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
+ Box::new(self.to_owned())
+ }
+
+ fn collect(&self) -> Result<HashMap<String, Value>> {
+ let mut cache: Value = HashMap::<String, Value>::new().into();
+
+ for source in self {
+ source.collect_to(&mut cache)?;
+ }
+
+ if let ValueKind::Table(table) = cache.kind {
+ Ok(table)
+ } else {
+ unreachable!();
+ }
+ }
+}
+
impl<T> Source for Vec<T>
where
T: Source + Sync + Send,
diff --git a/tests/datetime.rs b/tests/datetime.rs
index 471da47..1bdce3c 100644
--- a/tests/datetime.rs
+++ b/tests/datetime.rs
@@ -14,8 +14,10 @@ use chrono::{DateTime, TimeZone, Utc};
use config::*;
fn make() -> Config {
- Config::default()
- .merge(File::from_str(
+ let mut builder = Config::builder();
+
+ builder
+ .add_source(File::from_str(
r#"
{
"json_datetime": "2017-05-10T02:14:53Z"
@@ -23,22 +25,19 @@ fn make() -> Config {
"#,
FileFormat::Json,
))
- .unwrap()
- .merge(File::from_str(
+ .add_source(File::from_str(
r#"
yaml_datetime: 2017-06-12T10:58:30Z
"#,
FileFormat::Yaml,
))
- .unwrap()
- .merge(File::from_str(
+ .add_source(File::from_str(
r#"
toml_datetime = 2017-05-11T14:55:15Z
"#,
FileFormat::Toml,
))
- .unwrap()
- .merge(File::from_str(
+ .add_source(File::from_str(
r#"
{
"hjson_datetime": "2017-05-10T02:14:53Z"
@@ -46,24 +45,22 @@ fn make() -> Config {
"#,
FileFormat::Hjson,
))
- .unwrap()
- .merge(File::from_str(
+ .add_source(File::from_str(
r#"
ini_datetime = 2017-05-10T02:14:53Z
"#,
FileFormat::Ini,
))
- .unwrap()
- .merge(File::from_str(
+ .add_source(File::from_str(
r#"
(
ron_datetime: "2021-04-19T11:33:02Z"
)
"#,
FileFormat::Ron,
- ))
- .unwrap()
- .clone()
+ ));
+
+ builder.build().unwrap()
}
#[test]
diff --git a/tests/errors.rs b/tests/errors.rs
index cb7f637..b47d821 100644
--- a/tests/errors.rs
+++ b/tests/errors.rs
@@ -10,17 +10,16 @@ use std::path::PathBuf;
use config::*;
fn make() -> Config {
- let mut c = Config::default();
- c.merge(File::new("tests/Settings", FileFormat::Toml))
- .unwrap();
-
- c
+ let mut c = Config::builder();
+ c.add_source(File::new("tests/Settings", FileFormat::Toml));
+ c.build().unwrap()
}
#[test]
fn test_error_parse() {
- let mut c = Config::default();
- let res = c.merge(File::new("tests/Settings-invalid", FileFormat::Toml));
+ let mut c = Config::builder();
+ c.add_source(File::new("tests/Settings-invalid", FileFormat::Toml));
+ let res = c.build();
let path: PathBuf = ["tests", "Settings-invalid.toml"].iter().collect();
@@ -121,9 +120,9 @@ inner:
test: ABC
"#;
- let mut cfg = Config::default();
- cfg.merge(File::from_str(CFG, FileFormat::Yaml)).unwrap();
- let e = cfg.try_into::<Outer>().unwrap_err();
+ let mut cfg = Config::builder();
+ cfg.add_source(File::from_str(CFG, FileFormat::Yaml));
+ let e = cfg.build().unwrap().try_into::<Outer>().unwrap_err();
if let ConfigError::Type {
key: Some(path), ..
} = e
diff --git a/tests/file.rs b/tests/file.rs
index 0680c2a..8292426 100644
--- a/tests/file.rs
+++ b/tests/file.rs
@@ -6,16 +6,18 @@ use config::*;
#[test]
fn test_file_not_required() {
- let mut c = Config::default();
- let res = c.merge(File::new("tests/NoSettings", FileFormat::Yaml).required(false));
+ let mut c = Config::builder();
+ c.add_source(File::new("tests/NoSettings", FileFormat::Yaml).required(false));
+ let res = c.build();
assert!(res.is_ok());
}
#[test]
fn test_file_required_not_found() {
- let mut c = Config::default();
- let res = c.merge(File::new("tests/NoSettings", FileFormat::Yaml));
+ let mut c = Config::builder();
+ c.add_source(File::new("tests/NoSettings", FileFormat::Yaml));
+ let res = c.build();
assert!(res.is_err());
assert_eq!(
@@ -26,9 +28,10 @@ fn test_file_required_not_found() {
#[test]
fn test_file_auto() {
- let mut c = Config::default();
- c.merge(File::with_name("tests/Settings-production"))
- .unwrap();
+ let mut builder = Config::builder();
+ builder.add_source(File::with_name("tests/Settings-production"));
+
+ let c = builder.build().unwrap();
assert_eq!(c.get("debug").ok(), Some(false));
assert_eq!(c.get("production").ok(), Some(true));
@@ -36,8 +39,9 @@ fn test_file_auto() {
#[test]
fn test_file_auto_not_found() {
- let mut c = Config::default();
- let res = c.merge(File::with_name("tests/NoSettings"));
+ let mut c = Config::builder();
+ c.add_source(File::with_name("tests/NoSettings"));
+ let res = c.build();
assert!(res.is_err());
assert_eq!(
@@ -48,8 +52,10 @@ fn test_file_auto_not_found() {
#[test]
fn test_file_ext() {
- let mut c = Config::default();
- c.merge(File::with_name("tests/Settings.json")).unwrap();
+ let mut builder = Config::builder();
+ builder.add_source(File::with_name("tests/Settings.json"));
+
+ let c = builder.build().unwrap();
assert_eq!(c.get("debug").ok(), Some(true));
assert_eq!(c.get("production").ok(), Some(false));
diff --git a/tests/file_hjson.rs b/tests/file_hjson.rs
index 4ef48ac..5d9f24d 100644
--- a/tests/file_hjson.rs
+++ b/tests/file_hjson.rs
@@ -35,11 +35,9 @@ struct Settings {
}
fn make() -> Config {
- let mut c = Config::default();
- c.merge(File::new("tests/Settings", FileFormat::Hjson))
- .unwrap();
-
- c
+ let mut c = Config::builder();
+ c.add_source(File::new("tests/Settings", FileFormat::Hjson));
+ c.build().unwrap()
}
#[test]
@@ -68,8 +66,9 @@ fn test_file() {
#[test]
fn test_error_parse() {
- let mut c = Config::default();
- let res = c.merge(File::new("tests/Settings-invalid", FileFormat::Hjson));
+ let mut c = Config::builder();
+ c.add_source(File::new("tests/Settings-invalid", FileFormat::Hjson));
+ let res = c.build();
let path: PathBuf = ["tests", "Settings-invalid.hjson"].iter().collect();
diff --git a/tests/file_ini.rs b/tests/file_ini.rs
index 437c0d9..1f57272 100644
--- a/tests/file_ini.rs
+++ b/tests/file_ini.rs
@@ -28,10 +28,9 @@ struct Settings {
}
fn make() -> Config {
- let mut c = Config::default();
- c.merge(File::new("tests/Settings", FileFormat::Ini))
- .unwrap();
- c
+ let mut c = Config::builder();
+ c.add_source(File::new("tests/Settings", FileFormat::Ini));
+ c.build().unwrap()
}
#[test]
@@ -56,8 +55,9 @@ fn test_file() {
#[test]
fn test_error_parse() {
- let mut c = Config::default();
- let res = c.merge(File::new("tests/Settings-invalid", FileFormat::Ini));
+ let mut c = Config::builder();
+ c.add_source(File::new("tests/Settings-invalid", FileFormat::Ini));
+ let res = c.build();
let path: PathBuf = ["tests", "Settings-invalid.ini"].iter().collect();
diff --git a/tests/file_json.rs b/tests/file_json.rs
index bd27572..9d457e4 100644
--- a/tests/file_json.rs
+++ b/tests/file_json.rs
@@ -35,11 +35,9 @@ struct Settings {
}
fn make() -> Config {
- let mut c = Config::default();
- c.merge(File::new("tests/Settings", FileFormat::Json))
- .unwrap();
-
- c
+ let mut c = Config::builder();
+ c.add_source(File::new("tests/Settings", FileFormat::Json));
+ c.build().unwrap()
}
#[test]
@@ -68,8 +66,9 @@ fn test_file() {
#[test]
fn test_error_parse() {
- let mut c = Config::default();
- let res = c.merge(File::new("tests/Settings-invalid", FileFormat::Json));
+ let mut c = Config::builder();
+ c.add_source(File::new("tests/Settings-invalid", FileFormat::Json));
+ let res = c.build();
let path_with_extension: PathBuf = ["tests", "Settings-invalid.json"].iter().collect();
@@ -85,17 +84,17 @@ fn test_error_parse() {
#[test]
fn test_json_vec() {
- let c = Config::default()
- .merge(File::from_str(
- r#"
+ let mut builder = Config::builder();
+ builder.add_source(File::from_str(
+ r#"
{
"WASTE": ["example_dir1", "example_dir2"]
}
"#,
- FileFormat::Json,
- ))
- .unwrap()
- .clone();
+ FileFormat::Json,
+ ));
+
+ let c = builder.build().unwrap();
let v = c.get_array("WASTE").unwrap();
let mut vi = v.into_iter();
diff --git a/tests/file_ron.rs b/tests/file_ron.rs
index 1f1ede2..1e5c6d3 100644
--- a/tests/file_ron.rs
+++ b/tests/file_ron.rs
@@ -36,11 +36,9 @@ struct Settings {
}
fn make() -> Config {
- let mut c = Config::default();
- c.merge(File::new("tests/Settings", FileFormat::Ron))
- .unwrap();
-
- c
+ let mut c = Config::builder();
+ c.add_source(File::new("tests/Settings", FileFormat::Ron));
+ c.build().unwrap()
}
#[test]
@@ -70,8 +68,9 @@ fn test_file() {
#[test]
fn test_error_parse() {
- let mut c = Config::default();
- let res = c.merge(File::new("tests/Settings-invalid", FileFormat::Ron));
+ let mut c = Config::builder();
+ c.add_source(File::new("tests/Settings-invalid", FileFormat::Ron));
+ let res = c.build();
let path_with_extension: PathBuf = ["tests", "Settings-invalid.ron"].iter().collect();
diff --git a/tests/file_toml.rs b/tests/file_toml.rs
index 83b2630..cee80b7 100644
--- a/tests/file_toml.rs
+++ b/tests/file_toml.rs
@@ -44,11 +44,9 @@ struct Settings {
#[cfg(test)]
fn make() -> Config {
- let mut c = Config::default();
- c.merge(File::new("tests/Settings", FileFormat::Toml))
- .unwrap();
-
- c
+ let mut c = Config::builder();
+ c.add_source(File::new("tests/Settings", FileFormat::Toml));
+ c.build().unwrap()
}
#[test]
@@ -79,8 +77,9 @@ fn test_file() {
#[test]
fn test_error_parse() {
- let mut c = Config::default();
- let res = c.merge(File::new("tests/Settings-invalid", FileFormat::Toml));
+ let mut c = Config::builder();
+ c.add_source(File::new("tests/Settings-invalid", FileFormat::Toml));
+ let res = c.build();
let path_with_extension: PathBuf = ["tests", "Settings-invalid.toml"].iter().collect();
diff --git a/tests/file_yaml.rs b/tests/file_yaml.rs
index b2746cd..645829a 100644
--- a/tests/file_yaml.rs
+++ b/tests/file_yaml.rs
@@ -35,11 +35,9 @@ struct Settings {
}
fn make() -> Config {
- let mut c = Config::default();
- c.merge(File::new("tests/Settings", FileFormat::Yaml))
- .unwrap();
-
- c
+ let mut c = Config::builder();
+ c.add_source(File::new("tests/Settings", FileFormat::Yaml));
+ c.build().unwrap()
}
#[test]
@@ -68,8 +66,9 @@ fn test_file() {
#[test]
fn test_error_parse() {
- let mut c = Config::default();
- let res = c.merge(File::new("tests/Settings-invalid", FileFormat::Yaml));
+ let mut c = Config::builder();
+ c.add_source(File::new("tests/Settings-invalid", FileFormat::Yaml));
+ let res = c.build();
let path_with_extension: PathBuf = ["tests", "Settings-invalid.yaml"].iter().collect();
diff --git a/tests/get.rs b/tests/get.rs
index 1856cfb..10e2927 100644
--- a/tests/get.rs
+++ b/tests/get.rs
@@ -31,11 +31,9 @@ struct Settings {
}
fn make() -> Config {
- let mut c = Config::default();
- c.merge(File::new("tests/Settings", FileFormat::Toml))
- .unwrap();
-
- c
+ let mut c = Config::builder();
+ c.add_source(File::new("tests/Settings", FileFormat::Toml));
+ c.build().unwrap()
}
#[test]
diff --git a/tests/legacy/datetime.rs b/tests/legacy/datetime.rs
new file mode 100644
index 0000000..cde3edd
--- /dev/null
+++ b/tests/legacy/datetime.rs
@@ -0,0 +1,137 @@
+#![cfg(all(
+ feature = "toml",
+ feature = "json",
+ feature = "hjson",
+ feature = "yaml",
+ feature = "ini",
+ feature = "ron",
+))]
+
+extern crate chrono;
+extern crate config;
+
+use self::chrono::{DateTime, TimeZone, Utc};
+use self::config::*;
+
+fn make() -> Config {
+ Config::default()
+ .merge(File::from_str(
+ r#"
+ {
+ "json_datetime": "2017-05-10T02:14:53Z"
+ }
+ "#,
+ FileFormat::Json,
+ ))
+ .unwrap()
+ .merge(File::from_str(
+ r#"
+ yaml_datetime: 2017-06-12T10:58:30Z
+ "#,
+ FileFormat::Yaml,
+ ))
+ .unwrap()
+ .merge(File::from_str(
+ r#"
+ toml_datetime = 2017-05-11T14:55:15Z
+ "#,
+ FileFormat::Toml,
+ ))
+ .unwrap()
+ .merge(File::from_str(
+ r#"
+ {
+ "hjson_datetime": "2017-05-10T02:14:53Z"
+ }
+ "#,
+ FileFormat::Hjson,
+ ))
+ .unwrap()
+ .merge(File::from_str(
+ r#"
+ ini_datetime = 2017-05-10T02:14:53Z
+ "#,
+ FileFormat::Ini,
+ ))
+ .unwrap()
+ .merge(File::from_str(
+ r#"
+ (
+ ron_datetime: "2021-04-19T11:33:02Z"
+ )
+ "#,
+ FileFormat::Ron,
+ ))
+ .unwrap()
+ .clone()
+}
+
+#[test]
+fn test_datetime_string() {
+ let s = make();
+
+ // JSON
+ let date: String = s.get("json_datetime").unwrap();
+
+ assert_eq!(&date, "2017-05-10T02:14:53Z");
+
+ // TOML
+ let date: String = s.get("toml_datetime").unwrap();
+
+ assert_eq!(&date, "2017-05-11T14:55:15Z");
+
+ // YAML
+ let date: String = s.get("yaml_datetime").unwrap();
+
+ assert_eq!(&date, "2017-06-12T10:58:30Z");
+
+ // HJSON
+ let date: String = s.get("hjson_datetime").unwrap();
+
+ assert_eq!(&date, "2017-05-10T02:14:53Z");
+
+ // INI
+ let date: String = s.get("ini_datetime").unwrap();
+
+ assert_eq!(&date, "2017-05-10T02:14:53Z");
+
+ // RON
+ let date: String = s.get("ron_datetime").unwrap();
+
+ assert_eq!(&date, "2021-04-19T11:33:02Z");
+}
+
+#[test]
+fn test_datetime() {
+ let s = make();
+
+ // JSON
+ let date: DateTime<Utc> = s.get("json_datetime").unwrap();
+
+ assert_eq!(date, Utc.ymd(2017, 5, 10).and_hms(2, 14, 53));
+
+ // TOML
+ let date: DateTime<Utc> = s.get("toml_datetime").unwrap();
+
+ assert_eq!(date, Utc.ymd(2017, 5, 11).and_hms(14, 55, 15));
+
+ // YAML
+ let date: DateTime<Utc> = s.get("yaml_datetime").unwrap();
+
+ assert_eq!(date, Utc.ymd(2017, 6, 12).and_hms(10, 58, 30));
+
+ // HJSON
+ let date: DateTime<Utc> = s.get("hjson_datetime").unwrap();
+
+ assert_eq!(date, Utc.ymd(2017, 5, 10).and_hms(2, 14, 53));
+
+ // INI
+ let date: DateTime<Utc> = s.get("ini_datetime").unwrap();
+
+ assert_eq!(date, Utc.ymd(2017, 5, 10).and_hms(2, 14, 53));
+
+ // RON
+ let date: DateTime<Utc> = s.get("ron_datetime").unwrap();
+
+ assert_eq!(date, Utc.ymd(2021, 4, 19).and_hms(11, 33, 2));
+}
diff --git a/tests/legacy/errors.rs b/tests/legacy/errors.rs
new file mode 100644
index 0000000..9058c80
--- /dev/null
+++ b/tests/legacy/errors.rs
@@ -0,0 +1,132 @@
+#![cfg(feature = "toml")]
+
+extern crate config;
+
+use std::path::PathBuf;
+
+use self::config::*;
+
+fn make() -> Config {
+ let mut c = Config::default();
+ c.merge(File::new("tests/Settings", FileFormat::Toml))
+ .unwrap();
+
+ c
+}
+
+#[test]
+fn test_error_parse() {
+ let mut c = Config::default();
+ let res = c.merge(File::new("tests/Settings-invalid", FileFormat::Toml));
+
+ let path: PathBuf = ["tests", "Settings-invalid.toml"].iter().collect();
+
+ assert!(res.is_err());
+ assert_eq!(
+ res.unwrap_err().to_string(),
+ format!(
+ "invalid TOML value, did you mean to use a quoted string? at line 2 column 9 in {}",
+ path.display()
+ )
+ );
+}
+
+#[test]
+fn test_error_type() {
+ let c = make();
+
+ let res = c.get::<bool>("boolean_s_parse");
+
+ let path: PathBuf = ["tests", "Settings.toml"].iter().collect();
+
+ assert!(res.is_err());
+ assert_eq!(
+ res.unwrap_err().to_string(),
+ format!(
+ "invalid type: string \"fals\", expected a boolean for key `boolean_s_parse` in {}",
+ path.display()
+ )
+ );
+}
+
+#[test]
+fn test_error_type_detached() {
+ let c = make();
+
+ let value = c.get::<Value>("boolean_s_parse").unwrap();
+ let res = value.try_into::<bool>();
+
+ assert!(res.is_err());
+ assert_eq!(
+ res.unwrap_err().to_string(),
+ "invalid type: string \"fals\", expected a boolean".to_string()
+ );
+}
+
+#[test]
+fn test_error_enum_de() {
+ #[derive(Debug, Deserialize, PartialEq)]
+ enum Diode {
+ Off,
+ Brightness(i32),
+ Blinking(i32, i32),
+ Pattern { name: String, inifinite: bool },
+ }
+
+ let on_v: Value = "on".into();
+ let on_d = on_v.try_into::<Diode>();
+ assert_eq!(
+ on_d.unwrap_err().to_string(),
+ "enum Diode does not have variant constructor on".to_string()
+ );
+
+ let array_v: Value = vec![100, 100].into();
+ let array_d = array_v.try_into::<Diode>();
+ assert_eq!(
+ array_d.unwrap_err().to_string(),
+ "value of enum Diode should be represented by either string or table with exactly one key"
+ );
+
+ let confused_v: Value = [
+ ("Brightness".to_string(), 100.into()),
+ ("Blinking".to_string(), vec![300, 700].into()),
+ ]
+ .iter()
+ .cloned()
+ .collect::<std::collections::HashMap<String, Value>>()
+ .into();
+ let confused_d = confused_v.try_into::<Diode>();
+ assert_eq!(
+ confused_d.unwrap_err().to_string(),
+ "value of enum Diode should be represented by either string or table with exactly one key"
+ );
+}
+
+#[test]
+fn error_with_path() {
+ #[derive(Debug, Deserialize)]
+ struct Inner {
+ test: i32,
+ }
+
+ #[derive(Debug, Deserialize)]
+ struct Outer {
+ inner: Inner,
+ }
+ const CFG: &str = r#"
+inner:
+ test: ABC
+"#;
+
+ let mut cfg = Config::default();
+ cfg.merge(File::from_str(CFG, FileFormat::Yaml)).unwrap();
+ let e = cfg.try_into::<Outer>().unwrap_err();
+ if let ConfigError::Type {
+ key: Some(path), ..
+ } = e
+ {
+ assert_eq!(path, "inner.test");
+ } else {
+ panic!("Wrong error {:?}", e);
+ }
+}
diff --git a/tests/legacy/file.rs b/tests/legacy/file.rs
new file mode 100644
index 0000000..7ec8e65
--- /dev/null
+++ b/tests/legacy/file.rs
@@ -0,0 +1,56 @@
+#![cfg(feature = "yaml")]
+
+extern crate config;
+
+use self::config::*;
+
+#[test]
+fn test_file_not_required() {
+ let mut c = Config::default();
+ let res = c.merge(File::new("tests/NoSettings", FileFormat::Yaml).required(false));
+
+ assert!(res.is_ok());
+}
+
+#[test]
+fn test_file_required_not_found() {
+ let mut c = Config::default();
+ let res = c.merge(File::new("tests/NoSettings", FileFormat::Yaml));
+
+ assert!(res.is_err());
+ assert_eq!(
+ res.unwrap_err().to_string(),
+ "configuration file \"tests/NoSettings\" not found".to_string()
+ );
+}
+
+#[test]
+fn test_file_auto() {
+ let mut c = Config::default();
+ c.merge(File::with_name("tests/Settings-production"))
+ .unwrap();
+
+ assert_eq!(c.get("debug").ok(), Some(false));
+ assert_eq!(c.get("production").ok(), Some(true));
+}
+
+#[test]
+fn test_file_auto_not_found() {
+ let mut c = Config::default();
+ let res = c.merge(File::with_name("tests/NoSettings"));
+
+ assert!(res.is_err());
+ assert_eq!(
+ res.unwrap_err().to_string(),
+ "configuration file \"tests/NoSettings\" not found".to_string()
+ );
+}
+
+#[test]
+fn test_file_ext() {
+ let mut c = Config::default();
+ c.merge(File::with_name("tests/Settings.json")).unwrap();
+
+ assert_eq!(c.get("debug").ok(), Some(true));
+ assert_eq!(c.get("production").ok(), Some(false));
+}
diff --git a/tests/legacy/file_hjson.rs b/tests/legacy/file_hjson.rs
new file mode 100644
index 0000000..120bcc6
--- /dev/null
+++ b/tests/legacy/file_hjson.rs
@@ -0,0 +1,78 @@
+#![cfg(feature = "hjson")]
+
+extern crate config;
+extern crate float_cmp;
+extern crate serde;
+
+use std::collections::HashMap;
+use std::path::PathBuf;
+
+use self::config::*;
+use self::float_cmp::ApproxEqUlps;
+
+#[derive(Debug, Deserialize)]
+struct Place {
+ name: String,
+ longitude: f64,
+ latitude: f64,
+ favorite: bool,
+ telephone: Option<String>,
+ reviews: u64,
+ creator: HashMap<String, Value>,
+ rating: Option<f32>,
+}
+
+#[derive(Debug, Deserialize)]
+struct Settings {
+ debug: f64,
+ production: Option<String>,
+ place: Place,
+ #[serde(rename = "arr")]
+ elements: Vec<String>,
+}
+
+fn make() -> Config {
+ let mut c = Config::default();
+ c.merge(File::new("tests/Settings", FileFormat::Hjson))
+ .unwrap();
+
+ c
+}
+
+#[test]
+fn test_file() {
+ let c = make();
+
+ // Deserialize the entire file as single struct
+ let s: Settings = c.try_into().unwrap();
+
+ assert!(s.debug.approx_eq_ulps(&1.0, 2));
+ assert_eq!(s.production, Some("false".to_string()));
+ assert_eq!(s.place.name, "Torre di Pisa");
+ assert!(s.place.longitude.approx_eq_ulps(&43.7224985, 2));
+ assert!(s.place.latitude.approx_eq_ulps(&10.3970522, 2));
+ assert_eq!(s.place.favorite, false);
+ assert_eq!(s.place.reviews, 3866);
+ assert_eq!(s.place.rating, Some(4.5));
+ assert_eq!(s.place.telephone, None);
+ assert_eq!(s.elements.len(), 10);
+ assert_eq!(s.elements[3], "4".to_string());
+ assert_eq!(
+ s.place.c