use facet::Facet;
use facet_args as args;
#[test]
fn test_arg_parse_easy() {
#[derive(Facet)]
struct Args {
#[facet(args::positional)]
path: String,
#[facet(args::named, args::short = 'v')]
verbose: bool,
#[facet(args::named, args::short = 'j')]
concurrency: usize,
#[facet(args::named, args::short = 'x')]
consider_casing: usize,
}
let args: Args = facet_args::from_slice(&[
"--verbose",
"-j",
"14",
"--consider-casing",
"0",
"example.rs",
])
.unwrap();
assert!(args.verbose);
assert_eq!(args.path, "example.rs");
assert_eq!(args.concurrency, 14);
assert_eq!(args.consider_casing, 0);
}
#[test]
fn test_arg_parse_nums() {
#[derive(Facet)]
struct Args {
#[facet(args::named, args::short)]
x: i64,
#[facet(args::named, args::short)]
y: u64,
#[facet(args::named, args::short = 'z')]
zzz: f64,
}
let args: Args = facet_args::from_slice(&["-x", "1", "-y", "2", "-z", "3"]).unwrap();
assert_eq!(args.x, 1);
assert_eq!(args.y, 2);
assert_eq!(args.zzz, 3.0);
}
#[test]
fn test_missing_bool_is_false() {
#[derive(Facet)]
struct Args {
#[facet(args::named, args::short = 'v')]
verbose: bool,
#[facet(args::positional)]
path: String,
}
let args: Args = facet_args::from_slice(&["absence_is_falsey.rs"]).unwrap();
assert!(!args.verbose);
}
#[test]
fn test_missing_default() {
#[derive(Facet, Debug)]
struct Args {
#[facet(args::positional, default = 42)]
answer: usize,
#[facet(args::named, args::short = 'p')]
path: String,
}
let args: Args = facet_args::from_slice(&["-p", "absence_uses_default.rs"]).unwrap();
assert_eq!(args.answer, 42);
assert_eq!(args.path, "absence_uses_default.rs".to_string());
let args: Args =
facet_args::from_slice(&["100", "-p", "presence_overrides_default.rs"]).unwrap();
assert_eq!(args.answer, 100);
assert_eq!(args.path, "presence_overrides_default.rs".to_string());
}
#[test]
fn test_missing_default_fn() {
fn default_concurrency() -> usize {
2 + 2
}
#[derive(Facet, Debug)]
struct Args {
#[facet(args::named, args::short = 'p')]
path: String,
#[facet(args::named, args::short = 'j', default = default_concurrency())]
concurrency: usize,
}
let args: Args = facet_args::from_slice(&["-p", "absence_uses_default_fn.rs"]).unwrap();
assert_eq!(args.path, "absence_uses_default_fn.rs".to_string());
assert_eq!(args.concurrency, 4);
let args: Args =
facet_args::from_slice(&["-p", "presence_overrides_default_fn.rs", "-j", "2"]).unwrap();
assert_eq!(args.path, "presence_overrides_default_fn.rs".to_string());
assert_eq!(args.concurrency, 2);
}
#[test]
fn test_inf_float_parsing() {
#[derive(Facet, Debug)]
struct Args {
#[facet(args::named)]
rate: f64,
}
let args: Args = facet_args::from_slice(&["--rate", "infinity"]).unwrap();
assert_eq!(args.rate, f64::INFINITY);
}
#[test]
fn test_short_rename() {
#[derive(Facet, Debug)]
struct Args {
#[facet(args::named, args::short, rename = "j")]
concurrency: i64,
}
let args: Args = facet_args::from_slice(&["-j", "4"]).unwrap();
assert_eq!(args.concurrency, 4);
}
#[test]
fn test_bool_str_before() {
#[derive(Facet, Debug)]
struct Args {
#[facet(args::named)]
foo: bool,
#[facet(args::named)]
hello: String,
}
let args: Args = facet_args::from_slice(&["--foo", "--hello", "world"]).unwrap();
assert!(args.foo);
assert_eq!(args.hello, "world".to_string());
}
#[test]
fn test_option_string_positional() {
#[derive(Facet, Debug)]
struct Args {
#[facet(args::positional, default)]
path: Option<String>,
}
let args: Args = facet_args::from_slice(&["."]).unwrap();
assert_eq!(args.path, Some(".".to_string()));
let args: Args = facet_args::from_slice(&[]).unwrap();
assert_eq!(args.path, None);
}
#[test]
fn test_string_default_value() {
#[derive(Facet, Debug)]
struct Args {
#[facet(args::named)]
name: String,
#[facet(args::named, default = "0.0.0-test")]
version: String,
}
let args: Args = facet_args::from_slice(&["--name", "myapp"]).unwrap();
assert_eq!(args.name, "myapp");
assert_eq!(args.version, "0.0.0-test");
let args: Args = facet_args::from_slice(&["--name", "myapp", "--version", "1.0.0"]).unwrap();
assert_eq!(args.name, "myapp");
assert_eq!(args.version, "1.0.0");
}
#[test]
fn test_ip_address_default_value() {
use std::net::{IpAddr, Ipv4Addr};
#[derive(Facet, Debug)]
struct ServerConfig {
#[facet(args::named)]
name: String,
#[facet(args::named, default = "127.0.0.1")]
bind_addr: IpAddr,
}
let config: ServerConfig = facet_args::from_slice(&["--name", "myserver"]).unwrap();
assert_eq!(config.name, "myserver");
assert_eq!(config.bind_addr, IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
let config: ServerConfig =
facet_args::from_slice(&["--name", "myserver", "--bind-addr", "0.0.0.0"]).unwrap();
assert_eq!(config.bind_addr, IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)));
}
#[test]
fn test_pathbuf_default_value() {
use std::path::PathBuf;
#[derive(Facet, Debug)]
struct FileConfig {
#[facet(args::named)]
name: String,
#[facet(args::named, default = "/tmp/default.log")]
log_path: PathBuf,
}
let config: FileConfig = facet_args::from_slice(&["--name", "myapp"]).unwrap();
assert_eq!(config.name, "myapp");
assert_eq!(config.log_path, PathBuf::from("/tmp/default.log"));
let config: FileConfig =
facet_args::from_slice(&["--name", "myapp", "--log-path", "/var/log/app.log"]).unwrap();
assert_eq!(config.name, "myapp");
assert_eq!(config.log_path, PathBuf::from("/var/log/app.log"));
}
#[test]
fn test_option_named_struct() {
#[derive(Facet, Debug)]
struct Args {
#[facet(args::named)]
name: String,
#[facet(args::named)]
filter: Option<String>,
}
let args: Args = facet_args::from_slice(&["--name", "test"]).unwrap();
assert_eq!(args.name, "test");
assert_eq!(args.filter, None);
let args: Args = facet_args::from_slice(&["--name", "test", "--filter", "active"]).unwrap();
assert_eq!(args.name, "test");
assert_eq!(args.filter, Some("active".to_string()));
}
#[test]
fn test_option_named_enum_variant() {
#[derive(Facet, Debug)]
#[repr(u8)]
enum CliCommand {
Explain {
#[facet(args::named)]
node: Option<String>,
},
}
#[derive(Facet, Debug)]
struct Args {
#[facet(args::subcommand)]
command: CliCommand,
}
let args: Args = facet_args::from_slice(&["explain"]).unwrap();
match args.command {
CliCommand::Explain { node } => {
assert_eq!(node, None);
}
}
let args: Args = facet_args::from_slice(&["explain", "--node", "42"]).unwrap();
match args.command {
CliCommand::Explain { node } => {
assert_eq!(node, Some("42".to_string()));
}
}
}