mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-28 20:18:06 -06:00
The desktop app's argument loop took `--help` as a view setting named `help` (consuming the next argument as its value) and `-h` as a file to open, so both started the window and a scripted call never returned. `-h` and `--help` now print a short usage, which points scripts to pdfcraft-cli, and exit 0 before any window or log file is created. `--version` and `--help` write through a plain `writeln!` instead of `println!`, which panicked (exit 101) when standard output was full or closed, e.g. `pdfcraft --version > /dev/full`. Release builds on Windows are GUI-subsystem programs, so, as with `--version` already, the text shows when the output is redirected or piped but not in a plain console window. Fixes #4076
56 lines
2.4 KiB
Rust
56 lines
2.4 KiB
Rust
//! `--help`, `-h` and `--version` print and exit without opening a window (#4076), so a script that
|
|
//! calls them returns.
|
|
|
|
use std::process::{Command, Output, Stdio};
|
|
use std::time::{Duration, Instant};
|
|
|
|
const BIN: &str = env!("CARGO_BIN_EXE_pdfcraft");
|
|
|
|
/// Run the app with `args`, failing if it is still running after 60 s (it opened its window).
|
|
fn run(args: &[&str], stdout: Stdio) -> Output {
|
|
let mut child = Command::new(BIN).args(args).stdin(Stdio::null()).stdout(stdout).stderr(Stdio::piped()).spawn().unwrap();
|
|
let deadline = Instant::now() + Duration::from_secs(60);
|
|
while child.try_wait().unwrap().is_none() {
|
|
if Instant::now() > deadline {
|
|
let _ = child.kill();
|
|
panic!("pdfcraft {args:?} did not exit: it started the app instead");
|
|
}
|
|
std::thread::sleep(Duration::from_millis(50));
|
|
}
|
|
child.wait_with_output().unwrap()
|
|
}
|
|
|
|
#[test]
|
|
fn help_prints_usage_and_exits() {
|
|
for flag in ["--help", "-h"] {
|
|
let out = run(&[flag], Stdio::piped());
|
|
assert!(out.status.success(), "{flag}: {:?} {}", out.status, String::from_utf8_lossy(&out.stderr));
|
|
let stdout = String::from_utf8_lossy(&out.stdout);
|
|
assert!(stdout.starts_with("Usage: pdfcraft [options] [files…]"), "{flag}: {stdout}");
|
|
assert!(stdout.contains("pdfcraft-cli"), "{flag}: points scripts to the CLI: {stdout}");
|
|
}
|
|
// Wherever it is on the command line, and with files named.
|
|
let out = run(&["missing.pdf", "--help"], Stdio::piped());
|
|
assert!(out.status.success());
|
|
assert!(String::from_utf8_lossy(&out.stdout).starts_with("Usage:"));
|
|
}
|
|
|
|
#[test]
|
|
fn version_prints_the_version_and_exits() {
|
|
let out = run(&["--version"], Stdio::piped());
|
|
assert!(out.status.success(), "{:?} {}", out.status, String::from_utf8_lossy(&out.stderr));
|
|
assert!(String::from_utf8_lossy(&out.stdout).starts_with("pdfcraft "), "{}", String::from_utf8_lossy(&out.stdout));
|
|
}
|
|
|
|
/// A standard output that can't be written (here a full device) ends the run normally: `println!`
|
|
/// would panic and exit 101.
|
|
#[cfg(target_os = "linux")]
|
|
#[test]
|
|
fn help_and_version_survive_an_unwritable_stdout() {
|
|
for flag in ["--help", "--version"] {
|
|
let full = std::fs::OpenOptions::new().write(true).open("/dev/full").unwrap();
|
|
let out = run(&[flag], Stdio::from(full));
|
|
assert!(out.status.success(), "{flag}: {:?} {}", out.status, String::from_utf8_lossy(&out.stderr));
|
|
}
|
|
}
|