use clap::ArgMatches;
use crate::error::ErrorKind::InvalidProxyConfig;
use failure::Error;
use getset::{Getters, Setters};
use std::convert::TryFrom;
#[derive(Clone, Debug, Default, Getters, Hash, Eq, PartialEq, Setters)]
pub struct Proxy {
#[get = "pub"]
#[set = "pub"]
use_proxy: bool,
#[get = "pub"]
#[set = "pub"]
proxy_url: Option<String>,
#[get = "pub"]
#[set = "pub"]
proxy_username: Option<String>,
#[get = "pub"]
#[set = "pub"]
proxy_password: Option<String>,
}
impl Proxy {
pub fn new(use_proxy: bool, proxy_url: Option<String>) -> Self {
Self {
use_proxy,
proxy_url,
proxy_username: None,
proxy_password: None,
}
}
}
impl<'a> TryFrom<&'a ArgMatches<'a>> for Proxy {
type Error = Error;
fn try_from(matches: &'a ArgMatches<'a>) -> Result<Self, Error> {
let use_proxy = matches.is_present("proxy");
let proxy_url = matches.value_of("proxy-url").map(|s| s.to_string());
let proxy_username = matches.value_of("proxy-username").map(|s| s.to_string());
let proxy_password = matches.value_of("proxy-password").map(|s| s.to_string());
if use_proxy && proxy_url.is_some() {
Ok(Self {
proxy_url,
use_proxy,
proxy_username,
proxy_password,
})
} else if use_proxy && proxy_url.is_none() {
Err(InvalidProxyConfig.into())
} else {
Ok(Self {
proxy_url,
use_proxy,
proxy_username,
proxy_password,
})
}
}
}
#[cfg(test)]
mod test {
use super::Proxy;
use clap::{App, Arg};
use std::convert::TryFrom;
fn test_cli() -> App<'static, 'static> {
App::new("proxy-config-test")
.version("1")
.author("Yoda")
.about("command line for proxy config testing")
.arg(
Arg::with_name("proxy")
.short("p")
.long("proxy")
.requires("proxy-url")
.help("Use a proxy"),
)
.arg(
Arg::with_name("proxy-url")
.long("proxy-url")
.takes_value(true)
.value_name("PROXY_URL")
.help("Your proxy url, if applicable"),
)
.arg(
Arg::with_name("proxy-username")
.long("proxy-username")
.takes_value(true)
.value_name("PROXY_USER")
.help("Your proxy username, if applicable"),
)
.arg(
Arg::with_name("proxy-password")
.long("proxy-password")
.takes_value(true)
.value_name("PROXY_PASS")
.help("Your proxy password, if applicable"),
)
}
fn test_cli_no_requires() -> App<'static, 'static> {
App::new("proxy-config-test")
.version("1")
.author("Yoda")
.about("command line for proxy config testing")
.arg(
Arg::with_name("proxy")
.short("p")
.long("proxy")
.help("Use a proxy"),
)
.arg(
Arg::with_name("proxy-url")
.long("proxy-url")
.takes_value(true)
.value_name("PROXY_URL")
.help("Your proxy url, if applicable"),
)
}
#[test]
fn default_is_disabled() {
let proxy_config = Proxy::default();
assert!(!proxy_config.use_proxy());
}
#[test]
fn from_all_args() {
let arg_vec = vec![
"test-cli",
"-p",
"--proxy-url",
"http://a.proxy.com",
"--proxy-username",
"test",
"--proxy-password",
"test",
];
let matches = test_cli().get_matches_from(arg_vec);
match Proxy::try_from(&matches) {
Ok(proxy_config) => {
assert!(proxy_config.use_proxy());
assert_eq!(
proxy_config.proxy_url(),
&Some("http://a.proxy.com".to_string())
);
assert_eq!(proxy_config.proxy_username(), &Some("test".to_string()));
assert_eq!(proxy_config.proxy_password(), &Some("test".to_string()));
}
Err(_) => assert!(false, "Not expected to error!"),
}
}
#[test]
fn no_username_password() {
let arg_vec = vec!["test-cli", "-p", "--proxy-url", "http://a.proxy.com"];
let matches = test_cli().get_matches_from(arg_vec);
match Proxy::try_from(&matches) {
Ok(proxy_config) => {
assert!(proxy_config.use_proxy());
assert_eq!(
proxy_config.proxy_url(),
&Some("http://a.proxy.com".to_string())
);
assert!(proxy_config.proxy_username().is_none());
assert!(proxy_config.proxy_password().is_none());
}
Err(_) => assert!(false, "Not expected to error!"),
}
}
#[test]
fn proxy_requires_proxy_url() {
let arg_vec = vec!["test-cli", "-p", "--proxy-username", "password"];
assert!(test_cli().get_matches_from_safe(arg_vec).is_err());
}
#[test]
fn proxy_config_requires_proxy_url() {
let arg_vec = vec!["test-cli", "-p"];
let matches = test_cli_no_requires().get_matches_from(arg_vec);
match Proxy::try_from(&matches) {
Ok(_) => assert!(false, "Not expected to succeed!"),
Err(e) => assert_eq!(
format!("{}", e),
"invalid proxy configuration! proxy url is required"
),
}
}
}