use std::io;
use std::path::PathBuf;
use std::process::Child;
use perforce_cli::P4Cli;
use perforce_cli::cmd::SubCommand;
use perforce_cli::cmd::clients::Clients;
use perforce_cli::global::GlobalOpts;
use perforce_cli::spawn::ParameterizedSpawn;
fn args_of(command: &std::process::Command) -> Vec<String> {
command
.get_args()
.map(|arg| arg.to_string_lossy().into_owned())
.collect()
}
fn expect_args(cmd: &impl SubCommand, expected: &[&str]) {
assert_eq!(args_of(&cmd.setup_command("p4")), expected);
}
macro_rules! expect_chain {
([$($e:literal),* $(,)?], $($chain:tt)*) => {{
let cmd = $($chain)*;
expect_args(&cmd, &[$($e),*]);
}};
}
fn echo_bin() -> PathBuf {
let path = std::env::temp_dir().join("p4cli_clients_echo_args.bat");
std::fs::write(&path, "@echo %*\r\n").expect("write echo helper");
path
}
fn parse_echo(stdout: &[u8]) -> Vec<String> {
String::from_utf8_lossy(stdout)
.split_whitespace()
.map(|s| s.trim_matches('"').to_string())
.collect()
}
fn spawned_args_unit<C>(cmd: &mut C) -> Vec<String>
where
C: ParameterizedSpawn<(), Output = Child, Error = io::Error>,
{
let output = cmd
.spawn_with(())
.expect("spawn echo helper")
.wait_with_output()
.expect("wait for echo helper");
assert!(output.status.success(), "echo helper exited unsuccessfully");
parse_echo(&output.stdout)
}
fn echo_clients() -> Clients {
Clients::new(echo_bin(), GlobalOpts::new())
}
fn form_1_bare() {
let p4 = P4Cli::default();
expect_chain!(["clients"], p4.clients());
expect_chain!(["clients"], p4.workspaces());
let mut cmd = echo_clients();
assert_eq!(spawned_args_unit(&mut cmd), ["clients"]);
}
fn form_2_single_options() {
let p4 = P4Cli::default();
expect_chain!(["clients", "-t"], p4.clients().display_time(true));
expect_chain!(["clients"], p4.clients().display_time(false));
expect_chain!(["clients", "-m", "5"], p4.clients().limit(5));
expect_chain!(
["clients", "-S", "//stream/main"],
p4.clients().stream("//stream/main")
);
expect_chain!(
["clients", "-e", "p4vBeta*"],
p4.clients().filter("p4vBeta*", false)
);
expect_chain!(
["clients", "-E", "*Us*rs"],
p4.clients().filter("*Us*rs", true)
);
expect_chain!(["clients", "-u", "O*hara"], p4.clients().user("O*hara"));
expect_chain!(["clients", "-a"], p4.clients().all());
expect_chain!(
["clients", "-s", "edge.1667"],
p4.clients().server_id("edge.1667")
);
#[cfg(not(feature = "lt2016_1"))]
expect_chain!(["clients", "--me"], p4.clients().filter_me());
#[cfg(not(feature = "lt2024_2"))]
expect_chain!(
["clients", "-u", "O*hara", "--user-case-insensitive"],
p4.clients().user("O*hara").case_insensitive()
);
let mut cmd = echo_clients().limit(5);
assert_eq!(spawned_args_unit(&mut cmd), ["clients", "-m", "5"]);
}
fn form_3_selection_orders() {
let p4 = P4Cli::default();
expect_chain!(
["clients", "-u", "O*hara", "-E", "*Us*rs"],
p4.clients().user("O*hara").filter("*Us*rs", true)
);
expect_chain!(
["clients", "-u", "O*hara", "-E", "*Us*rs"],
p4.clients().filter("*Us*rs", true).user("O*hara")
);
#[cfg(not(feature = "lt2016_1"))]
{
expect_chain!(
["clients", "--me", "-e", "p4vBeta*"],
p4.clients().filter_me().filter("p4vBeta*", false)
);
expect_chain!(
["clients", "--me", "-e", "p4vBeta*"],
p4.clients().filter("p4vBeta*", false).filter_me()
);
}
#[cfg(not(feature = "lt2024_2"))]
{
expect_chain!(
[
"clients",
"-u",
"O*hara",
"--user-case-insensitive",
"-s",
"edge.1667"
],
p4.clients()
.user("O*hara")
.case_insensitive()
.server_id("edge.1667")
);
expect_chain!(
[
"clients",
"-u",
"O*hara",
"--user-case-insensitive",
"-s",
"edge.1667"
],
p4.clients()
.user("O*hara")
.server_id("edge.1667")
.case_insensitive()
);
expect_chain!(
[
"clients",
"-u",
"O*hara",
"--user-case-insensitive",
"-s",
"edge.1667"
],
p4.clients()
.server_id("edge.1667")
.user("O*hara")
.case_insensitive()
);
}
let full = [
"clients",
"-t",
"-u",
"O*hara",
"-E",
"*Us*rs",
"-m",
"5",
"-S",
"//stream/main",
"-s",
"edge.1667",
];
expect_chain!(
[
"clients",
"-t",
"-u",
"O*hara",
"-E",
"*Us*rs",
"-m",
"5",
"-S",
"//stream/main",
"-s",
"edge.1667",
],
p4.clients()
.display_time(true)
.user("O*hara")
.filter("*Us*rs", true)
.limit(5)
.stream("//stream/main")
.server_id("edge.1667")
);
expect_chain!(
[
"clients",
"-t",
"-u",
"O*hara",
"-E",
"*Us*rs",
"-m",
"5",
"-S",
"//stream/main",
"-s",
"edge.1667",
],
p4.clients()
.server_id("edge.1667")
.stream("//stream/main")
.limit(5)
.filter("*Us*rs", true)
.user("O*hara")
.display_time(true)
);
expect_chain!(
[
"clients",
"-t",
"-u",
"O*hara",
"-E",
"*Us*rs",
"-m",
"5",
"-S",
"//stream/main",
"-s",
"edge.1667",
],
p4.clients()
.filter("*Us*rs", true)
.server_id("edge.1667")
.stream("//stream/main")
.user("O*hara")
.limit(5)
.display_time(true)
);
#[cfg(not(feature = "lt2016_1"))]
{
expect_chain!(
[
"clients",
"-t",
"--me",
"-e",
"p4vBeta*",
"-m",
"5",
"-S",
"//stream/main",
"-a",
],
p4.clients()
.all()
.filter_me()
.display_time(true)
.filter("p4vBeta*", false)
.stream("//stream/main")
.limit(5)
);
expect_chain!(
[
"clients",
"-t",
"--me",
"-e",
"p4vBeta*",
"-m",
"5",
"-S",
"//stream/main",
"-a",
],
p4.clients()
.filter("p4vBeta*", false)
.filter_me()
.all()
.limit(5)
.stream("//stream/main")
.display_time(true)
);
}
let mut cmd = p4.clients().user("O*hara");
cmd.set_limit(10)
.set_display_time(true)
.set_stream("//stream/dev");
assert_eq!(cmd.get_limit(), Some(10));
assert!(cmd.get_display_time());
assert_eq!(cmd.get_stream(), Some(&"//stream/dev".to_string()));
expect_args(
&cmd,
&[
"clients",
"-t",
"-u",
"O*hara",
"-m",
"10",
"-S",
"//stream/dev",
],
);
let mut cmd = echo_clients()
.display_time(true)
.user("O*hara")
.filter("*Us*rs", true)
.limit(5)
.stream("//stream/main")
.server_id("edge.1667");
assert_eq!(spawned_args_unit(&mut cmd), full);
}
fn form_4_unloaded() {
let p4 = P4Cli::default();
expect_chain!(["clients", "-U"], p4.clients().unloaded());
expect_chain!(["clients", "-U"], p4.workspaces().unloaded());
let mut cmd = echo_clients().unloaded();
assert_eq!(spawned_args_unit(&mut cmd), ["clients", "-U"]);
}
fn main() -> io::Result<()> {
form_1_bare();
form_2_single_options();
form_3_selection_orders();
form_4_unloaded();
println!("all p4 clients syntax combinations verified");
Ok(())
}