#![allow(clippy::unwrap_used, clippy::expect_used)]
use std::process::Command;
fn tokf() -> Command {
Command::new(env!("CARGO_BIN_EXE_tokf"))
}
const TEN_LINE_CMD: &str = "for i in 1 2 3 4 5 6 7 8 9 10; do echo line$i; done";
fn last_event(db_path: &std::path::Path) -> (i64, i64) {
let conn = rusqlite::Connection::open(db_path).unwrap();
conn.query_row(
"SELECT input_bytes, output_bytes FROM events ORDER BY rowid DESC LIMIT 1",
[],
|row| Ok((row.get(0)?, row.get(1)?)),
)
.unwrap()
}
fn last_event_full(db_path: &std::path::Path) -> (i64, i64, bool) {
let conn = rusqlite::Connection::open(db_path).unwrap();
conn.query_row(
"SELECT input_bytes, output_bytes, pipe_override FROM events ORDER BY rowid DESC LIMIT 1",
[],
|row| {
let po: i64 = row.get(2)?;
Ok((row.get(0)?, row.get(1)?, po != 0))
},
)
.unwrap()
}
fn setup_filter_dir(filter_output: &str) -> tempfile::TempDir {
let dir = tempfile::TempDir::new().unwrap();
let filters_dir = dir.path().join(".tokf/filters");
std::fs::create_dir_all(&filters_dir).unwrap();
std::fs::write(
filters_dir.join("echo.toml"),
format!("command = \"echo\"\n[on_success]\noutput = \"{filter_output}\""),
)
.unwrap();
dir
}
#[test]
fn baseline_pipe_records_piped_byte_count() {
let dir = tempfile::TempDir::new().unwrap();
let db_path = dir.path().join("test-fair.db");
let output = tokf()
.args([
"run",
"--no-filter",
"--baseline-pipe",
"tail -3",
"sh",
"-c",
TEN_LINE_CMD,
])
.env("TOKF_DB_PATH", &db_path)
.current_dir(dir.path())
.output()
.unwrap();
assert!(
output.status.success(),
"tokf run failed: {}",
String::from_utf8_lossy(&output.stderr)
);
let (input_bytes, _) = last_event(&db_path);
assert!(
input_bytes > 0,
"input_bytes should be positive, got {input_bytes}"
);
assert!(
input_bytes < 30,
"input_bytes should reflect ~3 lines (~18 bytes), got {input_bytes}"
);
}
#[test]
fn no_baseline_pipe_records_full_byte_count() {
let dir = tempfile::TempDir::new().unwrap();
let db_path = dir.path().join("test-full.db");
let output = tokf()
.args(["run", "--no-filter", "sh", "-c", TEN_LINE_CMD])
.env("TOKF_DB_PATH", &db_path)
.current_dir(dir.path())
.output()
.unwrap();
assert!(output.status.success());
let (input_bytes, _) = last_event(&db_path);
assert!(
input_bytes > 50,
"input_bytes should reflect full output (~61 bytes), got {input_bytes}"
);
}
#[test]
fn passthrough_output_bytes_is_full_output() {
let dir = tempfile::TempDir::new().unwrap();
let db_path = dir.path().join("test-passthrough.db");
let output = tokf()
.args([
"run",
"--no-filter",
"--baseline-pipe",
"tail -3",
"sh",
"-c",
TEN_LINE_CMD,
])
.env("TOKF_DB_PATH", &db_path)
.current_dir(dir.path())
.output()
.unwrap();
assert!(output.status.success());
let (input_bytes, output_bytes) = last_event(&db_path);
assert!(
input_bytes < 30,
"input_bytes should be piped baseline, got {input_bytes}"
);
assert!(
output_bytes > 50,
"output_bytes should be full output, got {output_bytes}"
);
assert!(
output_bytes > input_bytes,
"output_bytes ({output_bytes}) should exceed input_bytes ({input_bytes})"
);
}
#[test]
fn baseline_pipe_rejects_unknown_command() {
let dir = tempfile::TempDir::new().unwrap();
let db_path = dir.path().join("test-reject.db");
let output = tokf()
.args([
"run",
"--no-filter",
"--baseline-pipe",
"wc -l",
"sh",
"-c",
TEN_LINE_CMD,
])
.env("TOKF_DB_PATH", &db_path)
.current_dir(dir.path())
.output()
.unwrap();
assert!(output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("not allowed"),
"expected rejection warning, got: {stderr}"
);
let (input_bytes, _) = last_event(&db_path);
assert!(
input_bytes > 50,
"should fall back to full output, got {input_bytes}"
);
}
#[test]
fn baseline_pipe_does_not_crash_on_pipe_failure() {
let dir = tempfile::TempDir::new().unwrap();
let db_path = dir.path().join("test-fail.db");
let output = tokf()
.args([
"run",
"--no-filter",
"--baseline-pipe",
"grep --nonexistent-flag-xyz",
"sh",
"-c",
TEN_LINE_CMD,
])
.env("TOKF_DB_PATH", &db_path)
.current_dir(dir.path())
.output()
.unwrap();
assert!(
output.status.success(),
"tokf should not crash on pipe failure: {}",
String::from_utf8_lossy(&output.stderr)
);
let conn = rusqlite::Connection::open(&db_path).unwrap();
let count: i64 = conn
.query_row("SELECT COUNT(*) FROM events", [], |row| row.get(0))
.unwrap();
assert_eq!(count, 1, "should record exactly one event");
}
#[test]
fn baseline_pipe_grep_records_matching_lines() {
let dir = tempfile::TempDir::new().unwrap();
let db_path = dir.path().join("test-grep.db");
let output = tokf()
.args([
"run",
"--no-filter",
"--baseline-pipe",
"grep line1",
"sh",
"-c",
TEN_LINE_CMD,
])
.env("TOKF_DB_PATH", &db_path)
.current_dir(dir.path())
.output()
.unwrap();
assert!(output.status.success());
let (input_bytes, _) = last_event(&db_path);
assert!(
input_bytes > 0,
"input_bytes should be positive, got {input_bytes}"
);
assert!(
input_bytes < 20,
"input_bytes should reflect matching lines (~12 bytes), got {input_bytes}"
);
}
#[test]
fn baseline_pipe_empty_output() {
let dir = tempfile::TempDir::new().unwrap();
let db_path = dir.path().join("test-empty.db");
let output = tokf()
.args([
"run",
"--no-filter",
"--baseline-pipe",
"tail -3",
"sh",
"-c",
"exit 0",
])
.env("TOKF_DB_PATH", &db_path)
.current_dir(dir.path())
.output()
.unwrap();
assert!(output.status.success());
let (input_bytes, output_bytes) = last_event(&db_path);
assert_eq!(input_bytes, 0, "empty command → input_bytes = 0");
assert_eq!(output_bytes, 0, "empty command → output_bytes = 0");
}
#[test]
fn baseline_pipe_head_records_first_lines() {
let dir = tempfile::TempDir::new().unwrap();
let db_path = dir.path().join("test-head.db");
let output = tokf()
.args([
"run",
"--no-filter",
"--baseline-pipe",
"head -2",
"sh",
"-c",
TEN_LINE_CMD,
])
.env("TOKF_DB_PATH", &db_path)
.current_dir(dir.path())
.output()
.unwrap();
assert!(output.status.success());
let (input_bytes, _) = last_event(&db_path);
assert!(
input_bytes > 0 && input_bytes < 20,
"input_bytes should reflect ~2 lines (~12 bytes), got {input_bytes}"
);
}
#[test]
fn prefer_less_uses_filtered_when_smaller() {
let dir = setup_filter_dir("filtered");
let db_path = dir.path().join("test-pl-filtered.db");
let output = tokf()
.args([
"run",
"--baseline-pipe",
"grep a",
"--prefer-less",
"echo",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
])
.env("TOKF_DB_PATH", &db_path)
.current_dir(dir.path())
.output()
.unwrap();
assert!(
output.status.success(),
"stderr: {}",
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("filtered"),
"should print filtered output, got: {stdout}"
);
let (_, _, pipe_override) = last_event_full(&db_path);
assert!(!pipe_override, "pipe_override should be false");
}
#[test]
fn prefer_less_uses_piped_when_smaller() {
let dir = tempfile::TempDir::new().unwrap();
let filters_dir = dir.path().join(".tokf/filters");
std::fs::create_dir_all(&filters_dir).unwrap();
let long_output = "x".repeat(200);
std::fs::write(
filters_dir.join("sh.toml"),
format!("command = \"sh\"\n[on_success]\noutput = \"{long_output}\""),
)
.unwrap();
let db_path = dir.path().join("test-pl-piped.db");
let output = tokf()
.args([
"run",
"--baseline-pipe",
"tail -1",
"--prefer-less",
"sh",
"-c",
TEN_LINE_CMD,
])
.env("TOKF_DB_PATH", &db_path)
.current_dir(dir.path())
.output()
.unwrap();
assert!(
output.status.success(),
"stderr: {}",
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("line10"),
"should print piped output (tail -1), got: {stdout}"
);
assert!(
!stdout.contains(&long_output),
"should NOT print filter output"
);
let (_, _, pipe_override) = last_event_full(&db_path);
assert!(pipe_override, "pipe_override should be true");
}
#[test]
fn prefer_less_without_baseline_pipe_is_noop() {
let output = tokf()
.args(["run", "--prefer-less", "echo", "hello"])
.output()
.unwrap();
assert!(
output.status.success(),
"should succeed as a no-op, stderr: {}",
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("hello"),
"should print normal output, got: {stdout}"
);
}
#[test]
fn prefer_less_fallback_on_disallowed_pipe() {
let dir = setup_filter_dir("filtered-ok");
let db_path = dir.path().join("test-pl-fail.db");
let output = tokf()
.args([
"run",
"--baseline-pipe",
"wc -l",
"--prefer-less",
"echo",
"hello",
])
.env("TOKF_DB_PATH", &db_path)
.current_dir(dir.path())
.output()
.unwrap();
assert!(
output.status.success(),
"tokf should not crash, stderr: {}",
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("filtered-ok"),
"should fall back to filtered output, got: {stdout}"
);
let (_, _, pipe_override) = last_event_full(&db_path);
assert!(!pipe_override, "pipe_override should be false on failure");
}
#[test]
fn prefer_less_passthrough_verbose_warns() {
let dir = tempfile::TempDir::new().unwrap();
let output = tokf()
.args([
"--verbose",
"run",
"--baseline-pipe",
"tail -1",
"--prefer-less",
"echo",
"hello",
])
.current_dir(dir.path())
.output()
.unwrap();
assert!(output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("--prefer-less has no effect"),
"should warn about no effect, got: {stderr}"
);
}