Fix custom config file and add test

This commit is contained in:
Demmie 2023-07-08 23:23:29 -04:00
parent d6e762630e
commit ca72df7e6e
No known key found for this signature in database
GPG Key ID: B06DAA3D432C6E9A
4 changed files with 116 additions and 9 deletions

1
Cargo.lock generated
View File

@ -3873,6 +3873,7 @@ dependencies = [
"serde",
"serde_default",
"serde_json",
"tempfile",
"tokio",
"toml 0.7.5",
"wayland-backend",

View File

@ -111,13 +111,9 @@ pub fn from_cli() -> anyhow::Result<RunnerConfig> {
pub fn new_with_cli(matches: &ArgMatches) -> anyhow::Result<FileConfig> {
let mut config_path = None;
if matches.contains_id("config") {
let config_file = matches.get_one::<String>("config");
let config_file = matches.get_one::<PathBuf>("config");
if let Some(path) = config_file {
if let Err(e) = std::fs::metadata(path) {
warn!("Invalid config filename, using the default config: {e}");
} else {
config_path = Some(Path::new(path).to_path_buf());
}
config_path = Some(Path::new(path).to_path_buf());
}
}
let mut config = FileConfig::new(config_path)?;

View File

@ -11,6 +11,7 @@ path = "src/lib.rs"
[dev-dependencies]
rstest = "0.17.0"
tempfile = "3.5.0"
[dependencies]
aw-client-rust = { git = "https://github.com/2e3s/aw-server-rust", rev = "81db4c8" }

View File

@ -1,7 +1,7 @@
use anyhow::{anyhow, Context};
use serde::Deserialize;
use serde_default::DefaultFromSerde;
use std::{io::ErrorKind, path::PathBuf, time::Duration};
use std::{fs, io::ErrorKind, path::PathBuf, time::Duration};
use crate::config::defaults;
@ -97,8 +97,15 @@ pub struct FileConfig {
impl FileConfig {
pub fn new(config_override: Option<PathBuf>) -> anyhow::Result<Self> {
let is_config_overridden = config_override.is_some();
let config_path = if let Some(config_override) = config_override {
config_override
if config_override.starts_with("~/") {
dirs::home_dir()
.ok_or(anyhow!("Home directory is not found"))?
.join(config_override.strip_prefix("~").unwrap())
} else {
config_override
}
} else {
let mut system_config_path: PathBuf =
dirs::config_dir().ok_or(anyhow!("Config directory is unknown"))?;
@ -108,7 +115,7 @@ impl FileConfig {
system_config_path
};
let mut config = if config_path.exists() {
let mut config = if fs::metadata(&config_path).is_ok() {
debug!("Reading config at {}", config_path.display());
let config_content = std::fs::read_to_string(&config_path).with_context(|| {
format!("Impossible to read config file {}", config_path.display())
@ -116,6 +123,9 @@ impl FileConfig {
toml::from_str(&config_content)?
} else {
if is_config_overridden {
anyhow::bail!("Config file is not accessible at {}", config_path.display());
}
let config = default_config();
let error = std::fs::create_dir(config_path.parent().unwrap());
if let Err(e) = error {
@ -133,3 +143,102 @@ impl FileConfig {
Ok(config)
}
}
#[cfg(test)]
mod tests {
use super::*;
use rstest::rstest;
use std::io::Write;
use tempfile::NamedTempFile;
#[rstest]
fn all() {
let mut file = NamedTempFile::new().unwrap();
write!(
file,
r#"
[server]
port = 1234
host = "http://address.com"
[awatcher]
idle-timeout-seconds=14
poll-time-idle-seconds=13
poll-time-window-seconds=12
# Add as many filters as needed.
# There should be at least 1 match field, and at least 1 replace field.
[[awatcher.filters]]
match-app-id = "firefox"
replace-title = "Unknown"
[[awatcher.filters]]
match-app-id = "code"
match-title = "title"
replace-app-id = "VSCode"
replace-title = "Title"
"#
)
.unwrap();
let config = FileConfig::new(Some(file.path().to_path_buf())).unwrap();
assert_eq!(1234, config.server.port);
assert_eq!("http://address.com", config.server.host);
assert_eq!(14, config.client.idle_timeout_seconds);
assert_eq!(13, config.client.poll_time_idle_seconds);
assert_eq!(12, config.client.poll_time_window_seconds);
assert_eq!(2, config.client.filters.len());
let replacement1 = config.client.filters[0]
.replacement("firefox", "any")
.unwrap();
assert_eq!(None, replacement1.replace_app_id);
assert_eq!(Some("Unknown".to_string()), replacement1.replace_title);
let replacement2 = config.client.filters[1]
.replacement("code", "title")
.unwrap();
assert_eq!(Some("VSCode".to_string()), replacement2.replace_app_id);
assert_eq!(Some("Title".to_string()), replacement2.replace_title);
}
#[rstest]
fn empty() {
let mut file = NamedTempFile::new().unwrap();
write!(file, "[awatcher]").unwrap();
let config = FileConfig::new(Some(file.path().to_path_buf())).unwrap();
assert_eq!(defaults::port(), config.server.port);
assert_eq!(defaults::host(), config.server.host);
assert_eq!(
defaults::idle_timeout_seconds(),
config.client.idle_timeout_seconds
);
assert_eq!(
defaults::poll_time_idle_seconds(),
config.client.poll_time_idle_seconds
);
assert_eq!(
defaults::poll_time_window_seconds(),
config.client.poll_time_window_seconds
);
assert_eq!(0, config.client.filters.len());
}
#[rstest]
fn wrong_file() {
let file = PathBuf::new();
let config = FileConfig::new(Some(file));
assert!(config.is_err());
assert_eq!(
"Config file is not accessible at ",
config.err().unwrap().to_string()
);
}
}