marg 0.4.2

Meta config for apps from args
Documentation
#![allow(warnings)]

use super::*;
use super::{link_db_user, get_exec_name};
use crate::feature::SupportedDb;
use uuid::Uuid;

// ── helpers ──────────────────────────────────────────────────────────────────

fn new(args: Vec<&str>) -> ArgConfig {
    ArgConfig::new(
        args.into_iter().map(str::to_string).collect(),
        SupportedDb::Postgres,
        "".to_string(),
        None,
    )
    .unwrap()
}

// ── exec-name ────────────────────────────────────────────────────────────────

#[test]
#[cfg(unix)]
fn test_file_name() {
    assert_eq!(get_exec_name("", "").as_str(), "");
    assert_eq!(get_exec_name("", "target/debug/marg").as_str(), "marg");
    assert_eq!(get_exec_name("", "marg").as_str(), "marg");
}

#[test]
#[cfg(windows)]
fn test_file_name() {
    assert_eq!(get_exec_name("", "").as_str(), "");
    assert_eq!(get_exec_name("", "target\\debug\\marg.exe").as_str(), "marg");
    assert_eq!(get_exec_name("", "target\\\\debug\\\\marg.exe").as_str(), "marg");
}

// ── basic positional / explicit flags ────────────────────────────────────────

#[test]
fn config_args_file1_test() {
    let cfg = ArgConfig::new(vec!["".to_string()], SupportedDb::Postgres, "".to_string(), None).unwrap();
    assert_eq!(0, cfg.cfg.len());
}

#[test]
fn config_args_file2_test() {
    let url = "postgresql://user:pwd@host/db".to_string();
    let cfg = ArgConfig::new(vec![url.clone()], SupportedDb::Postgres, "vk".to_string(), None).unwrap();
    assert_eq!(url, cfg.db_url());
}

#[test]
fn config_args_file3_test() {
    let url = "postgresql://user:pwd@host/db".to_string();
    let t = "public.table".to_string();
    let cfg = ArgConfig::new(vec![url.clone(), t.clone()], SupportedDb::Postgres, "".to_string(), None).unwrap();
    assert_eq!(url, cfg.db_url());
    assert_eq!(t, cfg.table);
}

#[test]
fn config_args_user_test() {
    let user = match std::env::var_os("USER") {
        Some(a) => a.to_str().unwrap_or("postgres").to_string(),
        _ => "postgres".to_string(),
    };
    assert_eq!(format!("postgresql://{}:pwd@host/db", user), link_db_user("postgresql://$USER:pwd@host/db".to_string(), user.clone()));
    assert_eq!(format!("postgresql://{}:$PWD@host/db", user), link_db_user("postgresql://$USER:$PWD@host/db".to_string(), user.clone()));
    assert_eq!(format!("postgresql://{}@host/db", user), link_db_user("postgresql://$USER@host/db".to_string(), user.clone()));
    assert_eq!(format!("postgresql://{}@host/db", ""), link_db_user("postgresql://@host/db".to_string(), user.clone()));
}

#[test]
fn uuid_gen_autogenerated_test() {
    let cfg = new(vec![""]);
    assert!(cfg.uuid_gen);
}

#[test]
fn uuid_positional_test() {
    let id = "550e8400-e29b-41d4-a716-446655440000";
    let cfg = new(vec!["", id]);
    assert_eq!(Uuid::parse_str(id).unwrap(), cfg.uuid);
    assert!(!cfg.uuid_gen);
}

#[test]
fn explicit_db_flag_test() {
    let url = "postgresql://user:pwd@host/db";
    let cfg = new(vec!["", "--db", url]);
    assert_eq!(url, cfg.db_url());
}

#[test]
fn explicit_config_flag_test() {
    let tbl = "myschema.mytable";
    let cfg = new(vec!["", "--config", tbl]);
    assert_eq!(tbl, cfg.table);
}

#[test]
fn explicit_uuid_flag_test() {
    let id = "550e8400-e29b-41d4-a716-446655440000";
    let cfg = new(vec!["", "--uuid", id]);
    assert_eq!(Uuid::parse_str(id).unwrap(), cfg.uuid);
    assert!(!cfg.uuid_gen);
}

#[test]
fn explicit_token_flag_test() {
    let cfg = new(vec!["", "--token", "get-token.sh"]);
    assert_eq!("get-token.sh", cfg.token.cmd);
}

#[test]
fn explicit_ttl_flag_test() {
    let cfg = new(vec!["", "--ttl", "30"]);
    assert_eq!(30, cfg.token.min);
}

#[test]
fn explicit_token_ttl_combined_test() {
    let cfg = new(vec!["", "--token", "get-token.sh", "--ttl", "15"]);
    assert_eq!("get-token.sh", cfg.token.cmd);
    assert_eq!(15, cfg.token.min);
}

#[test]
fn explicit_secret_flag_test() {
    let cfg = new(vec!["", "--secret", "mysecret"]);
    assert_eq!(Some("mysecret".to_string()), cfg.secret);
}

#[test]
fn positional_token_test() {
    let cfg = new(vec!["", "postgresql://host/db", "myschema.table", "mytoken"]);
    assert_eq!("mytoken", cfg.token.cmd);
}

