Organize the public CLI with clap
This commit is contained in:
parent
e7dd95aea6
commit
d08d931b5f
1 changed files with 445 additions and 255 deletions
|
|
@ -2,11 +2,11 @@ use std::collections::VecDeque;
|
|||
use std::convert::Infallible;
|
||||
use std::ffi::OsString;
|
||||
use std::io::Write;
|
||||
use std::os::unix::ffi::OsStringExt;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use lazaret_client::{
|
||||
BootstrapAcquisition, ClientBackend, ClientCommand, ClientError, DomainStatus,
|
||||
parse_command_line, run,
|
||||
BootstrapAcquisition, ClientBackend, ClientCommand, ClientError, DomainStatus, run,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
|
|
@ -234,8 +234,9 @@ fn unsupported_host_and_configuration_errors_keep_their_cause() {
|
|||
|
||||
#[test]
|
||||
fn command_line_requires_an_explicit_profile_and_preserves_command_bytes() {
|
||||
let parsed = parse_command_line(
|
||||
let parsed = lazaret_client::cli::parse(
|
||||
[
|
||||
"run",
|
||||
"--profile",
|
||||
"agent",
|
||||
"--workspace",
|
||||
|
|
@ -250,6 +251,9 @@ fn command_line_requires_an_explicit_profile_and_preserves_command_bytes() {
|
|||
PathBuf::from("/current"),
|
||||
)
|
||||
.unwrap();
|
||||
let lazaret_client::cli::Command::Run(parsed) = parsed else {
|
||||
panic!("expected run command");
|
||||
};
|
||||
assert_eq!(parsed.profile, "agent");
|
||||
assert_eq!(parsed.workspace, PathBuf::from("/project"));
|
||||
assert_eq!(
|
||||
|
|
@ -259,8 +263,8 @@ fn command_line_requires_an_explicit_profile_and_preserves_command_bytes() {
|
|||
assert_eq!(parsed.argv, [b"tool".to_vec(), b"argument".to_vec()]);
|
||||
|
||||
assert!(
|
||||
parse_command_line(
|
||||
["--", "tool"].map(OsString::from),
|
||||
lazaret_client::cli::parse(
|
||||
["run", "--", "tool"].map(OsString::from),
|
||||
PathBuf::from("/current")
|
||||
)
|
||||
.unwrap_err()
|
||||
|
|
@ -268,3 +272,102 @@ fn command_line_requires_an_explicit_profile_and_preserves_command_bytes() {
|
|||
.contains("profile")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn command_line_preserves_non_utf8_paths_and_command_arguments() {
|
||||
let workspace = OsString::from_vec(b"/project-\xff".to_vec());
|
||||
let argument = OsString::from_vec(b"argument-\xfe".to_vec());
|
||||
let parsed = lazaret_client::cli::parse(
|
||||
[
|
||||
OsString::from("run"),
|
||||
OsString::from("--profile"),
|
||||
OsString::from("agent"),
|
||||
OsString::from("--workspace"),
|
||||
workspace.clone(),
|
||||
OsString::from("--"),
|
||||
OsString::from("tool"),
|
||||
argument,
|
||||
],
|
||||
PathBuf::from("/current"),
|
||||
)
|
||||
.unwrap();
|
||||
let lazaret_client::cli::Command::Run(parsed) = parsed else {
|
||||
panic!("expected run command");
|
||||
};
|
||||
assert_eq!(parsed.workspace, PathBuf::from(workspace));
|
||||
assert_eq!(parsed.argv, [b"tool".to_vec(), b"argument-\xfe".to_vec()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn public_help_explains_commands_and_options() {
|
||||
for (arguments, expected) in [
|
||||
(
|
||||
&["--help"][..],
|
||||
&[
|
||||
"Run development tools in an isolated gVisor sandbox",
|
||||
"run",
|
||||
"state",
|
||||
][..],
|
||||
),
|
||||
(
|
||||
&["run", "--help"],
|
||||
&[
|
||||
"Agent profile to use",
|
||||
"Project directory to share",
|
||||
"Command and arguments to run",
|
||||
],
|
||||
),
|
||||
(
|
||||
&["state", "--help"],
|
||||
&["list", "inspect", "verify", "reset"],
|
||||
),
|
||||
(
|
||||
&["state", "reset", "--help"],
|
||||
&[
|
||||
"Reset every configured persistent sandbox path",
|
||||
"Reset one exact configured container path",
|
||||
"interactive confirmation",
|
||||
],
|
||||
),
|
||||
] {
|
||||
let error = lazaret_client::cli::parse(
|
||||
arguments.iter().map(OsString::from),
|
||||
PathBuf::from("/current"),
|
||||
)
|
||||
.unwrap_err();
|
||||
assert_eq!(error.kind(), clap::error::ErrorKind::DisplayHelp);
|
||||
let help = error.to_string();
|
||||
for text in expected {
|
||||
assert!(
|
||||
help.contains(text),
|
||||
"{arguments:?} did not explain {text:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clap_rejects_missing_profile_command_and_ambiguous_reset_scope() {
|
||||
let workspace = PathBuf::from("/current");
|
||||
for arguments in [
|
||||
vec!["run", "--", "tool"],
|
||||
vec!["run", "--profile", "agent"],
|
||||
vec!["state", "reset", "--profile", "agent"],
|
||||
vec![
|
||||
"state",
|
||||
"reset",
|
||||
"--profile",
|
||||
"agent",
|
||||
"--all",
|
||||
"--path",
|
||||
"/usr",
|
||||
],
|
||||
] {
|
||||
let error = lazaret_client::cli::parse(
|
||||
arguments.into_iter().map(OsString::from),
|
||||
workspace.clone(),
|
||||
)
|
||||
.unwrap_err();
|
||||
assert_eq!(error.exit_code(), 2);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue