refactor and test the multi-call code

main
_ 2021-10-02 18:47:10 +00:00
parent f44613540e
commit 4329562aa3
1 changed files with 100 additions and 19 deletions

View File

@ -1,7 +1,9 @@
use std::{
ffi::OsString,
iter::FromIterator,
};
#[derive (Debug, PartialEq)]
enum Subcommand {
PtthServer,
PtthQuicEndServer,
@ -22,30 +24,109 @@ fn parse_subcommand (name: &str) -> Option <Subcommand>
}
}
fn parse_args (args: &[OsString]) -> anyhow::Result <(Subcommand, &[OsString])>
{
let arg_0 = match args.get (0) {
Some (x) => x,
None => anyhow::bail! ("arg 0 must be the exe name"),
};
let arg_0 = arg_0.to_str ().ok_or_else (|| anyhow::anyhow! ("arg 0 should be valid UTF-8"))?;
match parse_subcommand (arg_0) {
Some (x) => return Ok ((x, args)),
None => (),
}
let arg_1 = match args.get (1) {
Some (x) => x,
None => anyhow::bail! ("arg 1 must be the subcommand if arg 0 is not"),
};
let arg_1 = arg_1.to_str ().ok_or_else (|| anyhow::anyhow! ("arg 1 subcommand should be valid UTF-8"))?;
match parse_subcommand (arg_1) {
Some (x) => return Ok ((x, &args [1..])),
None => (),
}
anyhow::bail! ("Subcommand must be either arg 0 (exe name) or arg 1")
}
#[tokio::main]
async fn main () -> anyhow::Result <()> {
tracing_subscriber::fmt::init ();
let args = Vec::from_iter (std::env::args_os ());
let arg_0 = args [0].to_str ().expect ("exe name should be valid UTF-8");
match parse_subcommand (arg_0) {
Some (Subcommand::PtthServer) => return ptth_server::executable::main (&args).await,
Some (Subcommand::PtthQuicEndServer) => return quic_demo::executable_end_server::main (&args).await,
_ => (),
let (subcommand, args) = parse_args (&args)?;
match subcommand {
Subcommand::PtthServer => ptth_server::executable::main (&args).await,
Subcommand::PtthQuicEndServer => quic_demo::executable_end_server::main (&args).await,
}
}
#[cfg (test)]
mod tests {
use super::*;
#[test]
fn multi_call () -> anyhow::Result <()> {
let negative_cases = vec! [
vec! [],
vec! ["invalid_exe_name"],
vec! ["ptth_multi_call_server"],
vec! ["ptth_multi_call_server", "invalid_subcommand"],
];
for input in &negative_cases {
let input: Vec <_> = input.iter ().map (OsString::from).collect ();
let actual = parse_args (&input);
assert! (actual.is_err ());
}
let positive_cases = vec! [
(vec! ["ptth_server"], (Subcommand::PtthServer, vec! ["ptth_server"])),
(vec! ["ptth_server", "--help"], (Subcommand::PtthServer, vec! ["ptth_server", "--help"])),
(vec! ["ptth_quic_end_server", "--help"], (Subcommand::PtthQuicEndServer, vec! ["ptth_quic_end_server", "--help"])),
(vec! ["ptth_multi_call_server", "ptth_server"], (Subcommand::PtthServer, vec! ["ptth_server"])),
(
vec! [
"ptth_multi_call_server",
"ptth_server",
"--help"
],
(
Subcommand::PtthServer,
vec! [
"ptth_server",
"--help"
]
)
),
(
vec! [
"invalid_exe_name",
"ptth_server",
"--help"
],
(
Subcommand::PtthServer,
vec! [
"ptth_server",
"--help"
]
)
),
];
for (input, (expected_subcommand, expected_args)) in &positive_cases {
let input: Vec <_> = input.iter ().map (OsString::from).collect ();
let (actual_subcommand, actual_args) = parse_args (&input)?;
assert_eq! (expected_subcommand, &actual_subcommand);
assert_eq! (expected_args, actual_args);
}
Ok (())
}
let arg_1 = match args.get (1) {
Some (x) => x,
None => anyhow::bail! ("Subcommand must be the first argument if it's not the exe name"),
};
let arg_1 = arg_1.to_str ().expect ("subcommand should be valid UTF-8");
match parse_subcommand (arg_1) {
Some (Subcommand::PtthServer) => return ptth_server::executable::main (&args [1..]).await,
Some (Subcommand::PtthQuicEndServer) => return quic_demo::executable_end_server::main (&args [1..]).await,
_ => (),
}
anyhow::bail! ("Subcommand should be provided in exe name or first argument, e.g. `./ptth_multi_call_server ptth_server`");
}