Skip to content
This repository was archived by the owner on Feb 11, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ roff = "0.2.1"
strsim = "0.11.1"
uutils-args-derive = { version = "0.1.0", path = "derive" }

[dev-dependencies]
trybuild = "1.0.104"

[features]
parse-is-complete = []

Expand Down
84 changes: 0 additions & 84 deletions examples/test_compile_errors_manually.rs

This file was deleted.

41 changes: 41 additions & 0 deletions tests/derive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#[test]
fn derive_error_messages_common() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/derive/arg_bare_keyword.rs");
t.compile_fail("tests/derive/arg_just_minus.rs");
t.compile_fail("tests/derive/arg_key_value.rs");
t.compile_fail("tests/derive/arg_missing_closing_bracket.rs");
t.compile_fail("tests/derive/arg_missing_equals.rs");
t.compile_fail("tests/derive/arg_missing_field.rs");
t.compile_fail("tests/derive/arg_missing_metavar.rs");
t.compile_fail("tests/derive/arguments_file_nonexistent.rs");
t.compile_fail("tests/derive/value_bare_keyword.rs");
t.pass("tests/derive/arg_duplicate_other.rs"); // FIXME: Should fail!
t.pass("tests/derive/arg_duplicate_within.rs"); // FIXME: Should fail!
}

#[cfg(unix)]
#[test]
fn derive_error_messages_unix() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/derive/arguments_file_isdir.rs"); // Needs the directory "/"
}

#[cfg(target_os = "linux")]
#[test]
fn derive_error_messages_linux_writeonly_file() {
use std::fs::metadata;
use std::os::unix::fs::PermissionsExt;

// First, verify that /proc/self/clear_refs exists and is write-only:
// https://man.archlinux.org/man/proc_pid_clear_refs.5.en
let metadata = metadata("/proc/self/clear_refs").expect("should be in Linux 2.6.22");
eprintln!("is_file={}", metadata.is_file());
eprintln!("permissions={:?}", metadata.permissions());
assert_eq!(0o100200, metadata.permissions().mode());

// The file exists, as it should. Now we can run the test, using this
// special write-only file, without having to worry about clean-up:
let t = trybuild::TestCases::new();
t.compile_fail("tests/derive/arguments_file_writeonly.rs");
}
19 changes: 19 additions & 0 deletions tests/derive/arg_bare_keyword.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use uutils_args::{Arguments, Options};

#[derive(Arguments)]
enum Arg {
#[arg(banana)] // Oops!
Something,
}

struct Settings {}

impl Options<Arg> for Settings {
fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> {
Ok(())
}
}

fn main() {
Settings {}.parse(std::env::args_os()).unwrap();
}
16 changes: 16 additions & 0 deletions tests/derive/arg_bare_keyword.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
error[E0425]: cannot find function `banana` in this scope
--> tests/derive/arg_bare_keyword.rs:5:11
|
5 | #[arg(banana)] // Oops!
| ^^^^^^ not found in this scope

error[E0618]: expected function, found `Arg`
--> tests/derive/arg_bare_keyword.rs:3:10
|
3 | #[derive(Arguments)]
| ^^^^^^^^^ call expression requires function
...
6 | Something,
| --------- `Arg::Something` defined here
|
= note: this error originates in the derive macro `Arguments` (in Nightly builds, run with -Z macro-backtrace for more info)
21 changes: 21 additions & 0 deletions tests/derive/arg_duplicate_other.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use uutils_args::{Arguments, Options};

#[derive(Arguments)]
enum Arg {
#[arg("--foo")]
Something,
#[arg("--foo")] // Oops!
Banana,
}

struct Settings {}

impl Options<Arg> for Settings {
fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> {
Ok(())
}
}

fn main() {
Settings {}.parse(std::env::args_os()).unwrap();
}
19 changes: 19 additions & 0 deletions tests/derive/arg_duplicate_within.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use uutils_args::{Arguments, Options};

#[derive(Arguments)]
enum Arg {
#[arg("--foo", "--foo")] // Oops!
Something,
}

struct Settings {}

impl Options<Arg> for Settings {
fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> {
Ok(())
}
}

fn main() {
Settings {}.parse(std::env::args_os()).unwrap();
}
19 changes: 19 additions & 0 deletions tests/derive/arg_just_minus.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use uutils_args::{Arguments, Options};

#[derive(Arguments)]
enum Arg {
#[arg("-")] // Oops!
Something,
}

struct Settings {}

impl Options<Arg> for Settings {
fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> {
Ok(())
}
}

fn main() {
Settings {}.parse(std::env::args_os()).unwrap();
}
34 changes: 34 additions & 0 deletions tests/derive/arg_just_minus.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
error: proc-macro derive panicked
--> tests/derive/arg_just_minus.rs:3:10
|
3 | #[derive(Arguments)]
| ^^^^^^^^^
|
= help: message: flag name must be non-empty (cannot be just '-')