#[test]
fn positional_ttl_test() {
    let cfg = new(vec!["", "postgresql://host/db", "myschema.table", "mytoken", "45"]);
    assert_eq!("mytoken", cfg.token.cmd);
    assert_eq!(45, cfg.token.min);
}

#[test]
fn db_url_pwd_substitution_test() {
    let url = "postgresql://user:$PWD@host/db".to_string();
    let cfg = ArgConfig::new(vec![url.clone()], SupportedDb::Postgres, "".to_string(), Some("secret123".to_string())).unwrap();
    assert_eq!("postgresql://user:secret123@host/db", cfg.db_url());
}

#[test]
fn db_url_no_pwd_placeholder_test() {
    let url = "postgresql://user:pwd@host/db".to_string();
    let cfg = ArgConfig::new(vec![url.clone()], SupportedDb::Postgres, "".to_string(), Some("secret123".to_string())).unwrap();
    assert_eq!(url, cfg.db_url());
}

#[test]
fn all_positional_test() {
    let id = "550e8400-e29b-41d4-a716-446655440000";
    let cfg = new(vec!["", "postgresql://host/db", "myschema.table", id, "mytoken", "20"]);
    assert_eq!("postgresql://host/db", cfg.db_url);
    assert_eq!("myschema.table", cfg.table);
    assert_eq!(Uuid::parse_str(id).unwrap(), cfg.uuid);
    assert!(!cfg.uuid_gen);
    assert_eq!("mytoken", cfg.token.cmd);
    assert_eq!(20, cfg.token.min);
}

#[test]
fn all_explicit_flags_test() {
    let url = "postgresql://user:pwd@host/db";
    let tbl = "myschema.mytable";
    let id  = "550e8400-e29b-41d4-a716-446655440000";
    let cfg = new(vec![
        "", "--db", url, "--config", tbl, "--uuid", id,
        "--token", "get-token.sh", "--ttl", "15", "--secret", "mysecret",
    ]);
    assert_eq!(url, cfg.db_url);
    assert_eq!(tbl, cfg.table);
    assert_eq!(Uuid::parse_str(id).unwrap(), cfg.uuid);
    assert!(!cfg.uuid_gen);
    assert_eq!("get-token.sh", cfg.token.cmd);
    assert_eq!(15, cfg.token.min);
    assert_eq!(Some("mysecret".to_string()), cfg.secret);
}

#[test]
fn custom_db_any_url_test() {
    let url = "somedb://connection-string".to_string();
    let cfg = ArgConfig::new(vec![url.clone()], SupportedDb::Custom, "".to_string(), None).unwrap();
    assert_eq!(url, cfg.db_url);
}

#[test]
fn default_table_from_appname_test() {
    let cfg = ArgConfig::new(vec!["myapp".to_string()], SupportedDb::Postgres, "".to_string(), None).unwrap();
    assert_eq!("public.myapp", cfg.table);
}

// ── verbose / quiet / help / version flags ───────────────────────────────────

#[test]
fn flags_unset_by_default_test() {
    let cfg = new(vec![""]);
    assert!(!cfg.verbose.is_set());
    assert!(!cfg.quiet.is_set());
    assert!(!cfg.help.is_set());
}

#[test]
fn verbose_short_flag_test() {
    assert!(new(vec!["", "-v"]).verbose.is_set());
}

#[test]
fn verbose_long_flag_test() {
    assert!(new(vec!["", "--verbose"]).verbose.is_set());
}

#[test]
fn verbose_alt_flag_test() {
    assert!(new(vec!["", "--debug"]).verbose.is_set());
}

#[test]
fn verbose_eq_true_test() {
    assert!(new(vec!["", "--verbose=true"]).verbose.is_set());
}

#[test]
fn verbose_eq_false_test() {
    assert!(!new(vec!["", "--verbose=false"]).verbose.is_set());
}

#[test]
fn quiet_short_flag_test() {
    assert!(new(vec!["", "-q"]).quiet.is_set());
}

#[test]
fn quiet_long_flag_test() {
    assert!(new(vec!["", "--quiet"]).quiet.is_set());
}

#[test]
fn quiet_alt_flag_test() {
    assert!(new(vec!["", "--batch"]).quiet.is_set());
}

#[test]
fn help_short_flag_test() {
    assert!(new(vec!["", "-h"]).help.is_set());
}

#[test]
fn help_long_flag_test() {
    assert!(new(vec!["", "--help"]).help.is_set());
}

#[test]
fn help_alt_flag_test() {
    assert!(new(vec!["", "--info"]).help.is_set());
}

#[test]
fn flags_do_not_affect_other_args_test() {
    let url = "postgresql://host/db";
    let tbl = "myschema.table";
    let cfg = new(vec!["", "-v", "--quiet", url, tbl]);
    assert!(cfg.verbose.is_set());
    assert!(cfg.quiet.is_set());
    assert_eq!(url, cfg.db_url);
    assert_eq!(tbl, cfg.table);
}

#[test]
fn short_flag_not_consumed_as_positional_token_test() {
    // -v should not be picked up as the token command
    let cfg = new(vec!["", "-v"]);
    assert!(cfg.token.cmd.is_empty());
}

#[test]
fn verbose_and_quiet_together_test() {
    let cfg = new(vec!["", "-v", "-q"]);
    assert!(cfg.verbose.is_set());
    assert!(cfg.quiet.is_set());
}