mirror of
https://git.proxmox.com/git/proxmox
synced 2025-07-09 13:57:39 +00:00
cli: fix options with arguments, add tests
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
a5af6eedf7
commit
85a29246d5
@ -180,20 +180,20 @@ impl<Body: 'static> Method<Body> {
|
|||||||
loop {
|
loop {
|
||||||
match next_arg(&mut args) {
|
match next_arg(&mut args) {
|
||||||
Some(Arg::Opt(arg)) => {
|
Some(Arg::Opt(arg)) => {
|
||||||
if let Some(arg) = current_option {
|
if let Some(arg) = current_option.take() {
|
||||||
self.add_parameter(&mut params, arg, None)?;
|
self.add_parameter(&mut params, arg, None)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
current_option = Some(arg);
|
current_option = Some(arg);
|
||||||
}
|
}
|
||||||
Some(Arg::OptArg(arg, value)) => {
|
Some(Arg::OptArg(arg, value)) => {
|
||||||
if let Some(arg) = current_option {
|
if let Some(arg) = current_option.take() {
|
||||||
self.add_parameter(&mut params, arg, None)?;
|
self.add_parameter(&mut params, arg, None)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.add_parameter(&mut params, arg, Some(value))?;
|
self.add_parameter(&mut params, arg, Some(value))?;
|
||||||
}
|
}
|
||||||
Some(Arg::Positional(value)) => match current_option {
|
Some(Arg::Positional(value)) => match current_option.take() {
|
||||||
Some(arg) => self.add_parameter(&mut params, arg, Some(value))?,
|
Some(arg) => self.add_parameter(&mut params, arg, Some(value))?,
|
||||||
None => match positionals.next() {
|
None => match positionals.next() {
|
||||||
Some(arg) => self.add_parameter(&mut params, arg, Some(value))?,
|
Some(arg) => self.add_parameter(&mut params, arg, Some(value))?,
|
||||||
@ -201,7 +201,7 @@ impl<Body: 'static> Method<Body> {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
if let Some(arg) = current_option {
|
if let Some(arg) = current_option.take() {
|
||||||
self.add_parameter(&mut params, arg, None)?;
|
self.add_parameter(&mut params, arg, None)?;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -17,28 +17,71 @@ fn simple() {
|
|||||||
cli::Command::method(simple_method, &["foo", "bar"]),
|
cli::Command::method(simple_method, &["foo", "bar"]),
|
||||||
);
|
);
|
||||||
|
|
||||||
let result = cli
|
check_cli(&cli, &["new", "--foo=FOO", "--bar=BAR"], Ok("FOO:BAR"));
|
||||||
.run(&["new", "--foo=FOO", "--bar=BAR"])
|
check_cli(&cli, &["new", "--foo", "FOO", "--bar=BAR"], Ok("FOO:BAR"));
|
||||||
.expect("command should execute successfully");
|
check_cli(&cli, &["new", "--foo", "FOO", "--bar", "BAR"], Ok("FOO:BAR"));
|
||||||
let body =
|
check_cli(&cli, &["new", "--foo=FOO"], Err("missing parameter: 'bar'"));
|
||||||
std::str::from_utf8(result.body().as_ref()).expect("expected a valid utf8 repsonse body");
|
check_cli(&cli, &["new", "--bar=BAR"], Err("missing parameter: 'foo'"));
|
||||||
assert_eq!(body, "FOO:BAR");
|
check_cli(&cli, &["new"], Err("missing parameter: 'foo'"));
|
||||||
|
|
||||||
|
check_cli(&cli, &["newfoo", "POSFOO"], Err("missing parameter: 'bar'"));
|
||||||
|
check_cli(&cli, &["newfoo", "POSFOO", "--bar=BAR"], Ok("POSFOO:BAR"));
|
||||||
|
check_cli(&cli, &["newfoo", "--bar=BAR", "POSFOO"], Ok("POSFOO:BAR"));
|
||||||
|
check_cli(&cli, &["newfoo", "--bar=BAR"], Err("missing positional parameters: foo"));
|
||||||
|
|
||||||
|
check_cli(&cli, &["newbar", "POSBAR"], Err("missing parameter: 'foo'"));
|
||||||
|
check_cli(&cli, &["newbar", "POSBAR", "--foo=ABC"], Ok("ABC:POSBAR"));
|
||||||
|
check_cli(&cli, &["newbar", "--foo=ABC", "POSBAR"], Ok("ABC:POSBAR"));
|
||||||
|
check_cli(&cli, &["newbar", "--foo=ABC"], Err("missing positional parameters: bar"));
|
||||||
|
|
||||||
|
check_cli(&cli, &["newfoo", "FOO1", "--foo=FOO2", "--bar=BAR", "--baz=OMG"], Ok("FOO2:BAR:OMG"));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_cli(cli: &cli::App<Bytes>, args: &[&str], expect: Result<&str, &str>) {
|
||||||
|
match (cli.run(args), expect) {
|
||||||
|
(Ok(result), Ok(expect)) => {
|
||||||
|
let body = std::str::from_utf8(result.body().as_ref())
|
||||||
|
.expect("expected a valid utf8 repsonse body");
|
||||||
|
assert_eq!(body, expect, "expected successful CLI invocation");
|
||||||
|
}
|
||||||
|
(Err(result), Err(expected)) => {
|
||||||
|
let result = result.to_string();
|
||||||
|
assert_eq!(result, expected, "expected specific error message");
|
||||||
|
}
|
||||||
|
(Ok(result), Err(err)) => {
|
||||||
|
match std::str::from_utf8(result.body().as_ref()) {
|
||||||
|
Ok(value) => panic!("expected error '{}', got success with value '{}'", err, value),
|
||||||
|
Err(_) => panic!("expected error '{}', got success with non-utf8 string", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Err(err), Ok(expected)) => {
|
||||||
|
let err = err.to_string();
|
||||||
|
panic!("expected success with value '{}', got error '{}'", expected, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod methods {
|
mod methods {
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
use failure::{format_err, Error};
|
||||||
use http::Response;
|
use http::Response;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use proxmox_api::{get_type_info, ApiFuture, ApiMethod, ApiOutput, ApiType, Parameter};
|
use proxmox_api::{get_type_info, ApiFuture, ApiMethod, ApiOutput, ApiType, Parameter};
|
||||||
|
|
||||||
|
fn required_str<'a>(value: &'a Value, name: &'static str) -> Result<&'a str, Error> {
|
||||||
|
value[name].as_str().ok_or_else(|| format_err!("missing parameter: '{}'", name))
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn simple_method(value: Value) -> ApiOutput<Bytes> {
|
pub async fn simple_method(value: Value) -> ApiOutput<Bytes> {
|
||||||
let foo = value["foo"].as_str().unwrap();
|
let foo = required_str(&value, "foo")?;
|
||||||
|
let bar = required_str(&value, "bar")?;
|
||||||
|
|
||||||
let bar = value["bar"].as_str().unwrap();
|
let baz = value
|
||||||
|
.get("baz")
|
||||||
let baz = value.get("baz").map(|value| value.as_str().unwrap());
|
.map(|value| value.as_str().ok_or_else(|| format_err!("'baz' must be a string")))
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
let output = match baz {
|
let output = match baz {
|
||||||
Some(baz) => format!("{}:{}:{}", foo, bar, baz),
|
Some(baz) => format!("{}:{}:{}", foo, bar, baz),
|
||||||
|
Loading…
Reference in New Issue
Block a user