use crate::QueueID;
#[non_exhaustive]
#[derive(clap::Parser)]
#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
#[clap(about, author)]
pub struct Args {
#[clap(short, long, action)]
pub version: bool,
#[arg(default_value_t = Args::default_config_location())]
#[clap(short, long, action)]
pub config: String,
#[clap(subcommand)]
pub command: Option<Commands>,
}
impl Args {
fn default_config_location() -> String {
String::from("/etc/vsmtp/vsmtp.vsl")
}
}
#[non_exhaustive]
#[derive(clap::Subcommand)]
#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
pub enum Commands {
Show {
#[clap(value_parser)]
queues: Vec<QueueID>,
#[clap(short, long, action, default_value = "0")]
empty_token: char,
},
Msg {
#[clap(value_parser = parse_uuid)]
msg: uuid::Uuid,
#[clap(subcommand)]
command: MessageCommand,
},
}
fn parse_uuid(value: &str) -> Result<uuid::Uuid, clap::Error> {
uuid::Uuid::parse_str(value)
.map_err(|_err| clap::Error::new(clap::error::ErrorKind::ValueValidation))
}
#[non_exhaustive]
#[derive(Clone, clap::Subcommand)]
#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
pub enum MessageCommand {
Show {
#[clap(value_enum, value_parser, default_value = "json")]
format: MessageShowFormat,
},
Move {
#[clap(value_parser)]
queue: QueueID,
},
Remove {
#[clap(short, long, value_parser)]
yes: bool,
},
ReRun {},
}
#[non_exhaustive]
#[derive(Clone, clap::ValueEnum)]
#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
pub enum MessageShowFormat {
Eml,
Json,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn arg_show_version() {
assert_eq!(
Args {
version: true,
config: Args::default_config_location(),
command: None,
},
<Args as clap::Parser>::try_parse_from(["", "--version"]).unwrap()
);
}
#[test]
fn arg_show_help() {
assert_eq!(
<Args as clap::Parser>::try_parse_from(["", "--help"])
.unwrap_err()
.kind(),
clap::error::ErrorKind::DisplayHelp,
);
}
#[test]
fn arg_show_queue() {
assert_eq!(
Args {
version: false,
config: Args::default_config_location(),
command: Some(Commands::Show {
queues: vec![],
empty_token: '0'
})
},
<Args as clap::Parser>::try_parse_from(["", "show"]).unwrap()
);
assert_eq!(
Args {
version: false,
config: Args::default_config_location(),
command: Some(Commands::Show {
queues: vec![QueueID::Dead],
empty_token: '0'
})
},
<Args as clap::Parser>::try_parse_from(["", "show", "dead"]).unwrap()
);
assert_eq!(
Args {
version: false,
config: Args::default_config_location(),
command: Some(Commands::Show {
queues: vec![],
empty_token: '.'
})
},
<Args as clap::Parser>::try_parse_from(["", "show", "-e", "."]).unwrap()
);
assert_eq!(
Args {
version: false,
config: Args::default_config_location(),
command: Some(Commands::Show {
queues: vec![QueueID::Dead, QueueID::Deliver],
empty_token: '0'
})
},
<Args as clap::Parser>::try_parse_from(["", "show", "dead", "deliver"]).unwrap()
);
}
#[test]
fn arg_show_message() {
assert_eq!(
Args {
version: false,
config: Args::default_config_location(),
command: Some(Commands::Msg {
msg: uuid::Uuid::nil(),
command: MessageCommand::Show {
format: MessageShowFormat::Json
}
})
},
<Args as clap::Parser>::try_parse_from([
"",
"msg",
"00000000-0000-0000-0000-000000000000",
"show"
])
.unwrap()
);
assert_eq!(
Args {
version: false,
config: Args::default_config_location(),
command: Some(Commands::Msg {
msg: uuid::Uuid::nil(),
command: MessageCommand::Show {
format: MessageShowFormat::Json
}
})
},
<Args as clap::Parser>::try_parse_from([
"",
"msg",
"00000000-0000-0000-0000-000000000000",
"show",
"json"
])
.unwrap()
);
assert_eq!(
Args {
version: false,
config: Args::default_config_location(),
command: Some(Commands::Msg {
msg: uuid::Uuid::nil(),
command: MessageCommand::Show {
format: MessageShowFormat::Eml
}
})
},
<Args as clap::Parser>::try_parse_from([
"",
"msg",
"00000000-0000-0000-0000-000000000000",
"show",
"eml"
])
.unwrap()
);
}
#[test]
fn arg_move_message() {
assert_eq!(
Args {
version: false,
config: Args::default_config_location(),
command: Some(Commands::Msg {
msg: uuid::Uuid::nil(),
command: MessageCommand::Move {
queue: QueueID::Dead
}
})
},
<Args as clap::Parser>::try_parse_from([
"",
"msg",
"00000000-0000-0000-0000-000000000000",
"move",
"dead"
])
.unwrap()
);
}
#[test]
fn arg_remove_message() {
assert_eq!(
Args {
version: false,
config: Args::default_config_location(),
command: Some(Commands::Msg {
msg: uuid::Uuid::nil(),
command: MessageCommand::Remove { yes: false }
})
},
<Args as clap::Parser>::try_parse_from([
"",
"msg",
"00000000-0000-0000-0000-000000000000",
"remove"
])
.unwrap()
);
assert_eq!(
Args {
version: false,
config: Args::default_config_location(),
command: Some(Commands::Msg {
msg: uuid::Uuid::nil(),
command: MessageCommand::Remove { yes: true }
})
},
<Args as clap::Parser>::try_parse_from([
"",
"msg",
"00000000-0000-0000-0000-000000000000",
"remove",
"--yes"
])
.unwrap()
);
}
}