diff --git a/Cargo.toml b/Cargo.toml index 6adaff6..89aedf9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 = [] diff --git a/examples/test_compile_errors_manually.rs b/examples/test_compile_errors_manually.rs deleted file mode 100644 index 7d08f10..0000000 --- a/examples/test_compile_errors_manually.rs +++ /dev/null @@ -1,84 +0,0 @@ -use uutils_args::{Arguments, Options, Value}; - -// Using a fully-fledged compile-error testsuite is a bit overkill, but we still -// want to make sure that the `derive` crate generates reasonable error messages. -// That's what this "example" is for. In the following, there are blocks of -// lines, one marked as POSITIVE and multiple lines marked as NEGATIVE. The -// committed version of this file should only contain POSITIVE. In order to run a -// test, comment out the POSITIVE line, and use a NEGATIVE line instead, and -// manually check whether you see a reasonable error message – ideally the error -// message indicated by the comment. One way to do this is: - -// $ cargo build --example test_compile_errors_manually - -#[derive(Value, Debug, Default)] -enum Flavor { - #[default] - #[value("kind", "nice")] - Kind, - #[value("condescending")] // POSITIVE - // #[value(condescending)] // NEGATIVE: "expected comma-separated list of string literals" - Condescending, -} - -#[derive(Arguments)] -#[arguments(file = "examples/hello_world_help.md")] // POSITIVE -// #[arguments(file = "examples/nonexistent.md")] // NEGATIVE: "cannot open help-string file" -// #[arguments(file = "/dev/full")] // NEGATIVE: Causes OOM, FIXME -// #[arguments(file = "/")] // NEGATIVE: "cannot read from help-string file" -// #[arguments(file = "path/to/some/WRITE-ONLY/file")] // NEGATIVE: "cannot open help-string file" -enum Arg { - /// The name to greet - #[arg("-n NAME", "--name[=NAME]", "name=NAME")] // POSITIVE - // #[arg("-")] // NEGATIVE: flag name must be non-empty (cannot be just '-') - // #[arg("-n NAME", "--name[NAME]", "name=NAME")] // NEGATIVE: "expected '=' after '[' in flag pattern" - // #[arg("-n NAME", "--name[=NAME", "name=NAME")] // NEGATIVE: "expected final ']' in flag pattern" - // #[arg(key="name")] // NEGATIVE: "can't parse arg attributes, expected one or more strings" - Name(String), - - /// The number of times to greet - #[arg("-c N", "--count=N")] - Count(u8), - - #[arg("--flavor=FLAVOR")] - Flavor(Flavor), -} - -struct Settings { - name: String, - count: u8, - flavor: Flavor, -} - -impl Options for Settings { - fn apply(&mut self, arg: Arg) -> Result<(), uutils_args::Error> { - match arg { - Arg::Name(n) => self.name = n, - Arg::Count(c) => self.count = c, - Arg::Flavor(flavor) => self.flavor = flavor, - } - Ok(()) - } -} - -fn main() -> Result<(), uutils_args::Error> { - let (settings, _operands) = Settings { - name: String::new(), - count: 1, - flavor: Flavor::Kind, - } - .parse(std::env::args_os()) - .unwrap(); - - for _ in 0..settings.count { - match settings.flavor { - Flavor::Kind => { - println!("Hello, {}!", settings.name); - } - Flavor::Condescending => { - println!("Ugh, {}.", settings.name); - } - } - } - Ok(()) -} diff --git a/tests/derive.rs b/tests/derive.rs new file mode 100644 index 0000000..f3083d3 --- /dev/null +++ b/tests/derive.rs @@ -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"); +} diff --git a/tests/derive/arg_bare_keyword.rs b/tests/derive/arg_bare_keyword.rs new file mode 100644 index 0000000..96b2ef8 --- /dev/null +++ b/tests/derive/arg_bare_keyword.rs @@ -0,0 +1,19 @@ +use uutils_args::{Arguments, Options}; + +#[derive(Arguments)] +enum Arg { + #[arg(banana)] // Oops! + Something, +} + +struct Settings {} + +impl Options for Settings { + fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> { + Ok(()) + } +} + +fn main() { + Settings {}.parse(std::env::args_os()).unwrap(); +} diff --git a/tests/derive/arg_bare_keyword.stderr b/tests/derive/arg_bare_keyword.stderr new file mode 100644 index 0000000..10a091c --- /dev/null +++ b/tests/derive/arg_bare_keyword.stderr @@ -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) diff --git a/tests/derive/arg_duplicate_other.rs b/tests/derive/arg_duplicate_other.rs new file mode 100644 index 0000000..f36607f --- /dev/null +++ b/tests/derive/arg_duplicate_other.rs @@ -0,0 +1,21 @@ +use uutils_args::{Arguments, Options}; + +#[derive(Arguments)] +enum Arg { + #[arg("--foo")] + Something, + #[arg("--foo")] // Oops! + Banana, +} + +struct Settings {} + +impl Options for Settings { + fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> { + Ok(()) + } +} + +fn main() { + Settings {}.parse(std::env::args_os()).unwrap(); +} diff --git a/tests/derive/arg_duplicate_within.rs b/tests/derive/arg_duplicate_within.rs new file mode 100644 index 0000000..dd1ef30 --- /dev/null +++ b/tests/derive/arg_duplicate_within.rs @@ -0,0 +1,19 @@ +use uutils_args::{Arguments, Options}; + +#[derive(Arguments)] +enum Arg { + #[arg("--foo", "--foo")] // Oops! + Something, +} + +struct Settings {} + +impl Options for Settings { + fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> { + Ok(()) + } +} + +fn main() { + Settings {}.parse(std::env::args_os()).unwrap(); +} diff --git a/tests/derive/arg_just_minus.rs b/tests/derive/arg_just_minus.rs new file mode 100644 index 0000000..b2d0e45 --- /dev/null +++ b/tests/derive/arg_just_minus.rs @@ -0,0 +1,19 @@ +use uutils_args::{Arguments, Options}; + +#[derive(Arguments)] +enum Arg { + #[arg("-")] // Oops! + Something, +} + +struct Settings {} + +impl Options for Settings { + fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> { + Ok(()) + } +} + +fn main() { + Settings {}.parse(std::env::args_os()).unwrap(); +} diff --git a/tests/derive/arg_just_minus.stderr b/tests/derive/arg_just_minus.stderr new file mode 100644 index 0000000..7955bfa --- /dev/null +++ b/tests/derive/arg_just_minus.stderr @@ -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 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: 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: Sized { + | ^^^^^^^^^ required by this bound in `Options::parse` +... + | fn parse(mut self, args: I) -> Result<(Self, Vec), Error> + | ----- required by a bound in this associated function diff --git a/tests/derive/arg_key_value.rs b/tests/derive/arg_key_value.rs new file mode 100644 index 0000000..a525a59 --- /dev/null +++ b/tests/derive/arg_key_value.rs @@ -0,0 +1,19 @@ +use uutils_args::{Arguments, Options}; + +#[derive(Arguments)] +enum Arg { + #[arg(key = "name")] // Oops! + Something, +} + +struct Settings {} + +impl Options for Settings { + fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> { + Ok(()) + } +} + +fn main() { + Settings {}.parse(std::env::args_os()).unwrap(); +} diff --git a/tests/derive/arg_key_value.stderr b/tests/derive/arg_key_value.stderr new file mode 100644 index 0000000..3a67462 --- /dev/null +++ b/tests/derive/arg_key_value.stderr @@ -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 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: 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: Sized { + | ^^^^^^^^^ required by this bound in `Options::parse` +... + | fn parse(mut self, args: I) -> Result<(Self, Vec), Error> + | ----- required by a bound in this associated function diff --git a/tests/derive/arg_missing_closing_bracket.rs b/tests/derive/arg_missing_closing_bracket.rs new file mode 100644 index 0000000..3edfba1 --- /dev/null +++ b/tests/derive/arg_missing_closing_bracket.rs @@ -0,0 +1,19 @@ +use uutils_args::{Arguments, Options}; + +#[derive(Arguments)] +enum Arg { + #[arg("--foo[=FOO")] // Oops! + Something(String), +} + +struct Settings {} + +impl Options for Settings { + fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> { + Ok(()) + } +} + +fn main() { + Settings {}.parse(std::env::args_os()).unwrap(); +} diff --git a/tests/derive/arg_missing_closing_bracket.stderr b/tests/derive/arg_missing_closing_bracket.stderr new file mode 100644 index 0000000..4aec1fd --- /dev/null +++ b/tests/derive/arg_missing_closing_bracket.stderr @@ -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 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: 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: Sized { + | ^^^^^^^^^ required by this bound in `Options::parse` +... + | fn parse(mut self, args: I) -> Result<(Self, Vec), Error> + | ----- required by a bound in this associated function diff --git a/tests/derive/arg_missing_equals.rs b/tests/derive/arg_missing_equals.rs new file mode 100644 index 0000000..f988a1a --- /dev/null +++ b/tests/derive/arg_missing_equals.rs @@ -0,0 +1,19 @@ +use uutils_args::{Arguments, Options}; + +#[derive(Arguments)] +enum Arg { + #[arg("--foo[FOO]")] // Oops! + Something(String), +} + +struct Settings {} + +impl Options for Settings { + fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> { + Ok(()) + } +} + +fn main() { + Settings {}.parse(std::env::args_os()).unwrap(); +} diff --git a/tests/derive/arg_missing_equals.stderr b/tests/derive/arg_missing_equals.stderr new file mode 100644 index 0000000..e00b141 --- /dev/null +++ b/tests/derive/arg_missing_equals.stderr @@ -0,0 +1,34 @@ +error: proc-macro derive panicked + --> tests/derive/arg_missing_equals.rs:3:10 + | +3 | #[derive(Arguments)] + | ^^^^^^^^^ + | + = help: message: expected '=' after '[' in flag pattern + +error[E0277]: the trait bound `Arg: uutils_args::Arguments` is not satisfied + --> tests/derive/arg_missing_equals.rs:11:6 + | +11 | impl Options 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: Sized { + | ^^^^^^^^^ required by this bound in `Options` + +error[E0277]: the trait bound `Arg: uutils_args::Arguments` is not satisfied + --> tests/derive/arg_missing_equals.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: Sized { + | ^^^^^^^^^ required by this bound in `Options::parse` +... + | fn parse(mut self, args: I) -> Result<(Self, Vec), Error> + | ----- required by a bound in this associated function diff --git a/tests/derive/arg_missing_field.rs b/tests/derive/arg_missing_field.rs new file mode 100644 index 0000000..88418ed --- /dev/null +++ b/tests/derive/arg_missing_field.rs @@ -0,0 +1,19 @@ +use uutils_args::{Arguments, Options}; + +#[derive(Arguments)] +enum Arg { + #[arg("--foo[=FOO]")] + Something, // Oops! +} + +struct Settings {} + +impl Options for Settings { + fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> { + Ok(()) + } +} + +fn main() { + Settings {}.parse(std::env::args_os()).unwrap(); +} diff --git a/tests/derive/arg_missing_field.stderr b/tests/derive/arg_missing_field.stderr new file mode 100644 index 0000000..eff1a85 --- /dev/null +++ b/tests/derive/arg_missing_field.stderr @@ -0,0 +1,34 @@ +error: proc-macro derive panicked + --> tests/derive/arg_missing_field.rs:3:10 + | +3 | #[derive(Arguments)] + | ^^^^^^^^^ + | + = help: message: Option cannot take a value if the variant doesn't have a field + +error[E0277]: the trait bound `Arg: uutils_args::Arguments` is not satisfied + --> tests/derive/arg_missing_field.rs:11:6 + | +11 | impl Options 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: Sized { + | ^^^^^^^^^ required by this bound in `Options` + +error[E0277]: the trait bound `Arg: uutils_args::Arguments` is not satisfied + --> tests/derive/arg_missing_field.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: Sized { + | ^^^^^^^^^ required by this bound in `Options::parse` +... + | fn parse(mut self, args: I) -> Result<(Self, Vec), Error> + | ----- required by a bound in this associated function diff --git a/tests/derive/arg_missing_metavar.rs b/tests/derive/arg_missing_metavar.rs new file mode 100644 index 0000000..cd68af7 --- /dev/null +++ b/tests/derive/arg_missing_metavar.rs @@ -0,0 +1,23 @@ +use uutils_args::{Arguments, Options}; + +struct Complicated { + // Doesn't "impl Default". Oops! +} + +#[derive(Arguments)] +enum Arg { + #[arg("--foo")] + Something(Complicated), +} + +struct Settings {} + +impl Options for Settings { + fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> { + Ok(()) + } +} + +fn main() { + Settings {}.parse(std::env::args_os()).unwrap(); +} diff --git a/tests/derive/arg_missing_metavar.stderr b/tests/derive/arg_missing_metavar.stderr new file mode 100644 index 0000000..993ce06 --- /dev/null +++ b/tests/derive/arg_missing_metavar.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `Complicated: Default` is not satisfied + --> tests/derive/arg_missing_metavar.rs:7:10 + | +7 | #[derive(Arguments)] + | ^^^^^^^^^ the trait `Default` is not implemented for `Complicated` + | + = note: this error originates in the derive macro `Arguments` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Complicated` with `#[derive(Default)]` + | +3 + #[derive(Default)] +4 | struct Complicated { + | diff --git a/tests/derive/arguments_file_isdir.rs b/tests/derive/arguments_file_isdir.rs new file mode 100644 index 0000000..8df1342 --- /dev/null +++ b/tests/derive/arguments_file_isdir.rs @@ -0,0 +1,17 @@ +use uutils_args::{Arguments, Options}; + +#[derive(Arguments)] +#[arguments(file = "/")] // Oops! +enum Arg {} + +struct Settings {} + +impl Options for Settings { + fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> { + Ok(()) + } +} + +fn main() { + Settings {}.parse(std::env::args_os()).unwrap(); +} diff --git a/tests/derive/arguments_file_isdir.stderr b/tests/derive/arguments_file_isdir.stderr new file mode 100644 index 0000000..944a429 --- /dev/null +++ b/tests/derive/arguments_file_isdir.stderr @@ -0,0 +1,34 @@ +error: proc-macro derive panicked + --> tests/derive/arguments_file_isdir.rs:3:10 + | +3 | #[derive(Arguments)] + | ^^^^^^^^^ + | + = help: message: cannot read from help-string file: Os { code: 21, kind: IsADirectory, message: "Is a directory" } + +error[E0277]: the trait bound `Arg: uutils_args::Arguments` is not satisfied + --> tests/derive/arguments_file_isdir.rs:9:6 + | +9 | impl Options 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: Sized { + | ^^^^^^^^^ required by this bound in `Options` + +error[E0277]: the trait bound `Arg: uutils_args::Arguments` is not satisfied + --> tests/derive/arguments_file_isdir.rs:16:17 + | +16 | 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: Sized { + | ^^^^^^^^^ required by this bound in `Options::parse` +... + | fn parse(mut self, args: I) -> Result<(Self, Vec), Error> + | ----- required by a bound in this associated function diff --git a/tests/derive/arguments_file_nonexistent.rs b/tests/derive/arguments_file_nonexistent.rs new file mode 100644 index 0000000..bdabf54 --- /dev/null +++ b/tests/derive/arguments_file_nonexistent.rs @@ -0,0 +1,17 @@ +use uutils_args::{Arguments, Options}; + +#[derive(Arguments)] +#[arguments(file = "nonexistent")] // Oops! +enum Arg {} + +struct Settings {} + +impl Options for Settings { + fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> { + Ok(()) + } +} + +fn main() { + Settings {}.parse(std::env::args_os()).unwrap(); +} diff --git a/tests/derive/arguments_file_nonexistent.stderr b/tests/derive/arguments_file_nonexistent.stderr new file mode 100644 index 0000000..8ea6b22 --- /dev/null +++ b/tests/derive/arguments_file_nonexistent.stderr @@ -0,0 +1,34 @@ +error: proc-macro derive panicked + --> tests/derive/arguments_file_nonexistent.rs:3:10 + | +3 | #[derive(Arguments)] + | ^^^^^^^^^ + | + = help: message: cannot open help-string file: Os { code: 2, kind: NotFound, message: "No such file or directory" } + +error[E0277]: the trait bound `Arg: uutils_args::Arguments` is not satisfied + --> tests/derive/arguments_file_nonexistent.rs:9:6 + | +9 | impl Options 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: Sized { + | ^^^^^^^^^ required by this bound in `Options` + +error[E0277]: the trait bound `Arg: uutils_args::Arguments` is not satisfied + --> tests/derive/arguments_file_nonexistent.rs:16:17 + | +16 | 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: Sized { + | ^^^^^^^^^ required by this bound in `Options::parse` +... + | fn parse(mut self, args: I) -> Result<(Self, Vec), Error> + | ----- required by a bound in this associated function diff --git a/tests/derive/arguments_file_writeonly.rs b/tests/derive/arguments_file_writeonly.rs new file mode 100644 index 0000000..f598635 --- /dev/null +++ b/tests/derive/arguments_file_writeonly.rs @@ -0,0 +1,17 @@ +use uutils_args::{Arguments, Options}; + +#[derive(Arguments)] +#[arguments(file = "/proc/self/clear_refs")] // Oops! +enum Arg {} + +struct Settings {} + +impl Options for Settings { + fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> { + Ok(()) + } +} + +fn main() { + Settings {}.parse(std::env::args_os()).unwrap(); +} diff --git a/tests/derive/arguments_file_writeonly.stderr b/tests/derive/arguments_file_writeonly.stderr new file mode 100644 index 0000000..403bd7c --- /dev/null +++ b/tests/derive/arguments_file_writeonly.stderr @@ -0,0 +1,34 @@ +error: proc-macro derive panicked + --> tests/derive/arguments_file_writeonly.rs:3:10 + | +3 | #[derive(Arguments)] + | ^^^^^^^^^ + | + = help: message: cannot open help-string file: Os { code: 13, kind: PermissionDenied, message: "Permission denied" } + +error[E0277]: the trait bound `Arg: uutils_args::Arguments` is not satisfied + --> tests/derive/arguments_file_writeonly.rs:9:6 + | +9 | impl Options 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: Sized { + | ^^^^^^^^^ required by this bound in `Options` + +error[E0277]: the trait bound `Arg: uutils_args::Arguments` is not satisfied + --> tests/derive/arguments_file_writeonly.rs:16:17 + | +16 | 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: Sized { + | ^^^^^^^^^ required by this bound in `Options::parse` +... + | fn parse(mut self, args: I) -> Result<(Self, Vec), Error> + | ----- required by a bound in this associated function diff --git a/tests/derive/value_bare_keyword.rs b/tests/derive/value_bare_keyword.rs new file mode 100644 index 0000000..7214066 --- /dev/null +++ b/tests/derive/value_bare_keyword.rs @@ -0,0 +1,26 @@ +use uutils_args::{Arguments, Options, Value}; + +#[derive(Value, Default)] +enum Flavor { + #[default] + #[value(banana)] // Oops! + Banana, +} + +#[derive(Arguments)] +enum Arg { + #[arg("--flavor=FLAVOR")] + Flavor(Flavor), +} + +struct Settings {} + +impl Options for Settings { + fn apply(&mut self, _arg: Arg) -> Result<(), uutils_args::Error> { + Ok(()) + } +} + +fn main() { + Settings {}.parse(std::env::args_os()).unwrap(); +} diff --git a/tests/derive/value_bare_keyword.stderr b/tests/derive/value_bare_keyword.stderr new file mode 100644 index 0000000..1fdb7e8 --- /dev/null +++ b/tests/derive/value_bare_keyword.stderr @@ -0,0 +1,30 @@ +error: proc-macro derive panicked + --> tests/derive/value_bare_keyword.rs:3:10 + | +3 | #[derive(Value, Default)] + | ^^^^^ + | + = help: message: expected comma-separated list of string literals: Error("unexpected end of input, unrecognized keyword in value attribute") + +error[E0277]: the trait bound `Flavor: uutils_args::Value` is not satisfied + --> tests/derive/value_bare_keyword.rs:10:10 + | +10 | #[derive(Arguments)] + | ^^^^^^^^^ the trait `uutils_args::Value` is not implemented for `Flavor` + | + = help: the following other types implement trait `uutils_args::Value`: + Option + OsString + PathBuf + String + i128 + i16 + i32 + i64 + and $N others +note: required by a bound in `parse_value_for_option` + --> src/internal.rs + | + | pub fn parse_value_for_option(opt: &str, v: &OsStr) -> Result { + | ^^^^^ required by this bound in `parse_value_for_option` + = note: this error originates in the derive macro `Arguments` (in Nightly builds, run with -Z macro-backtrace for more info)