error[E0277]: the trait bound `Arg: uutils_args::Arguments` is not satisfied
--> tests/derive/arg_just_minus.rs:11:6
|
11 | impl Options<Arg> for Settings {
| ^^^^^^^^^^^^ the trait `uutils_args::Arguments` is not implemented for `Arg`
|
note: required by a bound in `Options`
--> src/lib.rs
|
| pub trait Options<Arg: Arguments>: Sized {
| ^^^^^^^^^ required by this bound in `Options`

error[E0277]: the trait bound `Arg: uutils_args::Arguments` is not satisfied
--> tests/derive/arg_just_minus.rs:18:17
|
18 | Settings {}.parse(std::env::args_os()).unwrap();
| ^^^^^ the trait `uutils_args::Arguments` is not implemented for `Arg`
|
note: required by a bound in `uutils_args::Options::parse`
--> src/lib.rs
|
| pub trait Options<Arg: Arguments>: Sized {
| ^^^^^^^^^ required by this bound in `Options::parse`
...
| fn parse<I>(mut self, args: I) -> Result<(Self, Vec<OsString>), Error>
| ----- required by a bound in this associated function
19 changes: 19 additions & 0 deletions tests/derive/arg_key_value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use uutils_args::{Arguments, Options};

#[derive(Arguments)]
enum Arg {
#[arg(key = "name")] // Oops!
Something,
}

struct Settings {}

impl Options<Arg> for Settings {
fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> {
Ok(())
}
}

fn main() {
Settings {}.parse(std::env::args_os()).unwrap();
}
34 changes: 34 additions & 0 deletions tests/derive/arg_key_value.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
error: proc-macro derive panicked
--> tests/derive/arg_key_value.rs:3:10
|
3 | #[derive(Arguments)]
| ^^^^^^^^^
|
= help: message: can't parse arg attributes, expected one or more strings: Error("expected `,`")

error[E0277]: the trait bound `Arg: uutils_args::Arguments` is not satisfied
--> tests/derive/arg_key_value.rs:11:6
|
11 | impl Options<Arg> for Settings {
| ^^^^^^^^^^^^ the trait `uutils_args::Arguments` is not implemented for `Arg`
|
note: required by a bound in `Options`
--> src/lib.rs
|
| pub trait Options<Arg: Arguments>: Sized {
| ^^^^^^^^^ required by this bound in `Options`

error[E0277]: the trait bound `Arg: uutils_args::Arguments` is not satisfied
--> tests/derive/arg_key_value.rs:18:17
|
18 | Settings {}.parse(std::env::args_os()).unwrap();
| ^^^^^ the trait `uutils_args::Arguments` is not implemented for `Arg`
|
note: required by a bound in `uutils_args::Options::parse`
--> src/lib.rs
|
| pub trait Options<Arg: Arguments>: Sized {
| ^^^^^^^^^ required by this bound in `Options::parse`
...
| fn parse<I>(mut self, args: I) -> Result<(Self, Vec<OsString>), Error>
| ----- required by a bound in this associated function
19 changes: 19 additions & 0 deletions tests/derive/arg_missing_closing_bracket.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use uutils_args::{Arguments, Options};

#[derive(Arguments)]
enum Arg {
#[arg("--foo[=FOO")] // Oops!
Something(String),
}

struct Settings {}

impl Options<Arg> for Settings {
fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> {
Ok(())
}
}

fn main() {
Settings {}.parse(std::env::args_os()).unwrap();
}
34 changes: 34 additions & 0 deletions tests/derive/arg_missing_closing_bracket.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
error: proc-macro derive panicked
--> tests/derive/arg_missing_closing_bracket.rs:3:10
|
3 | #[derive(Arguments)]
| ^^^^^^^^^
|
= help: message: expected final ']' in flag pattern

error[E0277]: the trait bound `Arg: uutils_args::Arguments` is not satisfied
--> tests/derive/arg_missing_closing_bracket.rs:11:6
|
11 | impl Options<Arg> for Settings {
| ^^^^^^^^^^^^ the trait `uutils_args::Arguments` is not implemented for `Arg`
|
note: required by a bound in `Options`
--> src/lib.rs
|
| pub trait Options<Arg: Arguments>: Sized {
| ^^^^^^^^^ required by this bound in `Options`

error[E0277]: the trait bound `Arg: uutils_args::Arguments` is not satisfied
--> tests/derive/arg_missing_closing_bracket.rs:18:17
|
18 | Settings {}.parse(std::env::args_os()).unwrap();
| ^^^^^ the trait `uutils_args::Arguments` is not implemented for `Arg`
|
note: required by a bound in `uutils_args::Options::parse`
--> src/lib.rs
|
| pub trait Options<Arg: Arguments>: Sized {
| ^^^^^^^^^ required by this bound in `Options::parse`
...
| fn parse<I>(mut self, args: I) -> Result<(Self, Vec<OsString>), Error>
| ----- required by a bound in this associated function
Loading
Loading