Files

643 lines
14 KiB
Rust
Raw Permalink Normal View History

2023-02-14 00:51:27 +01:00
use std::ffi::OsStr;
2023-12-02 17:40:52 +01:00
use uutils_args::{Arguments, Options, Value, ValueResult};
2022-12-02 13:49:12 +01:00
#[test]
fn string_option() {
#[derive(Arguments)]
2022-12-02 13:49:12 +01:00
enum Arg {
#[arg("--message=MSG")]
2022-12-02 13:49:12 +01:00
Message(String),
}
2023-12-02 17:40:52 +01:00
#[derive(Default)]
2022-12-02 13:49:12 +01:00
struct Settings {
message: String,
}
impl Options<Arg> for Settings {
2024-03-29 03:32:30 +01:00
fn apply(&mut self, Arg::Message(s): Arg) -> Result<(), uutils_args::Error> {
self.message = s;
Ok(())
}
}
2022-12-02 13:49:12 +01:00
assert_eq!(
2023-12-02 17:40:52 +01:00
Settings::default()
.parse(["test", "--message=hello"])
2023-12-19 15:13:12 +01:00
.unwrap()
.0
2023-12-02 17:40:52 +01:00
.message,
2022-12-02 13:49:12 +01:00
"hello"
);
}
#[test]
fn enum_option() {
2023-02-14 00:51:27 +01:00
#[derive(Value, Default, Debug, PartialEq, Eq, Clone)]
2022-12-02 13:49:12 +01:00
enum Format {
#[default]
#[value]
Foo,
#[value]
Bar,
#[value]
Baz,
}
#[derive(Arguments)]
2022-12-02 13:49:12 +01:00
enum Arg {
#[arg("--format=FORMAT")]
2022-12-02 13:49:12 +01:00
Format(Format),
}
2023-12-02 17:40:52 +01:00
#[derive(Default)]
2022-12-02 13:49:12 +01:00
struct Settings {
format: Format,
}
impl Options<Arg> for Settings {
2024-03-29 03:32:30 +01:00
fn apply(&mut self, Arg::Format(f): Arg) -> Result<(), uutils_args::Error> {
self.format = f;
2024-03-29 03:32:30 +01:00
Ok(())
}
}
2022-12-02 13:49:12 +01:00
assert_eq!(
2023-12-19 15:13:12 +01:00
Settings::default()
.parse(["test", "--format=bar"])
.unwrap()
.0
.format,
2022-12-02 13:49:12 +01:00
Format::Bar
);
assert_eq!(
2023-12-02 17:40:52 +01:00
Settings::default()
.parse(["test", "--format", "baz"])
2023-12-19 15:13:12 +01:00
.unwrap()
.0
2023-12-02 17:40:52 +01:00
.format,
2022-12-02 13:49:12 +01:00
Format::Baz
);
}
#[test]
fn enum_option_with_fields() {
2023-02-14 00:51:27 +01:00
#[derive(Value, Default, Debug, PartialEq, Eq)]
2022-12-02 13:49:12 +01:00
enum Indent {
#[default]
Tabs,
#[value("thin", value = Self::Spaces(4))]
#[value("wide", value = Self::Spaces(8))]
Spaces(u8),
}
#[derive(Arguments)]
2022-12-02 13:49:12 +01:00
enum Arg {
#[arg("-i INDENT")]
2022-12-02 13:49:12 +01:00
Indent(Indent),
}
2023-12-02 17:40:52 +01:00
#[derive(Default)]
2022-12-02 13:49:12 +01:00
struct Settings {
indent: Indent,
}
impl Options<Arg> for Settings {
2024-03-29 03:32:30 +01:00
fn apply(&mut self, Arg::Indent(i): Arg) -> Result<(), uutils_args::Error> {
self.indent = i;
2024-03-29 03:32:30 +01:00
Ok(())
}
}
2022-12-02 13:49:12 +01:00
assert_eq!(
2023-12-19 15:13:12 +01:00
Settings::default()
.parse(["test", "-i=thin"])
.unwrap()
.0
.indent,
2022-12-02 13:49:12 +01:00
Indent::Spaces(4)
);
assert_eq!(
2023-12-19 15:13:12 +01:00
Settings::default()
.parse(["test", "-i=wide"])
.unwrap()
.0
.indent,
2022-12-02 13:49:12 +01:00
Indent::Spaces(8)
);
}
#[test]
fn enum_with_complex_from_value() {
#[derive(Default, Debug, PartialEq, Eq, Clone)]
enum Indent {
#[default]
Tabs,
Spaces(u8),
}
2023-02-14 00:51:27 +01:00
impl Value for Indent {
fn from_value(value: &std::ffi::OsStr) -> ValueResult<Self> {
let value = String::from_value(value)?;
2022-12-02 13:49:12 +01:00
if value == "tabs" {
Ok(Self::Tabs)
} else if let Ok(n) = value.parse() {
Ok(Self::Spaces(n))
} else {
2023-02-14 00:51:27 +01:00
Err("Failure!".into())
2022-12-02 13:49:12 +01:00
}
}
}
#[derive(Arguments)]
2022-12-02 13:49:12 +01:00
enum Arg {
#[arg("-i INDENT")]
2022-12-02 13:49:12 +01:00
Indent(Indent),
}
2023-12-02 17:40:52 +01:00
#[derive(Default)]
2022-12-02 13:49:12 +01:00
struct Settings {
indent: Indent,
}
impl Options<Arg> for Settings {
2024-03-29 03:32:30 +01:00
fn apply(&mut self, Arg::Indent(i): Arg) -> Result<(), uutils_args::Error> {
self.indent = i;
2024-03-29 03:32:30 +01:00
Ok(())
}
}
2023-12-02 17:40:52 +01:00
assert_eq!(
2023-12-19 15:13:12 +01:00
Settings::default()
.parse(["test", "-i=tabs"])
.unwrap()
.0
.indent,
2023-12-02 17:40:52 +01:00
Indent::Tabs
);
assert_eq!(
2023-12-19 15:13:12 +01:00
Settings::default()
.parse(["test", "-i=4"])
.unwrap()
.0
.indent,
2023-12-02 17:40:52 +01:00
Indent::Spaces(4)
);
2022-12-02 13:49:12 +01:00
}
#[test]
fn color() {
2023-02-14 00:51:27 +01:00
#[derive(Default, Value, Debug, PartialEq, Eq)]
2022-12-02 13:49:12 +01:00
enum Color {
#[value("yes", "always")]
Always,
#[default]
#[value("auto")]
Auto,
#[value("no", "never")]
Never,
}
#[derive(Arguments)]
2022-12-02 13:49:12 +01:00
enum Arg {
#[arg("--color[=WHEN]")]
2022-12-02 13:49:12 +01:00
Color(Option<Color>),
}
2023-12-02 17:40:52 +01:00
#[derive(Default)]
2022-12-02 13:49:12 +01:00
struct Settings {
color: Color,
}
impl Options<Arg> for Settings {
2024-03-29 03:32:30 +01:00
fn apply(&mut self, Arg::Color(c): Arg) -> Result<(), uutils_args::Error> {
self.color = c.unwrap_or(Color::Always);
2024-03-29 03:32:30 +01:00
Ok(())
}
}
2022-12-02 13:49:12 +01:00
assert_eq!(
Settings::default()
2023-12-19 15:13:12 +01:00
.parse(["test", "--color=yes"])
.unwrap()
.0
.color,
2022-12-02 13:49:12 +01:00
Color::Always
);
assert_eq!(
2023-12-19 15:13:12 +01:00
Settings::default()
.parse(["test", "--color=always"])
.unwrap()
.0
.color,
Color::Always
);
assert_eq!(
Settings::default()
.parse(["test", "--color=no"])
.unwrap()
.0
.color,
2022-12-02 13:49:12 +01:00
Color::Never
);
2023-12-02 17:40:52 +01:00
assert_eq!(
2023-12-19 15:13:12 +01:00
Settings::default()
.parse(["test", "--color=never"])
.unwrap()
.0
.color,
2023-12-02 17:40:52 +01:00
Color::Never
);
assert_eq!(
2023-12-19 15:13:12 +01:00
Settings::default()
.parse(["test", "--color=auto"])
.unwrap()
.0
.color,
2023-12-02 17:40:52 +01:00
Color::Auto
);
assert_eq!(
2023-12-19 15:13:12 +01:00
Settings::default()
.parse(["test", "--color"])
.unwrap()
.0
.color,
2023-12-02 17:40:52 +01:00
Color::Always
)
2022-12-02 13:49:12 +01:00
}
#[test]
fn actions() {
#[derive(Arguments)]
2022-12-02 13:49:12 +01:00
enum Arg {
#[arg("-m MESSAGE")]
2022-12-02 13:49:12 +01:00
Message(String),
#[arg("--send")]
2022-12-02 13:49:12 +01:00
Send,
#[arg("--receive")]
2022-12-02 13:49:12 +01:00
Receive,
}
2023-12-02 17:40:52 +01:00
#[derive(Default)]
2022-12-02 13:49:12 +01:00
struct Settings {
last_message: String,
2022-12-02 13:49:12 +01:00
send: bool,
messages: Vec<String>,
}
impl Options<Arg> for Settings {
2024-03-29 03:32:30 +01:00
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
match arg {
Arg::Message(m) => {
2024-05-09 21:02:30 +02:00
self.last_message.clone_from(&m);
self.messages.push(m);
}
Arg::Send => self.send = true,
Arg::Receive => self.send = false,
}
2024-03-29 03:32:30 +01:00
Ok(())
}
}
2023-12-19 15:13:12 +01:00
let (settings, _operands) = Settings::default()
.parse(["test", "-m=Hello", "-m=World", "--send"])
.unwrap();
2022-12-02 13:49:12 +01:00
assert_eq!(settings.messages, vec!["Hello", "World"]);
assert_eq!(settings.last_message, "World");
2022-12-02 13:49:12 +01:00
assert!(settings.send);
}
2022-12-03 18:50:46 +01:00
#[test]
fn width() {
#[derive(Arguments)]
2022-12-03 18:50:46 +01:00
enum Arg {
#[arg("-w WIDTH")]
2022-12-03 18:50:46 +01:00
Width(u64),
}
2023-12-02 17:40:52 +01:00
#[derive(Default)]
2022-12-03 18:50:46 +01:00
struct Settings {
2022-12-10 15:54:31 +01:00
width: Option<u64>,
2022-12-03 18:50:46 +01:00
}
impl Options<Arg> for Settings {
2024-03-29 03:32:30 +01:00
fn apply(&mut self, Arg::Width(w): Arg) -> Result<(), uutils_args::Error> {
self.width = match w {
0 => None,
x => Some(x),
2024-03-29 03:32:30 +01:00
};
Ok(())
}
}
2023-12-19 15:13:12 +01:00
assert_eq!(
Settings::default().parse(["test", "-w=0"]).unwrap().0.width,
None
);
assert_eq!(
Settings::default().parse(["test", "-w=1"]).unwrap().0.width,
Some(1)
);
2022-12-03 18:50:46 +01:00
}
#[test]
fn integers() {
#[derive(Arguments)]
2022-12-03 18:50:46 +01:00
enum Arg {
#[arg("--u8=N")]
2022-12-03 18:50:46 +01:00
U8(u8),
#[arg("--u16=N")]
2022-12-03 18:50:46 +01:00
U16(u16),
#[arg("--u32=N")]
2022-12-03 18:50:46 +01:00
U32(u32),
#[arg("--u64=N")]
2022-12-03 18:50:46 +01:00
U64(u64),
#[arg("--u128=N")]
2022-12-03 18:50:46 +01:00
U128(u128),
#[arg("--i8=N")]
2022-12-03 18:50:46 +01:00
I8(i8),
#[arg("--i16=N")]
2022-12-03 18:50:46 +01:00
I16(i16),
#[arg("--i32=N")]
2022-12-03 18:50:46 +01:00
I32(i32),
#[arg("--i64=N")]
2022-12-03 18:50:46 +01:00
I64(i64),
#[arg("--i128=N")]
2022-12-03 18:50:46 +01:00
I128(i128),
}
2023-12-02 17:40:52 +01:00
#[derive(Default)]
2022-12-03 18:50:46 +01:00
struct Settings {
n: i128,
}
impl Options<Arg> for Settings {
2024-03-29 03:32:30 +01:00
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
self.n = match arg {
Arg::U8(x) => x as i128,
Arg::U16(x) => x as i128,
Arg::U32(x) => x as i128,
Arg::U64(x) => x as i128,
Arg::U128(x) => x as i128,
Arg::I8(x) => x as i128,
Arg::I16(x) => x as i128,
Arg::I32(x) => x as i128,
Arg::I64(x) => x as i128,
Arg::I128(x) => x,
2024-03-29 03:32:30 +01:00
};
Ok(())
}
}
2023-12-19 15:13:12 +01:00
assert_eq!(
Settings::default().parse(["test", "--u8=5"]).unwrap().0.n,
5
);
assert_eq!(
Settings::default().parse(["test", "--u16=5"]).unwrap().0.n,
5
);
assert_eq!(
Settings::default().parse(["test", "--u32=5"]).unwrap().0.n,
5
);
assert_eq!(
Settings::default().parse(["test", "--u64=5"]).unwrap().0.n,
5
);
assert_eq!(
Settings::default().parse(["test", "--u128=5"]).unwrap().0.n,
5
);
2022-12-03 18:50:46 +01:00
2023-12-19 15:13:12 +01:00
assert_eq!(
Settings::default().parse(["test", "--i8=5"]).unwrap().0.n,
5
);
assert_eq!(
Settings::default().parse(["test", "--i16=5"]).unwrap().0.n,
5
);
assert_eq!(
Settings::default().parse(["test", "--i32=5"]).unwrap().0.n,
5
);
assert_eq!(
Settings::default().parse(["test", "--i64=5"]).unwrap().0.n,
5
);
assert_eq!(
Settings::default().parse(["test", "--i128=5"]).unwrap().0.n,
5
);
2022-12-03 18:50:46 +01:00
}
2022-12-14 23:56:43 +01:00
#[test]
fn ls_classify() {
2023-02-14 00:51:27 +01:00
#[derive(Value, Default, PartialEq, Eq, Debug)]
2022-12-14 23:56:43 +01:00
enum When {
#[value]
Never,
#[default]
#[value]
Auto,
#[value]
Always,
}
#[derive(Arguments)]
2022-12-14 23:56:43 +01:00
enum Arg {
#[arg(
2022-12-14 23:56:43 +01:00
"-F", "--classify[=WHEN]",
2023-12-07 12:51:30 +01:00
value = When::Always,
2022-12-14 23:56:43 +01:00
)]
Classify(When),
}
2023-12-02 17:40:52 +01:00
#[derive(Default)]
2022-12-14 23:56:43 +01:00
struct Settings {
classify: When,
}
impl Options<Arg> for Settings {
2024-03-29 03:32:30 +01:00
fn apply(&mut self, Arg::Classify(c): Arg) -> Result<(), uutils_args::Error> {
self.classify = c;
2024-03-29 03:32:30 +01:00
Ok(())
}
}
2023-12-19 15:13:12 +01:00
assert_eq!(
Settings::default().parse(["test"]).unwrap().0.classify,
When::Auto
);
2022-12-14 23:56:43 +01:00
assert_eq!(
2023-12-02 17:40:52 +01:00
Settings::default()
.parse(["test", "--classify=never"])
2023-12-19 15:13:12 +01:00
.unwrap()
.0
2023-12-02 17:40:52 +01:00
.classify,
2022-12-14 23:56:43 +01:00
When::Never,
);
assert_eq!(
2023-12-19 15:13:12 +01:00
Settings::default()
.parse(["test", "--classify"])
.unwrap()
.0
.classify,
2022-12-14 23:56:43 +01:00
When::Always,
);
2023-12-02 17:40:52 +01:00
assert_eq!(
2023-12-19 15:13:12 +01:00
Settings::default()
.parse(["test", "-F"])
.unwrap()
.0
.classify,
2023-12-02 17:40:52 +01:00
When::Always,
);
2023-12-19 15:13:12 +01:00
assert!(Settings::default().parse(["test", "-Falways"]).is_err());
2022-12-14 23:56:43 +01:00
}
#[test]
fn mktemp_tmpdir() {
#[derive(Clone, Arguments)]
enum Arg {
#[arg(
2022-12-14 23:56:43 +01:00
"-p DIR", "--tmpdir[=DIR]",
2023-12-07 12:51:30 +01:00
value = String::from("/tmp"),
2022-12-14 23:56:43 +01:00
)]
TmpDir(String),
}
2023-12-02 17:40:52 +01:00
#[derive(Default)]
2022-12-14 23:56:43 +01:00
struct Settings {
tmpdir: Option<String>,
}
impl Options<Arg> for Settings {
2024-03-29 03:32:30 +01:00
fn apply(&mut self, Arg::TmpDir(dir): Arg) -> Result<(), uutils_args::Error> {
self.tmpdir = Some(dir);
2024-03-29 03:32:30 +01:00
Ok(())
}
}
2023-12-19 15:13:12 +01:00
let (settings, _operands) = Settings::default().parse(["test", "-p", "X"]).unwrap();
2022-12-14 23:56:43 +01:00
assert_eq!(settings.tmpdir.unwrap(), "X");
2023-12-19 15:13:12 +01:00
let (settings, _operands) = Settings::default().parse(["test", "--tmpdir=X"]).unwrap();
2022-12-14 23:56:43 +01:00
assert_eq!(settings.tmpdir.unwrap(), "X");
2023-12-19 15:13:12 +01:00
let (settings, _operands) = Settings::default().parse(["test", "--tmpdir"]).unwrap();
2022-12-14 23:56:43 +01:00
assert_eq!(settings.tmpdir.unwrap(), "/tmp");
2023-12-19 15:13:12 +01:00
assert!(Settings::default().parse(["test", "-p"]).is_err());
2022-12-14 23:56:43 +01:00
}
#[test]
fn infer_value() {
2023-02-14 00:51:27 +01:00
#[derive(Value, PartialEq, Eq, Debug)]
enum Foo {
#[value("long")]
Long,
#[value("link")]
Link,
#[value("deck")]
Deck,
#[value("desk")]
Desk,
}
2023-02-14 00:51:27 +01:00
assert_eq!(Foo::from_value(OsStr::new("lo")).unwrap(), Foo::Long);
assert_eq!(Foo::from_value(OsStr::new("dec")).unwrap(), Foo::Deck);
2023-02-14 00:51:27 +01:00
Foo::from_value(OsStr::new("l")).unwrap_err();
Foo::from_value(OsStr::new("de")).unwrap_err();
}
#[test]
fn deprecated() {
2023-11-01 12:23:39 +01:00
fn parse_minus(s: &str) -> Option<&str> {
let num = s.strip_prefix('-')?;
if num.chars().all(|c| c.is_ascii_digit()) {
Some(num)
} else {
None
}
}
fn parse_plus(s: &str) -> Option<&str> {
let num = s.strip_prefix('+')?;
let num2 = num.strip_prefix('-').unwrap_or(num);
if num2.chars().all(|c| c.is_ascii_digit()) {
Some(num)
} else {
None
}
}
#[derive(Arguments)]
enum Arg {
#[arg(parse_minus)]
Min(usize),
#[arg(parse_plus)]
Plus(isize),
}
2023-12-02 17:40:52 +01:00
#[derive(Default)]
struct Settings {
n1: usize,
n2: isize,
}
impl Options<Arg> for Settings {
2024-03-29 03:32:30 +01:00
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
match arg {
Arg::Min(n) => self.n1 = n,
Arg::Plus(n) => self.n2 = n,
}
2024-03-29 03:32:30 +01:00
Ok(())
}
}
2023-12-19 15:13:12 +01:00
assert_eq!(
Settings::default().parse(["test", "-10"]).unwrap().0.n1,
10usize
);
assert!(Settings::default().parse(["test", "--10"]).is_err());
assert_eq!(
Settings::default().parse(["test", "+10"]).unwrap().0.n2,
10isize
);
assert_eq!(
Settings::default().parse(["test", "+-10"]).unwrap().0.n2,
-10isize
);
}
2023-12-19 16:34:05 +01:00
#[test]
#[allow(unreachable_code)]
fn empty_value() {
// We just check that this compiles
#[derive(Value)]
enum V {}
#[derive(Arguments)]
enum Arg {
#[arg("--val=VAL")]
Val(V),
}
2024-05-09 21:02:30 +02:00
#[allow(dead_code)]
2023-12-19 16:34:05 +01:00
struct Settings {}
impl Options<Arg> for Settings {
2024-03-29 03:32:30 +01:00
fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> {
2023-12-19 16:34:05 +01:00
match arg {
Arg::Val(_) => {}
}
2024-03-29 03:32:30 +01:00
Ok(())
2023-12-19 16:34:05 +01:00
}
}
}