| use configparser::ini::{Ini, WriteOptions}; | |
| use std::error::Error; | |
| #[test] | |
| #[allow(clippy::approx_constant)] | |
| fn non_cs() -> Result<(), Box<dyn Error>> { | |
| let mut config = Ini::new(); | |
| let map = config.load("tests/test.ini")?; | |
| config.set_comment_symbols(&[';', '#', '!']); | |
| let inpstring = config.read( | |
| "defaultvalues=defaultvalues | |
| [topsecret] | |
| KFC = the secret herb is orega- | |
| colon:value after colon | |
| Empty string = | |
| None string | |
| Password=[in-brackets] | |
| [ spacing ] | |
| indented=indented | |
| not indented = not indented ;testcomment | |
| !modified comment | |
| [values]#another comment | |
| Bool = True | |
| Boolcoerce = 0 | |
| Int = -31415 | |
| Uint = 31415 | |
| Float = 3.1415" | |
| .to_owned(), | |
| )?; | |
| assert_eq!(map, inpstring); | |
| config.set("DEFAULT", "defaultvalues", Some("notdefault".to_owned())); | |
| assert_eq!( | |
| config.get("DEFAULT", "defaultvalues").unwrap(), | |
| "notdefault" | |
| ); | |
| config.setstr("DEFAULT", "defaultvalues", Some("defaultvalues")); | |
| assert_eq!( | |
| config.get("DEFAULT", "defaultvalues").unwrap(), | |
| "defaultvalues" | |
| ); | |
| config.setstr("DEFAULT", "defaultvalues", None); | |
| config.write("output.ini")?; | |
| let map2 = config.clone().load("output.ini")?; | |
| assert_eq!(map2, *config.get_map_ref()); | |
| let map3 = config.clone().read(config.writes())?; | |
| assert_eq!(map2, map3); | |
| assert_eq!(config.sections().len(), 4); | |
| assert_eq!(config.get("DEFAULT", "defaultvalues"), None); | |
| assert_eq!( | |
| config.get("topsecret", "KFC").unwrap(), | |
| "the secret herb is orega-" | |
| ); | |
| assert_eq!(config.get("topsecret", "Empty string").unwrap(), ""); | |
| assert_eq!(config.get("topsecret", "None string"), None); | |
| assert_eq!(config.get("spacing", "indented").unwrap(), "indented"); | |
| assert_eq!( | |
| config.get("spacing", "not indented").unwrap(), | |
| "not indented" | |
| ); | |
| assert_eq!( | |
| config.get("topsecret", "colon").unwrap(), | |
| "value after colon" | |
| ); | |
| assert!(config.getbool("values", "Bool")?.unwrap()); | |
| assert!(!config.getboolcoerce("values", "Boolcoerce")?.unwrap()); | |
| assert_eq!(config.getint("values", "Int")?.unwrap(), -31415); | |
| assert_eq!(config.getuint("values", "Uint")?.unwrap(), 31415); | |
| assert_eq!(config.getfloat("values", "Float")?.unwrap(), 3.1415); | |
| assert_eq!(config.getfloat("topsecret", "None string"), Ok(None)); | |
| assert_eq!( | |
| map["default"]["defaultvalues"].clone().unwrap(), | |
| "defaultvalues" | |
| ); | |
| assert_eq!( | |
| map["topsecret"]["kfc"].clone().unwrap(), | |
| "the secret herb is orega-" | |
| ); | |
| assert_eq!(map["topsecret"]["empty string"].clone().unwrap(), ""); | |
| assert_eq!(map["topsecret"]["none string"], None); | |
| assert_eq!(map["spacing"]["indented"].clone().unwrap(), "indented"); | |
| assert_eq!( | |
| map["spacing"]["not indented"].clone().unwrap(), | |
| "not indented" | |
| ); | |
| let mut config2 = config.clone(); | |
| let val = config2.remove_key("default", "defaultvalues"); | |
| assert_eq!(val, Some(None)); | |
| assert_eq!(config2.get("default", "defaultvalues"), None); | |
| config2.remove_section("default"); | |
| assert_eq!(config2.get("default", "nope"), None); | |
| let mut_map = config.get_mut_map(); | |
| mut_map.get_mut("topsecret").unwrap().insert( | |
| String::from("none string"), | |
| Some(String::from("None string")), | |
| ); | |
| assert_eq!( | |
| mut_map["topsecret"]["none string"].clone().unwrap(), | |
| "None string" | |
| ); | |
| mut_map.clear(); | |
| config2.clear(); | |
| assert_eq!(config.get_map_ref(), config2.get_map_ref()); | |
| config.load("tests/test.ini")?; | |
| config.read_and_append("defaultvalues=somenewvalue".to_owned())?; | |
| assert_eq!( | |
| config.get("default", "defaultvalues").unwrap(), | |
| "somenewvalue" | |
| ); | |
| assert_eq!( | |
| config.get("topsecret", "KFC").unwrap(), | |
| "the secret herb is orega-" | |
| ); | |
| let mut config3 = config.clone(); | |
| let mut_map = config3.get_mut_map(); | |
| mut_map.clear(); | |
| config3.load("tests/test.ini")?; | |
| config3.load_and_append("tests/test_more.ini")?; | |
| assert_eq!( | |
| config3.get("default", "defaultvalues").unwrap(), | |
| "overwritten" | |
| ); | |
| assert_eq!(config3.get("topsecret", "KFC").unwrap(), "redacted"); | |
| // spacing -> indented exists in tests/test.ini, but not tests/test_more.ini | |
| assert_eq!(config3.get("spacing", "indented").unwrap(), "indented"); | |
| assert!(!config3.getbool("values", "Bool")?.unwrap()); | |
| Ok(()) | |
| } | |
| #[test] | |
| #[allow(clippy::approx_constant)] | |
| fn cs() -> Result<(), Box<dyn Error>> { | |
| let mut config = Ini::new_cs(); | |
| let map = config.load("tests/test.ini")?; | |
| config.set_comment_symbols(&[';', '#', '!']); | |
| let inpstring = config.read( | |
| "defaultvalues=defaultvalues | |
| [topsecret] | |
| KFC = the secret herb is orega- | |
| colon:value after colon | |
| Empty string = | |
| None string | |
| Password=[in-brackets] | |
| [ spacing ] | |
| indented=indented | |
| not indented = not indented ;testcomment | |
| !modified comment | |
| [values]#another comment | |
| Bool = True | |
| Boolcoerce = 0 | |
| Int = -31415 | |
| Uint = 31415 | |
| Float = 3.1415" | |
| .to_owned(), | |
| )?; | |
| assert_eq!(map, inpstring); | |
| config.set("default", "defaultvalues", Some("notdefault".to_owned())); | |
| assert_eq!( | |
| config.get("default", "defaultvalues").unwrap(), | |
| "notdefault" | |
| ); | |
| config.setstr("default", "defaultvalues", Some("defaultvalues")); | |
| assert_eq!( | |
| config.get("default", "defaultvalues").unwrap(), | |
| "defaultvalues" | |
| ); | |
| config.setstr("default", "defaultvalues", None); | |
| config.write("output2.ini")?; | |
| let map2 = config.clone().load("output2.ini")?; | |
| assert_eq!(map2, *config.get_map_ref()); | |
| let map3 = config.clone().read(config.writes())?; | |
| assert_eq!(map2, map3); | |
| assert_eq!(config.sections().len(), 4); | |
| assert_eq!(config.get("default", "defaultvalues"), None); | |
| assert_eq!( | |
| config.get("topsecret", "KFC").unwrap(), | |
| "the secret herb is orega-" | |
| ); | |
| assert_eq!(config.get("topsecret", "Empty string").unwrap(), ""); | |
| assert_eq!(config.get("topsecret", "None string"), None); | |
| assert_eq!(config.get("spacing", "indented").unwrap(), "indented"); | |
| assert_eq!( | |
| config.get("spacing", "not indented").unwrap(), | |
| "not indented" | |
| ); | |
| assert_eq!( | |
| config.get("topsecret", "colon").unwrap(), | |
| "value after colon" | |
| ); | |
| assert!(config.getbool("values", "Bool")?.unwrap()); | |
| assert!(!config.getboolcoerce("values", "Boolcoerce")?.unwrap()); | |
| assert_eq!(config.getint("values", "Int")?.unwrap(), -31415); | |
| assert_eq!(config.getuint("values", "Uint")?.unwrap(), 31415); | |
| assert_eq!(config.getfloat("values", "Float")?.unwrap(), 3.1415); | |
| assert_eq!(config.getfloat("topsecret", "None string"), Ok(None)); | |
| assert_eq!( | |
| map["default"]["defaultvalues"].clone().unwrap(), | |
| "defaultvalues" | |
| ); | |
| assert_eq!( | |
| map["topsecret"]["KFC"].clone().unwrap(), | |
| "the secret herb is orega-" | |
| ); | |
| assert_eq!(map["topsecret"]["Empty string"].clone().unwrap(), ""); | |
| assert_eq!(map["topsecret"]["None string"], None); | |
| assert_eq!(map["spacing"]["indented"].clone().unwrap(), "indented"); | |
| assert_eq!( | |
| map["spacing"]["not indented"].clone().unwrap(), | |
| "not indented" | |
| ); | |
| let mut config2 = config.clone(); | |
| let val = config2.remove_key("default", "defaultvalues"); | |
| assert_eq!(val, Some(None)); | |
| assert_eq!(config2.get("default", "defaultvalues"), None); | |
| config2.remove_section("default"); | |
| assert_eq!(config2.get("default", "nope"), None); | |
| let mut_map = config.get_mut_map(); | |
| mut_map.get_mut("topsecret").unwrap().insert( | |
| String::from("none string"), | |
| Some(String::from("None string")), | |
| ); | |
| assert_eq!( | |
| mut_map["topsecret"]["none string"].clone().unwrap(), | |
| "None string" | |
| ); | |
| mut_map.clear(); | |
| config2.clear(); | |
| assert_eq!(config.get_map_ref(), config2.get_map_ref()); | |
| Ok(()) | |
| } | |
| #[test] | |
| #[cfg(feature = "indexmap")] | |
| fn sort_on_write() -> Result<(), Box<dyn Error>> { | |
| let mut config = Ini::new_cs(); | |
| config.load("tests/test.ini")?; | |
| assert_eq!( | |
| config.writes(), | |
| "defaultvalues=defaultvalues | |
| [topsecret] | |
| KFC=the secret herb is orega- | |
| colon=value after colon | |
| Empty string= | |
| None string | |
| Password=[in-brackets] | |
| [spacing] | |
| indented=indented | |
| not indented=not indented | |
| [values] | |
| Bool=True | |
| Boolcoerce=0 | |
| Int=-31415 | |
| Uint=31415 | |
| Float=3.1415 | |
| " | |
| ); | |
| Ok(()) | |
| } | |
| #[test] | |
| #[cfg(feature = "indexmap")] | |
| fn pretty_writes_result_is_formatted_correctly() -> Result<(), Box<dyn Error>> { | |
| use configparser::ini::IniDefault; | |
| const OUT_FILE_CONTENTS: &str = "defaultvalues=defaultvalues | |
| [topsecret] | |
| KFC=the secret herb is orega- | |
| Empty string= | |
| None string | |
| Password=[in-brackets] | |
| [Section] | |
| Key1: Value1 | |
| Key2: this is a haiku | |
| spread across separate lines | |
| a single value | |
| Key3: another value | |
| "; | |
| let mut ini_defaults = IniDefault::default(); | |
| ini_defaults.case_sensitive = true; | |
| ini_defaults.multiline = true; | |
| let mut config = Ini::new_from_defaults(ini_defaults); | |
| config.read(OUT_FILE_CONTENTS.to_owned())?; | |
| let mut write_options = WriteOptions::default(); | |
| write_options.space_around_delimiters = true; | |
| write_options.multiline_line_indentation = 2; | |
| write_options.blank_lines_between_sections = 1; | |
| assert_eq!( | |
| config.pretty_writes(&write_options), | |
| "defaultvalues = defaultvalues | |
| [topsecret] | |
| KFC = the secret herb is orega- | |
| Empty string = | |
| None string | |
| Password = [in-brackets] | |
| [Section] | |
| Key1 = Value1 | |
| Key2 = this is a haiku | |
| spread across separate lines | |
| a single value | |
| Key3 = another value | |
| " | |
| ); | |
| Ok(()) | |
| } | |
| #[test] | |
| #[cfg(feature = "indexmap")] | |
| #[cfg(feature = "async-std")] | |
| #[cfg(feature = "tokio")] | |
| fn pretty_write_result_is_formatted_correctly() -> Result<(), Box<dyn Error>> { | |
| use configparser::ini::IniDefault; | |
| const OUT_FILE_CONTENTS: &str = "defaultvalues=defaultvalues | |
| [topsecret] | |
| KFC=the secret herb is orega- | |
| Empty string= | |
| None string | |
| Password=[in-brackets] | |
| [Section] | |
| Key1: Value1 | |
| Key2: this is a haiku | |
| spread across separate lines | |
| a single value | |
| Key3: another value | |
| "; | |
| let mut ini_defaults = IniDefault::default(); | |
| ini_defaults.case_sensitive = true; | |
| ini_defaults.multiline = true; | |
| let mut config = Ini::new_from_defaults(ini_defaults); | |
| config.read(OUT_FILE_CONTENTS.to_owned())?; | |
| let mut write_options = WriteOptions::default(); | |
| write_options.space_around_delimiters = true; | |
| write_options.multiline_line_indentation = 2; | |
| write_options.blank_lines_between_sections = 1; | |
| config.pretty_write("pretty_output.ini", &write_options)?; | |
| let file_contents = std::fs::read_to_string("pretty_output.ini")?; | |
| assert_eq!( | |
| file_contents, | |
| "defaultvalues = defaultvalues | |
| [topsecret] | |
| KFC = the secret herb is orega- | |
| Empty string = | |
| None string | |
| Password = [in-brackets] | |
| [Section] | |
| Key1 = Value1 | |
| Key2 = this is a haiku | |
| spread across separate lines | |
| a single value | |
| Key3 = another value | |
| " | |
| ); | |
| Ok(()) | |
| } | |
| #[tokio::test] | |
| #[cfg(feature = "indexmap")] | |
| #[cfg(feature = "async-std")] | |
| #[cfg(feature = "tokio")] | |
| async fn async_pretty_print_result_is_formatted_correctly() -> Result<(), Box<dyn Error>> { | |
| use configparser::ini::IniDefault; | |
| const OUT_FILE_CONTENTS: &str = "defaultvalues=defaultvalues | |
| [topsecret] | |
| KFC=the secret herb is orega- | |
| Empty string= | |
| None string | |
| Password=[in-brackets] | |
| [Section] | |
| Key1: Value1 | |
| Key2: this is a haiku | |
| spread across separate lines | |
| a single value | |
| Key3: another value | |
| "; | |
| let mut ini_defaults = IniDefault::default(); | |
| ini_defaults.case_sensitive = true; | |
| ini_defaults.multiline = true; | |
| let mut config = Ini::new_from_defaults(ini_defaults); | |
| config.read(OUT_FILE_CONTENTS.to_owned())?; | |
| let mut write_options = WriteOptions::default(); | |
| write_options.space_around_delimiters = true; | |
| write_options.multiline_line_indentation = 2; | |
| write_options.blank_lines_between_sections = 1; | |
| config | |
| .pretty_write_async("pretty_output_async.ini", &write_options) | |
| .await | |
| .map_err(|e| e.to_string())?; | |
| let file_contents = std::fs::read_to_string("pretty_output_async.ini")?; | |
| assert_eq!( | |
| file_contents, | |
| "defaultvalues = defaultvalues | |
| [topsecret] | |
| KFC = the secret herb is orega- | |
| Empty string = | |
| None string | |
| Password = [in-brackets] | |
| [Section] | |
| Key1 = Value1 | |
| Key2 = this is a haiku | |
| spread across separate lines | |
| a single value | |
| Key3 = another value | |
| " | |
| ); | |
| Ok(()) | |
| } | |
| #[tokio::test] | |
| #[cfg(feature = "async-std")] | |
| #[cfg(feature = "tokio")] | |
| async fn async_load_write() -> Result<(), Box<dyn Error>> { | |
| const OUT_FILE_CONTENTS: &str = "defaultvalues=defaultvalues | |
| [topsecret] | |
| KFC = the secret herb is orega- | |
| colon:value after colon | |
| Empty string = | |
| None string | |
| Password=[in-brackets] | |
| [ spacing ] | |
| indented=indented | |
| not indented = not indented ;testcomment | |
| !modified comment | |
| [values]#another comment | |
| Bool = True | |
| Boolcoerce = 0 | |
| Int = -31415 | |
| Uint = 31415 | |
| Float = 3.1415"; | |
| let mut config = Ini::new(); | |
| config.read(OUT_FILE_CONTENTS.to_owned())?; | |
| config.write("output_sync.ini")?; | |
| let mut config_async = Ini::new(); | |
| config_async.read(OUT_FILE_CONTENTS.to_owned())?; | |
| config_async | |
| .write_async("output_async.ini") | |
| .await | |
| .map_err(|e| e.to_string())?; | |
| let mut sync_content = Ini::new(); | |
| sync_content.load("output_sync.ini")?; | |
| let mut async_content = Ini::new(); | |
| async_content.load_async("output_async.ini").await?; | |
| assert_eq!(sync_content, async_content); | |
| Ok(()) | |
| } | |
| #[tokio::test] | |
| #[cfg(feature = "async-std")] | |
| #[cfg(feature = "tokio")] | |
| async fn async_load_and_append() -> Result<(), Box<dyn Error>> { | |
| let mut sync_content = Ini::new(); | |
| sync_content.load("tests/test.ini")?; | |
| sync_content.load_and_append("tests/test_more.ini")?; | |
| let mut async_content = Ini::new(); | |
| async_content.load_async("tests/test.ini").await?; | |
| async_content | |
| .load_and_append_async("tests/test_more.ini") | |
| .await?; | |
| assert_eq!(sync_content, async_content); | |
| Ok(()) | |
| } | |
| #[test] | |
| #[cfg(feature = "indexmap")] | |
| fn multiline_off() -> Result<(), Box<dyn Error>> { | |
| let mut config = Ini::new_cs(); | |
| config.load("tests/test_multiline.ini")?; | |
| let map = config.get_map_ref(); | |
| let section = map.get("Section").unwrap(); | |
| assert_eq!(config.get("Section", "Key1").unwrap(), "Value1"); | |
| assert_eq!(config.get("Section", "Key2").unwrap(), "Value Two"); | |
| assert_eq!(config.get("Section", "Key3").unwrap(), "this is a haiku"); | |
| assert!(section.contains_key("spread across separate lines")); | |
| assert!(section.contains_key("a single value")); | |
| assert_eq!(config.get("Section", "Key4").unwrap(), "Four"); | |
| assert_eq!( | |
| config.writes(), | |
| "[Section] | |
| Key1=Value1 | |
| Key2=Value Two | |
| Key3=this is a haiku | |
| spread across separate lines | |
| a single value | |
| Key4=Four | |
| " | |
| ); | |
| Ok(()) | |
| } | |
| #[test] | |
| #[cfg(feature = "indexmap")] | |
| fn multiline_on() -> Result<(), Box<dyn Error>> { | |
| let mut config = Ini::new_cs(); | |
| config.set_multiline(true); | |
| config.load("tests/test_multiline.ini")?; | |
| assert_eq!(config.get("Section", "Key1").unwrap(), "Value1"); | |
| assert_eq!(config.get("Section", "Key2").unwrap(), "Value Two"); | |
| assert_eq!( | |
| config.get("Section", "Key3").unwrap(), | |
| "this is a haiku\nspread across separate lines\na single value" | |
| ); | |
| assert_eq!(config.get("Section", "Key4").unwrap(), "Four"); | |
| assert_eq!( | |
| config.writes(), | |
| "[Section] | |
| Key1=Value1 | |
| Key2=Value Two | |
| Key3=this is a haiku | |
| spread across separate lines | |
| a single value | |
| Key4=Four | |
| " | |
| ); | |
| Ok(()) | |
| } |