#![allow(clippy::panic_in_result_fn)]
#![allow(clippy::unwrap_used)]
use std::fs;
use std::path::Path;
use rstest::rstest;
use thiserror::Error;
use tracing::trace;
use tracing_test::traced_test;
use crate::defs::{ConfgetError, Config};
use crate::format;
#[derive(Debug, Error)]
enum Error {
#[error("Could not read the {0} input file")]
FileRead(String, #[source] ConfgetError),
#[error("Could not filter vars from the {0} input file")]
FilterVars(String, #[source] ConfgetError),
#[error("Could not get the {0} section from the {1} input file")]
NoSection(String, String),
#[error("Could not get the {0}.{1} value from the {2} input file")]
NoValue(String, String, String),
}
fn run(
cfg: &Config,
filename: &str,
section: &str,
key: &str,
value: &str,
expected: bool,
) -> Result<(), Error> {
let (data, _) =
super::read_ini_file(cfg).map_err(|err| Error::FileRead(filename.to_owned(), err))?;
assert_eq!(
data.get(section)
.ok_or_else(|| Error::NoSection(filename.to_owned(), section.to_owned()))?
.get(key)
.ok_or_else(|| Error::NoValue(
filename.to_owned(),
section.to_owned(),
key.to_owned()
))?,
value
);
let vars = format::filter_vars(cfg, &data, section)
.map_err(|err| Error::FilterVars(filename.to_owned(), err))?;
trace!(?vars);
if expected {
assert!(!vars.is_empty());
let found = vars
.into_iter()
.find(|var| var.name == key)
.ok_or_else(|| {
Error::NoValue(filename.to_owned(), section.to_owned(), key.to_owned())
})?;
assert_eq!(found.value, value);
} else {
assert!(vars.is_empty());
}
Ok(())
}
#[rstest]
#[case("t1.ini", "b sect", "key4", "v'alu'e4")]
#[case("t2.ini", "sec1", "key2", "4")]
#[case("t3.ini", "a", "aonly", "a")]
#[case("t4.ini", "x", "key8", "key9=key10=key11")]
#[traced_test]
fn test_parse_full(
#[case] filename: &str,
#[case] section: &str,
#[case] key: &str,
#[case] value: &str,
) -> Result<(), Error> {
let cfg_list_all = Config {
filename: Some(format!("test_data/{}", filename)),
list_all: true,
..Config::default()
};
run(&cfg_list_all, filename, section, key, value, true)?;
let cfg_single = Config {
list_all: false,
varnames: vec![key.to_owned()],
..cfg_list_all
};
run(&cfg_single, filename, section, key, value, true)?;
let cfg_match_var_names = Config {
match_var_names: true,
varnames: vec![format!("{}*", key)],
..cfg_single
};
run(&cfg_match_var_names, filename, section, key, value, true)?;
let cfg_match_var_names_fail = Config {
match_var_names: true,
varnames: vec![format!("{}x*", key)],
..cfg_match_var_names
};
run(
&cfg_match_var_names_fail,
filename,
section,
key,
value,
false,
)?;
let cfg_match_var_values = Config {
list_all: true,
match_var_names: false,
match_var_values: Some(format!("{}*", value.to_owned())),
varnames: vec![],
..cfg_match_var_names_fail
};
run(&cfg_match_var_values, filename, section, key, value, true)?;
let cfg_match_var_values_fail = Config {
match_var_values: Some(format!("{}x*", value.to_owned())),
..cfg_match_var_values
};
run(
&cfg_match_var_values_fail,
filename,
section,
key,
value,
false,
)?;
Ok(())
}
#[rstest]
#[case("t1.ini")]
#[case("t2.ini")]
#[case("t3.ini")]
#[case("t4.ini")]
#[traced_test]
fn test_data_files_same(#[case] filename: &str) {
let up = Path::new("../t").join(filename);
if !up.is_file() {
trace!("No {} file, skipping", up.display());
return;
}
let up_contents = fs::read_to_string(&up).unwrap();
let ours = Path::new("test_data").join(filename);
let ours_contents = fs::read_to_string(&ours).unwrap();
assert_eq!(up_contents, ours_contents);
}