From 98662dd899d4eaab5dc2da07d5bb658960b588a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20Kot?= Date: Sat, 24 Apr 2021 19:44:27 +0200 Subject: Modify tests to use both ConfigBuilder and Config --- src/builder.rs | 6 +- src/config.rs | 8 ++ src/ser.rs | 2 + src/source.rs | 20 ++++ tests/datetime.rs | 27 ++--- tests/errors.rs | 19 ++-- tests/file.rs | 28 +++-- tests/file_hjson.rs | 13 +-- tests/file_ini.rs | 12 +- tests/file_json.rs | 27 +++-- tests/file_ron.rs | 13 +-- tests/file_toml.rs | 13 +-- tests/file_yaml.rs | 13 +-- tests/get.rs | 8 +- tests/legacy/datetime.rs | 137 +++++++++++++++++++++++ tests/legacy/errors.rs | 132 ++++++++++++++++++++++ tests/legacy/file.rs | 56 ++++++++++ tests/legacy/file_hjson.rs | 78 +++++++++++++ tests/legacy/file_ini.rs | 69 ++++++++++++ tests/legacy/file_json.rs | 102 +++++++++++++++++ tests/legacy/file_ron.rs | 80 +++++++++++++ tests/legacy/file_toml.rs | 92 +++++++++++++++ tests/legacy/file_yaml.rs | 82 ++++++++++++++ tests/legacy/get.rs | 272 +++++++++++++++++++++++++++++++++++++++++++++ tests/legacy/merge.rs | 49 ++++++++ tests/legacy/mod.rs | 12 ++ tests/legacy/set.rs | 93 ++++++++++++++++ tests/legacy_tests.rs | 5 + tests/merge.rs | 40 +++---- tests/set.rs | 111 +++++++++--------- 30 files changed, 1456 insertions(+), 163 deletions(-) create mode 100644 tests/legacy/datetime.rs create mode 100644 tests/legacy/errors.rs create mode 100644 tests/legacy/file.rs create mode 100644 tests/legacy/file_hjson.rs create mode 100644 tests/legacy/file_ini.rs create mode 100644 tests/legacy/file_json.rs create mode 100644 tests/legacy/file_ron.rs create mode 100644 tests/legacy/file_toml.rs create mode 100644 tests/legacy/file_yaml.rs create mode 100644 tests/legacy/get.rs create mode 100644 tests/legacy/merge.rs create mode 100644 tests/legacy/mod.rs create mode 100644 tests/legacy/set.rs create mode 100644 tests/legacy_tests.rs 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, overrides: HashMap, - sources: &Vec>, + sources: &[Box], ) -> error::Result { let mut cache: Value = HashMap::::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, { self.defaults.insert(key.parse()?, value.into()); + + #[allow(deprecated)] self.refresh() } @@ -124,6 +130,8 @@ impl Config { T: Into, { 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> { } } +impl Source for [Box] { + fn clone_into_box(&self) -> Box { + Box::new(self.to_owned()) + } + + fn collect(&self) -> Result> { + let mut cache: Value = HashMap::::new().into(); + + for source in self { + source.collect_to(&mut cache)?; + } + + if let ValueKind::Table(table) = cache.kind { + Ok(table) + } else { + unreachable!(); + } + } +} + impl Source for Vec 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::().unwrap_err(); + let mut cfg = Config::builder(); + cfg.add_source(File::from_str(CFG, FileFormat::Yaml)); + let e = cfg.build().unwrap().try_into::().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 = s.get("json_datetime").unwrap(); + + assert_eq!(date, Utc.ymd(2017, 5, 10).and_hms(2, 14, 53)); + + // TOML + let date: DateTime = s.get("toml_datetime").unwrap(); + + assert_eq!(date, Utc.ymd(2017, 5, 11).and_hms(14, 55, 15)); + + // YAML + let date: DateTime = s.get("yaml_datetime").unwrap(); + + assert_eq!(date, Utc.ymd(2017, 6, 12).and_hms(10, 58, 30)); + + // HJSON + let date: DateTime = s.get("hjson_datetime").unwrap(); + + assert_eq!(date, Utc.ymd(2017, 5, 10).and_hms(2, 14, 53)); + + // INI + let date: DateTime = s.get("ini_datetime").unwrap(); + + assert_eq!(date, Utc.ymd(2017, 5, 10).and_hms(2, 14, 53)); + + // RON + let date: DateTime = 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::("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::("boolean_s_parse").unwrap(); + let res = value.try_into::(); + + 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::(); + 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::(); + 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::>() + .into(); + let confused_d = confused_v.try_into::(); + 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::().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, + reviews: u64, + creator: HashMap, + rating: Option, +} + +#[derive(Debug, Deserialize)] +struct Settings { + debug: f64, + production: Option, + place: Place, + #[serde(rename = "arr")] + elements: Vec, +} + +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.creator["name"].clone().into_string().unwrap(), + "John Smith".to_string() + ); +} + +#[test] +fn test_error_parse() { + let mut c = Config::default(); + let res = c.merge(File::new("tests/Settings-invalid", FileFormat::Hjson)); + + let path: PathBuf = ["tests", "Settings-invalid.hjson"].iter().collect(); + + assert!(res.is_err()); + assert_eq!( + res.unwrap_err().to_string(), + format!("Found a punctuator where a key name was expected (check your syntax or use quotes if the key name includes {{}}[],: or whitespace) at line 4 column 1 in {}", path.display()) + ); +} diff --git a/tests/legacy/file_ini.rs b/tests/legacy/file_ini.rs new file mode 100644 index 0000000..8f8f88e --- /dev/null +++ b/tests/legacy/file_ini.rs @@ -0,0 +1,69 @@ +#![cfg(feature = "ini")] + +extern crate config; +extern crate float_cmp; +extern crate serde; + +use std::path::PathBuf; + +use self::config::*; + +#[derive(Debug, Deserialize, PartialEq)] +struct Place { + name: String, + longitude: f64, + latitude: f64, + favorite: bool, + reviews: u64, + rating: Option, +} + +#[derive(Debug, Deserialize, PartialEq)] +struct Settings { + debug: f64, + place: Place, +} + +fn make() -> Config { + let mut c = Config::default(); + c.merge(File::new("tests/Settings", FileFormat::Ini)) + .unwrap(); + c +} + +#[test] +fn test_file() { + let c = make(); + let s: Settings = c.try_into().unwrap(); + assert_eq!( + s, + Settings { + debug: 1.0, + place: Place { + name: String::from("Torre di Pisa"), + longitude: 43.7224985, + latitude: 10.3970522, + favorite: false, + reviews: 3866, + rating: Some(4.5), + }, + } + ); +} + +#[test] +fn test_error_parse() { + let mut c = Config::default(); + let res = c.merge(File::new("tests/Settings-invalid", FileFormat::Ini)); + + let path: PathBuf = ["tests", "Settings-invalid.ini"].iter().collect(); + + assert!(res.is_err()); + assert_eq!( + res.unwrap_err().to_string(), + format!( + r#"2:0 expecting "[Some('='), Some(':')]" but found EOF. in {}"#, + path.display() + ) + ); +} diff --git a/tests/legacy/file_json.rs b/tests/legacy/file_json.rs new file mode 100644 index 0000000..e2300c6 --- /dev/null +++ b/tests/legacy/file_json.rs @@ -0,0 +1,102 @@ +#![cfg(feature = "json")] + +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, + reviews: u64, + creator: HashMap, + rating: Option, +} + +#[derive(Debug, Deserialize)] +struct Settings { + debug: f64, + production: Option, + place: Place, + #[serde(rename = "arr")] + elements: Vec, +} + +fn make() -> Config { + let mut c = Config::default(); + c.merge(File::new("tests/Settings", FileFormat::Json)) + .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.creator["name"].clone().into_string().unwrap(), + "John Smith".to_string() + ); +} + +#[test] +fn test_error_parse() { + let mut c = Config::default(); + let res = c.merge(File::new("tests/Settings-invalid", FileFormat::Json)); + + let path_with_extension: PathBuf = ["tests", "Settings-invalid.json"].iter().collect(); + + assert!(res.is_err()); + assert_eq!( + res.unwrap_err().to_string(), + format!( + "expected `:` at line 4 column 1 in {}", + path_with_extension.display() + ) + ); +} + +#[test] +fn test_json_vec() { + let c = Config::default() + .merge(File::from_str( + r#" + { + "WASTE": ["example_dir1", "example_dir2"] + } + "#, + FileFormat::Json, + )) + .unwrap() + .clone(); + + let v = c.get_array("WASTE").unwrap(); + let mut vi = v.into_iter(); + assert_eq!(vi.next().unwrap().into_string().unwrap(), "example_dir1"); + assert_eq!(vi.next().unwrap().into_string().unwrap(), "example_dir2"); + assert!(vi.next().is_none()); +} diff --git a/tests/legacy/file_ron.rs b/tests/legacy/file_ron.rs new file mode 100644 index 0000000..91f88f3 --- /dev/null +++ b/tests/legacy/file_ron.rs @@ -0,0 +1,80 @@ +#![cfg(feature = "ron")] + +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 { + initials: (char, char), + name: String, + longitude: f64, + latitude: f64, + favorite: bool, + telephone: Option, + reviews: u64, + creator: HashMap, + rating: Option, +} + +#[derive(Debug, Deserialize)] +struct Settings { + debug: f64, + production: Option, + place: Place, + #[serde(rename = "arr")] + elements: Vec, +} + +fn make() -> Config { + let mut c = Config::default(); + c.merge(File::new("tests/Settings", FileFormat::Ron)) + .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.initials, ('T', 'P')); + 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.creator["name"].clone().into_string().unwrap(), + "John Smith".to_string() + ); +} + +#[test] +fn test_error_parse() { + let mut c = Config::default(); + let res = c.merge(File::new("tests/Settings-invalid", FileFormat::Ron)); + + let path_with_extension: PathBuf = ["tests", "Settings-invalid.ron"].iter().collect(); + + assert!(res.is_err()); + assert_eq!( + res.unwrap_err().to_string(), + format!("4:1: Expected colon in {}", path_with_extension.display()) + ); +} diff --git a/tests/legacy/file_toml.rs b/tests/legacy/file_toml.rs new file mode 100644 index 0000000..2271962 --- /dev/null +++ b/tests/legacy/file_toml.rs @@ -0,0 +1,92 @@ +#![cfg(feature = "toml")] + +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 { + number: PlaceNumber, + name: String, + longitude: f64, + latitude: f64, + favorite: bool, + telephone: Option, + reviews: u64, + creator: HashMap, + rating: Option, +} + +#[derive(Debug, Deserialize, PartialEq)] +struct PlaceNumber(u8); + +#[derive(Debug, Deserialize, PartialEq)] +struct AsciiCode(i8); + +#[derive(Debug, Deserialize)] +struct Settings { + debug: f64, + production: Option, + code: AsciiCode, + place: Place, + #[serde(rename = "arr")] + elements: Vec, +} + +#[cfg(test)] +fn make() -> Config { + let mut c = Config::default(); + c.merge(File::new("tests/Settings", FileFormat::Toml)) + .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.code, AsciiCode(53)); + assert_eq!(s.place.number, PlaceNumber(1)); + 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.creator["name"].clone().into_string().unwrap(), + "John Smith".to_string() + ); +} + +#[test] +fn test_error_parse() { + let mut c = Config::default(); + let res = c.merge(File::new("tests/Settings-invalid", FileFormat::Toml)); + + let path_with_extension: 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_with_extension.display() + ) + ); +} diff --git a/tests/legacy/file_yaml.rs b/tests/legacy/file_yaml.rs new file mode 100644 index 0000000..5d7a60f --- /dev/null +++ b/tests/legacy/file_yaml.rs @@ -0,0 +1,82 @@ +#![cfg(feature = "yaml")] + +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, + reviews: u64, + creator: HashMap, + rating: Option, +} + +#[derive(Debug, Deserialize)] +struct Settings { + debug: f64, + production: Option, + place: Place, + #[serde(rename = "arr")] + elements: Vec, +} + +fn make() -> Config { + let mut c = Config::default(); + c.merge(File::new("tests/Settings", FileFormat::Yaml)) + .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.creator["name"].clone().into_string().unwrap(), + "John Smith".to_string() + ); +} + +#[test] +fn test_error_parse() { + let mut c = Config::default(); + let res = c.merge(File::new("tests/Settings-invalid", FileFormat::Yaml)); + + let path_with_extension: PathBuf = ["tests", "Settings-invalid.yaml"].iter().collect(); + + assert!(res.is_err()); + assert_eq!( + res.unwrap_err().to_string(), + format!( + "while parsing a block mapping, did not find expected key at \ + line 2 column 1 in {}", + path_with_extension.display() + ) + ); +} diff --git a/tests/legacy/get.rs b/tests/legacy/get.rs new file mode 100644 index 0000000..48a7b43 --- /dev/null +++ b/tests/legacy/get.rs @@ -0,0 +1,272 @@ +#![cfg(feature = "toml")] + +extern crate config; +extern crate float_cmp; +extern crate serde; + +use std::collections::{HashMap, HashSet}; + +use self::config::*; +use self::float_cmp::ApproxEqUlps; + +#[derive(Debug, Deserialize)] +struct Place { + name: String, + longitude: f64, + latitude: f64, + favorite: bool, + telephone: Option, + reviews: u64, + rating: Option, +} + +#[derive(Debug, Deserialize)] +struct Settings { + debug: f64, + production: Option, + place: Place, +} + +fn make() -> Config { + let mut c = Config::default(); + c.merge(File::new("tests/Settings", FileFormat::Toml)) + .unwrap(); + + c +} + +#[test] +fn test_not_found() { + let c = make(); + let res = c.get::("not_found"); + + assert!(res.is_err()); + assert_eq!( + res.unwrap_err().to_string(), + "configuration property \"not_found\" not found".to_string() + ); +} + +#[test] +fn test_scalar() { + let c = make(); + + assert_eq!(c.get("debug").ok(), Some(true)); + assert_eq!(c.get("production").ok(), Some(false)); +} + +#[test] +fn test_scalar_type_loose() { + let c = make(); + + assert_eq!(c.get("debug").ok(), Some(true)); + assert_eq!(c.get("debug").ok(), Some("true".to_string())); + assert_eq!(c.get("debug").ok(), Some(1)); + assert_eq!(c.get("debug").ok(), Some(1.0)); + + assert_eq!(c.get("debug_s").ok(), Some(true)); + assert_eq!(c.get("debug_s").ok(), Some("true".to_string())); + assert_eq!(c.get("debug_s").ok(), Some(1)); + assert_eq!(c.get("debug_s").ok(), Some(1.0)); + + assert_eq!(c.get("production").ok(), Some(false)); + assert_eq!(c.get("production").ok(), Some("false".to_string())); + assert_eq!(c.get("production").ok(), Some(0)); + assert_eq!(c.get("production").ok(), Some(0.0)); + + assert_eq!(c.get("production_s").ok(), Some(false)); + assert_eq!(c.get("production_s").ok(), Some("false".to_string())); + assert_eq!(c.get("production_s").ok(), Some(0)); + assert_eq!(c.get("production_s").ok(), Some(0.0)); +} + +#[test] +fn test_get_scalar_path() { + let c = make(); + + assert_eq!(c.get("place.favorite").ok(), Some(false)); + assert_eq!( + c.get("place.creator.name").ok(), + Some("John Smith".to_string()) + ); +} + +#[test] +fn test_get_scalar_path_subscript() { + let c = make(); + + assert_eq!(c.get("arr[2]").ok(), Some(3)); + assert_eq!(c.get("items[0].name").ok(), Some("1".to_string())); + assert_eq!(c.get("items[1].name").ok(), Some("2".to_string())); + assert_eq!(c.get("items[-1].name").ok(), Some("2".to_string())); + assert_eq!(c.get("items[-2].name").ok(), Some("1".to_string())); +} + +#[test] +fn test_map() { + let c = make(); + let m: HashMap = c.get("place").unwrap(); + + assert_eq!(m.len(), 8); + assert_eq!( + m["name"].clone().into_string().unwrap(), + "Torre di Pisa".to_string() + ); + assert_eq!(m["reviews"].clone().into_int().unwrap(), 3866); +} + +#[test] +fn test_map_str() { + let c = make(); + let m: HashMap = c.get("place.creator").unwrap(); + + assert_eq!(m.len(), 1); + assert_eq!(m["name"], "John Smith".to_string()); +} + +#[test] +fn test_map_struct() { + #[derive(Debug, Deserialize)] + struct Settings { + place: HashMap, + } + + let c = make(); + let s: Settings = c.try_into().unwrap(); + + assert_eq!(s.place.len(), 8); + assert_eq!( + s.place["name"].clone().into_string().unwrap(), + "Torre di Pisa".to_string() + ); + assert_eq!(s.place["reviews"].clone().into_int().unwrap(), 3866); +} + +#[test] +fn test_file_struct() { + 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); +} + +#[test] +fn test_scalar_struct() { + let c = make(); + + // Deserialize a scalar struct that has lots of different + // data types + let p: Place = c.get("place").unwrap(); + + assert_eq!(p.name, "Torre di Pisa"); + assert!(p.longitude.approx_eq_ulps(&43.7224985, 2)); + assert!(p.latitude.approx_eq_ulps(&10.3970522, 2)); + assert_eq!(p.favorite, false); + assert_eq!(p.reviews, 3866); + assert_eq!(p.rating, Some(4.5)); + assert_eq!(p.telephone, None); +} + +#[test] +fn test_array_scalar() { + let c = make(); + let arr: Vec = c.get("arr").unwrap(); + + assert_eq!(arr.len(), 10); + assert_eq!(arr[3], 4); +} + +#[test] +fn test_struct_array() { + #[derive(Debug, Deserialize)] + struct Settings { + #[serde(rename = "arr")] + elements: Vec, + } + + let c = make(); + let s: Settings = c.try_into().unwrap(); + + assert_eq!(s.elements.len(), 10); + assert_eq!(s.elements[3], "4".to_string()); +} + +#[test] +fn test_enum() { + #[derive(Debug, Deserialize, PartialEq)] + #[serde(rename_all = "lowercase")] + enum Diode { + Off, + Brightness(i32), + Blinking(i32, i32), + Pattern { name: String, inifinite: bool }, + } + #[derive(Debug, Deserialize)] + struct Settings { + diodes: HashMap, + } + + let c = make(); + let s: Settings = c.try_into().unwrap(); + + assert_eq!(s.diodes["green"], Diode::Off); + assert_eq!(s.diodes["red"], Diode::Brightness(100)); + assert_eq!(s.diodes["blue"], Diode::Blinking(300, 700)); + assert_eq!( + s.diodes["white"], + Diode::Pattern { + name: "christmas".into(), + inifinite: true, + } + ); +} + +#[test] +fn test_enum_key() { + #[derive(Debug, Deserialize, PartialEq, Eq, Hash)] + #[serde(rename_all = "lowercase")] + enum Quark { + Up, + Down, + Strange, + Charm, + Bottom, + Top, + } + + #[derive(Debug, Deserialize)] + struct Settings { + proton: HashMap, + // Just to make sure that set keys work too. + quarks: HashSet, + } + + let c = make(); + let s: Settings = c.try_into().unwrap(); + + assert_eq!(s.proton[&Quark::Up], 2); + assert_eq!(s.quarks.len(), 6); +} + +#[test] +fn test_int_key() { + #[derive(Debug, Deserialize, PartialEq)] + struct Settings { + divisors: HashMap, + } + + let c = make(); + let s: Settings = c.try_into().unwrap(); + assert_eq!(s.divisors[&4], 3); + assert_eq!(s.divisors.len(), 4); +} diff --git a/tests/legacy/merge.rs b/tests/legacy/merge.rs new file mode 100644 index 0000000..989ae47 --- /dev/null +++ b/tests/legacy/merge.rs @@ -0,0 +1,49 @@ +#![cfg(feature = "toml")] + +extern crate config; + +use self::config::*; + +fn make() -> Config { + let mut c = Config::default(); + c.merge(File::new("tests/Settings", FileFormat::Toml)) + .unwrap(); + + c.merge(File::new("tests/Settings-production", FileFormat::Toml)) + .unwrap(); + + c +} + +#[test] +fn test_merge() { + let c = make(); + + assert_eq!(c.get("debug").ok(), Some(false)); + assert_eq!(c.get("production").ok(), Some(true)); + assert_eq!( + c.get("place.creator.name").ok(), + Some("Somebody New".to_string()) + ); + assert_eq!(c.get("place.rating").ok(), Some(4.9)); +} + +#[test] +fn test_merge_whole_config() { + let mut c1 = Config::default(); + let mut c2 = Config::default(); + + c1.set("x", 10).unwrap(); + c2.set("y", 25).unwrap(); + + assert_eq!(c1.get("x").ok(), Some(10)); + assert_eq!(c2.get::<()>("x").ok(), None); + + assert_eq!(c2.get("y").ok(), Some(25)); + assert_eq!(c1.get::<()>("y").ok(), None); + + c1.merge(c2).unwrap(); + + assert_eq!(c1.get("x").ok(), Some(10)); + assert_eq!(c1.get("y").ok(), Some(25)); +} diff --git a/tests/legacy/mod.rs b/tests/legacy/mod.rs new file mode 100644 index 0000000..b331e81 --- /dev/null +++ b/tests/legacy/mod.rs @@ -0,0 +1,12 @@ +pub mod datetime; +pub mod errors; +pub mod file; +pub mod file_hjson; +pub mod file_ini; +pub mod file_json; +pub mod file_ron; +pub mod file_toml; +pub mod file_yaml; +pub mod get; +pub mod merge; +pub mod set; diff --git a/tests/legacy/set.rs b/tests/legacy/set.rs new file mode 100644 index 0000000..7a3e3a3 --- /dev/null +++ b/tests/legacy/set.rs @@ -0,0 +1,93 @@ +extern crate config; + +use self::config::*; + +#[test] +fn test_set_scalar() { + let mut c = Config::default(); + + c.set("value", true).unwrap(); + + assert_eq!(c.get("value").ok(), Some(true)); +} + +#[cfg(feature = "toml")] +#[test] +fn test_set_scalar_default() { + let mut c = Config::default(); + + c.merge(File::new("tests/Settings", FileFormat::Toml)) + .unwrap(); + + c.set_default("debug", false).unwrap(); + c.set_default("staging", false).unwrap(); + + assert_eq!(c.get("debug").ok(), Some(true)); + assert_eq!(c.get("staging").ok(), Some(false)); +} + +#[cfg(feature = "toml")] +#[test] +fn test_set_scalar_path() { + let mut c = Config::default(); + + c.set("first.second.third", true).unwrap(); + + assert_eq!(c.get("first.second.third").ok(), Some(true)); + + c.merge(File::new("tests/Settings", FileFormat::Toml)) + .unwrap(); + + c.set_default("place.favorite", true).unwrap(); + c.set_default("place.blocked", true).unwrap(); + + assert_eq!(c.get("place.favorite").ok(), Some(false)); + assert_eq!(c.get("place.blocked").ok(), Some(true)); +} + +#[cfg(feature = "toml")] +#[test] +fn test_set_arr_path() { + let mut c = Config::default(); + + c.set("items[0].name", "Ivan").unwrap(); + + assert_eq!(c.get("items[0].name").ok(), Some("Ivan".to_string())); + + c.set("data[0].things[1].name", "foo").unwrap(); + c.set("data[0].things[1].value", 42).unwrap(); + c.set("data[1]", 0).unwrap(); + + assert_eq!( + c.get("data[0].things[1].name").ok(), + Some("foo".to_string()) + ); + assert_eq!(c.get("data[0].things[1].value").ok(), Some(42)); + assert_eq!(c.get("data[1]").ok(), Some(0)); + + c.merge(File::new("tests/Settings", FileFormat::Toml)) + .unwrap(); + + c.set("items[0].name", "John").unwrap(); + + assert_eq!(c.get("items[0].name").ok(), Some("John".to_string())); + + c.set("items[2]", "George").unwrap(); + + assert_eq!(c.get("items[2]").ok(), Some("George".to_string())); +} + +#[cfg(feature = "toml")] +#[test] +fn test_set_capital() { + let mut c = Config::default(); + + c.set_default("this", false).unwrap(); + c.set("ThAt", true).unwrap(); + c.merge(File::from_str("{\"logLevel\": 5}", FileFormat::Json)) + .unwrap(); + + assert_eq!(c.get("this").ok(), Some(false)); + assert_eq!(c.get("ThAt").ok(), Some(true)); + assert_eq!(c.get("logLevel").ok(), Some(5)); +} diff --git a/tests/legacy_tests.rs b/tests/legacy_tests.rs new file mode 100644 index 0000000..e38bddd --- /dev/null +++ b/tests/legacy_tests.rs @@ -0,0 +1,5 @@ +#[allow(deprecated)] +pub mod legacy; + +#[macro_use] +extern crate serde_derive; diff --git a/tests/merge.rs b/tests/merge.rs index 1be7db1..5bb84da 100644 --- a/tests/merge.rs +++ b/tests/merge.rs @@ -5,14 +5,11 @@ extern crate config; use config::*; fn make() -> Config { - let mut c = Config::default(); - c.merge(File::new("tests/Settings", FileFormat::Toml)) - .unwrap(); - - c.merge(File::new("tests/Settings-production", FileFormat::Toml)) - .unwrap(); - - c + let mut builder = Config::builder(); + builder + .add_source(File::new("tests/Settings", FileFormat::Toml)) + .add_source(File::new("tests/Settings-production", FileFormat::Toml)); + builder.build().unwrap() } #[test] @@ -30,20 +27,25 @@ fn test_merge() { #[test] fn test_merge_whole_config() { - let mut c1 = Config::default(); - let mut c2 = Config::default(); + let mut builder1 = Config::builder(); + let mut builder2 = Config::builder(); + + builder1.set_override("x", 10).unwrap(); + builder2.set_override("y", 25).unwrap(); + + let config1 = builder1.build_cloned().unwrap(); + let config2 = builder2.build_cloned().unwrap(); - c1.set("x", 10).unwrap(); - c2.set("y", 25).unwrap(); + assert_eq!(config1.get("x").ok(), Some(10)); + assert_eq!(config2.get::<()>("x").ok(), None); - assert_eq!(c1.get("x").ok(), Some(10)); - assert_eq!(c2.get::<()>("x").ok(), None); + assert_eq!(config2.get("y").ok(), Some(25)); + assert_eq!(config1.get::<()>("y").ok(), None); - assert_eq!(c2.get("y").ok(), Some(25)); - assert_eq!(c1.get::<()>("y").ok(), None); + builder1.add_source(config2); - c1.merge(c2).unwrap(); + let config3 = builder1.build().unwrap(); - assert_eq!(c1.get("x").ok(), Some(10)); - assert_eq!(c1.get("y").ok(), Some(25)); + assert_eq!(config3.get("x").ok(), Some(10)); + assert_eq!(config3.get("y").ok(), Some(25)); } diff --git a/tests/set.rs b/tests/set.rs index ac8d5c9..956f123 100644 --- a/tests/set.rs +++ b/tests/set.rs @@ -3,91 +3,100 @@ extern crate config; use config::*; #[test] -fn test_set_scalar() { - let mut c = Config::default(); +fn test_set_override_scalar() { + let mut builder = Config::builder(); - c.set("value", true).unwrap(); + builder.set_override("value", true).unwrap(); - assert_eq!(c.get("value").ok(), Some(true)); + let config = builder.build().unwrap(); + + assert_eq!(config.get("value").ok(), Some(true)); } #[cfg(feature = "toml")] #[test] fn test_set_scalar_default() { - let mut c = Config::default(); + let mut builder = Config::builder(); - c.merge(File::new("tests/Settings", FileFormat::Toml)) + builder + .add_source(File::new("tests/Settings", FileFormat::Toml)) + .set_default("debug", false) + .unwrap() + .set_default("staging", false) .unwrap(); - c.set_default("debug", false).unwrap(); - c.set_default("staging", false).unwrap(); + let config = builder.build().unwrap(); - assert_eq!(c.get("debug").ok(), Some(true)); - assert_eq!(c.get("staging").ok(), Some(false)); + assert_eq!(config.get("debug").ok(), Some(true)); + assert_eq!(config.get("staging").ok(), Some(false)); } #[cfg(feature = "toml")] #[test] fn test_set_scalar_path() { - let mut c = Config::default(); - - c.set("first.second.third", true).unwrap(); - - assert_eq!(c.get("first.second.third").ok(), Some(true)); - - c.merge(File::new("tests/Settings", FileFormat::Toml)) + let mut builder = Config::builder(); + + builder + .set_override("first.second.third", true) + .unwrap() + .add_source(File::new("tests/Settings", FileFormat::Toml)) + .set_default("place.favorite", true) + .unwrap() + .set_default("place.blocked", true) .unwrap(); - c.set_default("place.favorite", true).unwrap(); - c.set_default("place.blocked", true).unwrap(); + let config = builder.build().unwrap(); - assert_eq!(c.get("place.favorite").ok(), Some(false)); - assert_eq!(c.get("place.blocked").ok(), Some(true)); + assert_eq!(config.get("first.second.third").ok(), Some(true)); + assert_eq!(config.get("place.favorite").ok(), Some(false)); + assert_eq!(config.get("place.blocked").ok(), Some(true)); } #[cfg(feature = "toml")] #[test] fn test_set_arr_path() { - let mut c = Config::default(); - - c.set("items[0].name", "Ivan").unwrap(); - - assert_eq!(c.get("items[0].name").ok(), Some("Ivan".to_string())); + let mut builder = Config::builder(); + + builder + .set_override("items[0].name", "Ivan") + .unwrap() + .set_override("data[0].things[1].name", "foo") + .unwrap() + .set_override("data[0].things[1].value", 42) + .unwrap() + .set_override("data[1]", 0) + .unwrap() + .add_source(File::new("tests/Settings", FileFormat::Toml)) + .set_override("items[2]", "George") + .unwrap(); - c.set("data[0].things[1].name", "foo").unwrap(); - c.set("data[0].things[1].value", 42).unwrap(); - c.set("data[1]", 0).unwrap(); + let config = builder.build().unwrap(); + assert_eq!(config.get("items[0].name").ok(), Some("Ivan".to_string())); assert_eq!( - c.get("data[0].things[1].name").ok(), + config.get("data[0].things[1].name").ok(), Some("foo".to_string()) ); - assert_eq!(c.get("data[0].things[1].value").ok(), Some(42)); - assert_eq!(c.get("data[1]").ok(), Some(0)); - - c.merge(File::new("tests/Settings", FileFormat::Toml)) - .unwrap(); - - c.set("items[0].name", "John").unwrap(); - - assert_eq!(c.get("items[0].name").ok(), Some("John".to_string())); - - c.set("items[2]", "George").unwrap(); - - assert_eq!(c.get("items[2]").ok(), Some("George".to_string())); + assert_eq!(config.get("data[0].things[1].value").ok(), Some(42)); + assert_eq!(config.get("data[1]").ok(), Some(0)); + assert_eq!(config.get("items[2]").ok(), Some("George".to_string())); } #[cfg(feature = "toml")] #[test] fn test_set_capital() { - let mut c = Config::default(); + let mut builder = Config::builder(); - c.set_default("this", false).unwrap(); - c.set("ThAt", true).unwrap(); - c.merge(File::from_str("{\"logLevel\": 5}", FileFormat::Json)) - .unwrap(); + builder + .set_default("this", false) + .unwrap() + .set_override("ThAt", true) + .unwrap() + .add_source(File::from_str("{\"logLevel\": 5}", FileFormat::Json)); + + let config = builder.build().unwrap(); - assert_eq!(c.get("this").ok(), Some(false)); - assert_eq!(c.get("ThAt").ok(), Some(true)); - assert_eq!(c.get("logLevel").ok(), Some(5)); + assert_eq!(config.get("this").ok(), Some(false)); + assert_eq!(config.get("ThAt").ok(), Some(true)); + assert_eq!(config.get("logLevel").ok(), Some(5)); } -- cgit v1.2.3