#![cfg(not(miri))]
use std::path::Path;
use std::process::{Command, Output};
fn get_binary() -> String {
env!("CARGO_BIN_EXE_grpctestify").to_string()
}
fn fixture(rel: &str) -> String {
Path::new(env!("CARGO_MANIFEST_DIR"))
.join(rel)
.to_string_lossy()
.into_owned()
}
fn run(args: &[&str]) -> Output {
let binary = get_binary();
let runner = std::env::var("CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER")
.ok()
.or_else(|| std::env::var("CROSS_RUNNER").ok());
let mut cmd = if let Some(runner) = runner {
let mut parts = runner.split_whitespace();
let prog = parts.next().expect("runner must not be empty");
let mut c = Command::new(prog);
c.args(parts).arg(&binary);
c
} else {
Command::new(&binary)
};
cmd.current_dir(env!("CARGO_MANIFEST_DIR"))
.args(args)
.output()
.expect("failed to run grpctestify")
}
#[test]
fn call_missing_file_returns_error() {
let out = run(&["call", "nonexistent.gctf"]);
assert!(!out.status.success());
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(stderr.contains("not found") || stderr.contains("No such"));
}
#[test]
fn call_doc_index_zero_is_rejected() {
let f = fixture("tests/data/call/unreachable.gctf");
let out = run(&["call", "--doc-index", "0", &f]);
assert!(!out.status.success());
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(stderr.contains("--doc-index must be >= 1"));
}
#[test]
fn call_doc_index_out_of_range_returns_error() {
let f = fixture("tests/data/call/unreachable.gctf");
let out = run(&["call", "--doc-index", "99", &f]);
assert!(!out.status.success());
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(stderr.contains("out of range"));
}
#[test]
fn call_verbose_prints_request_section_to_stderr() {
let f = fixture("tests/data/call/unreachable.gctf");
let out = run(&["call", "-v", &f]);
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(
stderr.contains("* Trying"),
"expected '* Trying' in stderr:\n{}",
stderr
);
assert!(
stderr.contains("EchoService/SayHello"),
"expected method in stderr:\n{}",
stderr
);
}
#[test]
fn call_very_verbose_implies_verbose() {
let f = fixture("tests/data/call/unreachable.gctf");
let out = run(&["call", "--vv", &f]);
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(
stderr.contains("* Trying"),
"expected '* Trying' in stderr:\n{}",
stderr
);
}
#[test]
fn call_no_verbose_no_request_section_in_stderr() {
let f = fixture("tests/data/call/unreachable.gctf");
let out = run(&["call", &f]);
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(
!stderr.contains("* Trying") && !stderr.contains("* Connected"),
"unexpected verbose output in non-verbose mode:\n{}",
stderr
);
}
#[test]
fn call_silent_suppresses_verbose_stderr() {
let f = fixture("tests/data/call/unreachable.gctf");
let out = run(&["call", "-v", "-s", &f]);
let stderr = String::from_utf8_lossy(&out.stderr);
let has_verbose_line = stderr
.lines()
.any(|line| line.starts_with("* ") || line.starts_with("> ") || line.starts_with("< "));
assert!(
!has_verbose_line,
"verbose output leaked through silent mode:\n{}",
stderr
);
}
#[test]
fn call_silent_produces_no_body_in_stdout() {
let f = fixture("tests/data/call/unreachable.gctf");
let out = run(&["call", "-s", &f]);
let stdout = String::from_utf8_lossy(&out.stdout);
let has_json_body = stdout
.lines()
.any(|l| l.trim_start().starts_with('{') || l.trim_start().starts_with('['));
assert!(
!has_json_body,
"response body must not appear in silent mode:\n{}",
stdout
);
}
#[test]
fn call_multi_doc_selects_by_index() {
let f = fixture("tests/data/call/multi_doc.gctf");
for idx in ["1", "2"] {
let out = run(&["call", "--doc-index", idx, &f]);
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(
!stderr.contains("out of range"),
"doc-index {} reported out-of-range unexpectedly:\n{}",
idx,
stderr
);
}
}
#[test]
fn call_multi_doc_index_3_is_out_of_range() {
let f = fixture("tests/data/call/multi_doc.gctf");
let out = run(&["call", "--doc-index", "3", &f]);
assert!(!out.status.success());
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(stderr.contains("out of range"), "stderr:\n{}", stderr);
}