use assert_cmd::Command;
use predicates::prelude::*;
use std::os::unix::fs::PermissionsExt;
use tempfile::TempDir;
fn oo() -> Command {
Command::cargo_bin("oo").unwrap()
}
#[test]
fn test_echo_passthrough() {
oo().args(["echo", "hello"])
.assert()
.success()
.stdout("hello\n");
}
#[test]
fn test_multiword_echo() {
oo().args(["echo", "hello", "world"])
.assert()
.success()
.stdout("hello world\n");
}
#[test]
fn test_false_failure() {
oo().args(["false"])
.assert()
.failure()
.stdout(predicate::str::starts_with("\u{2717}")); }
#[test]
fn test_exit_code_preserved() {
oo().args(["sh", "-c", "exit 42"]).assert().code(42);
}
#[test]
fn test_version() {
oo().arg("version")
.assert()
.success()
.stdout(predicate::str::contains(env!("CARGO_PKG_VERSION")));
}
#[test]
fn test_no_args_shows_help() {
oo().assert()
.success()
.stdout(predicate::str::contains("Usage"));
}
#[test]
fn test_large_output_gets_indicator() {
let dir = TempDir::new().unwrap();
Command::new("git")
.args(["init"])
.current_dir(dir.path())
.output()
.unwrap();
for i in 0..100 {
std::fs::write(dir.path().join("file.txt"), format!("content {}\n", i)).unwrap();
Command::new("git")
.args(["add", "."])
.current_dir(dir.path())
.output()
.unwrap();
Command::new("git")
.args(["commit", "-m", &format!("commit {}", i)])
.env("GIT_AUTHOR_NAME", "Test")
.env("GIT_AUTHOR_EMAIL", "test@example.com")
.env("GIT_COMMITTER_NAME", "Test")
.env("GIT_COMMITTER_EMAIL", "test@example.com")
.current_dir(dir.path())
.output()
.unwrap();
}
oo().args(["git", "log"])
.current_dir(dir.path())
.assert()
.success()
.stdout(predicate::str::starts_with("\u{25CF}")); }
#[test]
fn test_stderr_included_in_failure() {
oo().args(["sh", "-c", "echo failure_msg >&2; exit 1"])
.assert()
.failure()
.stdout(predicate::str::contains("failure_msg"));
}
#[test]
fn test_forget_runs() {
oo().arg("forget")
.assert()
.success()
.stdout(predicate::str::contains("Cleared session data"));
}
#[test]
fn test_help_no_args_shows_usage() {
oo().arg("help")
.assert()
.success()
.stdout(predicate::str::contains("Usage:"));
}
#[test]
fn test_help_includes_help_cmd_in_usage() {
oo().assert()
.success()
.stdout(predicate::str::contains("help [cmd]"));
}
fn assert_full_subcommand_list(
assertion: assert_cmd::assert::Assert,
) -> assert_cmd::assert::Assert {
let mut assertion = assertion.success();
for (name, description) in [
("recall", "Search session output"),
("forget", "Clear session data"),
("learn", "Learn output compression patterns"),
("help [cmd]", "cheat-sheet for cmd via cheat.sh"),
("init", "Set up hooks for agent frameworks"),
("patterns", "List output compression patterns"),
("version", "Show version"),
] {
assertion = assertion.stdout(predicate::str::contains(name));
assertion = assertion.stdout(predicate::str::contains(description));
}
assertion = assertion.stdout(predicate::str::contains(
"Context-efficient command runner for AI coding agents",
));
assertion.stdout(predicate::str::contains("_learn_bg").not())
}
#[test]
fn test_no_args_lists_all_subcommands() {
assert_full_subcommand_list(oo().assert());
}
#[test]
fn test_help_no_args_lists_all_subcommands() {
assert_full_subcommand_list(oo().arg("help").assert());
}
#[test]
fn test_help_empty_arg() {
Command::cargo_bin("oo")
.unwrap()
.args(&["help", ""])
.assert()
.failure();
}
#[test]
fn test_init_creates_hooks_json() {
let dir = TempDir::new().unwrap();
oo().arg("init").current_dir(dir.path()).assert().success();
let hooks_path = dir.path().join(".claude").join("hooks.json");
assert!(
hooks_path.exists(),
".claude/hooks.json must exist after oo init"
);
}
#[test]
fn test_init_hooks_json_is_valid_json() {
let dir = TempDir::new().unwrap();
oo().arg("init").current_dir(dir.path()).assert().success();
let content = std::fs::read_to_string(dir.path().join(".claude").join("hooks.json")).unwrap();
let parsed: serde_json::Value =
serde_json::from_str(&content).expect("hooks.json must be valid JSON");
assert!(parsed.get("hooks").is_some());
}
#[test]
fn test_init_prints_agents_snippet() {
let dir = TempDir::new().unwrap();
oo().arg("init")
.current_dir(dir.path())
.assert()
.success()
.stdout(predicate::str::contains(
"Prefix all shell commands with `oo`",
));
}
#[test]
fn test_init_second_run_does_not_overwrite() {
let dir = TempDir::new().unwrap();
oo().arg("init").current_dir(dir.path()).assert().success();
let hooks_path = dir.path().join(".claude").join("hooks.json");
std::fs::write(&hooks_path, r#"{"hooks":[],"sentinel":true}"#).unwrap();
oo().arg("init").current_dir(dir.path()).assert().success();
let after = std::fs::read_to_string(&hooks_path).unwrap();
assert!(
after.contains("\"sentinel\":true"),
"pre-existing hooks.json must not be overwritten on second oo init"
);
}
#[test]
fn test_init_second_run_succeeds_without_error() {
let dir = TempDir::new().unwrap();
oo().arg("init").current_dir(dir.path()).assert().success();
oo().arg("init").current_dir(dir.path()).assert().success();
}
#[test]
fn test_init_format_generic_exits_success() {
let dir = TempDir::new().unwrap();
oo().args(["init", "--format", "generic"])
.current_dir(dir.path())
.assert()
.success();
}
#[test]
fn test_init_format_generic_prints_agents_snippet() {
let dir = TempDir::new().unwrap();
oo().args(["init", "--format", "generic"])
.current_dir(dir.path())
.assert()
.success()
.stdout(predicate::str::contains(
"Prefix all shell commands with `oo`",
));
}
#[test]
fn test_init_format_generic_prints_setup_section() {
let dir = TempDir::new().unwrap();
oo().args(["init", "--format", "generic"])
.current_dir(dir.path())
.assert()
.success()
.stdout(predicate::str::contains("## Setup"));
}
#[test]
fn test_init_format_generic_prints_shell_commands_instructions() {
let dir = TempDir::new().unwrap();
oo().args(["init", "--format", "generic"])
.current_dir(dir.path())
.assert()
.success()
.stdout(predicate::str::contains("oo recall"))
.stdout(predicate::str::contains("oo help"))
.stdout(predicate::str::contains("oo learn"));
}
#[test]
fn test_init_format_generic_prints_alias_section() {
let dir = TempDir::new().unwrap();
oo().args(["init", "--format", "generic"])
.current_dir(dir.path())
.assert()
.success()
.stdout(predicate::str::contains("alias o='oo'"));
}
#[test]
fn test_init_format_generic_does_not_create_hooks_json() {
let dir = TempDir::new().unwrap();
oo().args(["init", "--format", "generic"])
.current_dir(dir.path())
.assert()
.success();
let hooks_path = dir.path().join(".claude").join("hooks.json");
assert!(
!hooks_path.exists(),
"oo init --format generic must not create .claude/hooks.json"
);
}
#[test]
fn test_init_format_claude_creates_hooks_json() {
let dir = TempDir::new().unwrap();
oo().arg("init").current_dir(dir.path()).assert().success();
let hooks_path = dir.path().join(".claude").join("hooks.json");
assert!(
hooks_path.exists(),
".claude/hooks.json must exist after oo init --format claude"
);
}
#[test]
fn test_init_format_claude_prints_agents_snippet() {
let dir = TempDir::new().unwrap();
oo().arg("init")
.current_dir(dir.path())
.assert()
.success()
.stdout(predicate::str::contains(
"Prefix all shell commands with `oo`",
));
}
#[test]
fn test_recall_no_args() {
oo().arg("recall")
.assert()
.failure()
.stderr(predicate::str::contains("recall requires a query"));
}
#[test]
fn test_recall_no_results() {
oo().args(["recall", "xyzzy_nonexistent_query_12345"])
.assert()
.success()
.stdout(predicate::str::contains("No results found"));
}
fn index_large_blob() -> (TempDir, String) {
let dir = TempDir::new().unwrap();
let blob: String = (0..200)
.map(|i| {
format!(
"sentinel_line_{i:04} data_padding_abcdef_{}\n",
"x".repeat(50)
)
})
.collect();
let blob_file = dir.path().join("blob.txt");
std::fs::write(&blob_file, &blob).unwrap();
let mut cmd = oo();
cmd.args(["cat", blob_file.to_str().unwrap()]);
cmd.env("OO_DATA_DIR", dir.path());
cmd.assert().success();
(dir, blob)
}
#[test]
fn test_recall_default_is_bounded() {
let (dir, blob) = index_large_blob();
let mut cmd = oo();
cmd.args(["recall", "sentinel_line_0100"]);
cmd.env("OO_DATA_DIR", dir.path());
let output = cmd.output().unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(output.status.success(), "recall must exit 0");
let stdout_len = stdout.len();
let blob_len = blob.len();
assert!(
stdout_len < blob_len,
"default recall stdout ({stdout_len} B) must be < full blob ({blob_len} B)"
);
assert!(
!stdout.trim().is_empty(),
"default recall must produce output"
);
let blob_tail = &blob[blob.len().saturating_sub(100)..];
assert!(
!stdout.contains(blob_tail),
"default recall must NOT contain the tail of the blob (bounded display)"
);
}
#[test]
fn test_recall_full_shows_complete_blob() {
let (dir, _blob) = index_large_blob();
let mut cmd = oo();
cmd.args(["recall", "--full", "sentinel_line_0100"]);
cmd.env("OO_DATA_DIR", dir.path());
let output = cmd.output().unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(output.status.success(), "recall must exit 0");
assert!(
stdout.contains("sentinel_line_0199"),
"--full recall must contain the last sentinel line of the blob"
);
}
#[test]
fn test_recall_full_flag_position_independent() {
let (dir, _blob) = index_large_blob();
let mut cmd1 = oo();
cmd1.args(["recall", "--full", "sentinel_line_0100"]);
cmd1.env("OO_DATA_DIR", dir.path());
let out1 = cmd1.output().unwrap();
assert!(out1.status.success(), "flag-before must be --full mode");
let mut cmd2 = oo();
cmd2.args(["recall", "sentinel_line_0100", "--full"]);
cmd2.env("OO_DATA_DIR", dir.path());
let out2 = cmd2.output().unwrap();
assert!(out2.status.success(), "flag-after must be --full mode");
let stdout1 = String::from_utf8_lossy(&out1.stdout);
let stdout2 = String::from_utf8_lossy(&out2.stdout);
assert!(
stdout1.contains("sentinel_line_0199"),
"flag-before must be --full mode"
);
assert!(
stdout2.contains("sentinel_line_0199"),
"flag-after must be --full mode"
);
}
#[test]
fn test_recall_full_alone_gives_empty_query_error() {
oo().args(["recall", "--full"])
.assert()
.failure()
.stderr(predicate::str::contains("recall requires a query"));
}
#[test]
fn test_recall_default_displays_fts_snippet_not_content_prefix() {
let dir = TempDir::new().unwrap();
let filler: String = (0..500).map(|i| format!("filler{i:04}_ ")).collect(); let blob: String = format!("{filler}sentinel_beta_9999 {filler}"); let blob_file = dir.path().join("blob.txt");
std::fs::write(&blob_file, &blob).unwrap();
let mut cmd = oo();
cmd.args(["cat", blob_file.to_str().unwrap()]);
cmd.env("OO_DATA_DIR", dir.path());
cmd.assert().success();
let mut cmd = oo();
cmd.args(["recall", "sentinel_beta_9999"]);
cmd.env("OO_DATA_DIR", dir.path());
let output = cmd.output().unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(output.status.success(), "recall must exit 0");
assert!(
stdout.contains("sentinel_beta_9999"),
"default recall must display the FTS5 snippet centered on the matched token\ngot: {stdout}"
);
let stdout_len = stdout.len();
let blob_len = blob.len();
assert!(
stdout_len < blob_len,
"default recall stdout ({stdout_len} B) must be < full blob ({blob_len} B)"
);
}
#[test]
fn test_learn_no_args() {
oo().arg("learn")
.assert()
.failure()
.stderr(predicate::str::contains("learn requires a command"));
}
#[test]
fn test_learn_no_api_key() {
oo().args(["learn", "echo", "hello"])
.env_remove("ANTHROPIC_API_KEY")
.env_remove("OPENAI_API_KEY")
.assert()
.success()
.stderr(predicate::str::contains("[learning pattern for"));
}
#[test]
fn test_run_command_not_found() {
oo().args(["nonexistent_binary_xyz_abc_123"])
.assert()
.failure();
}
#[test]
fn test_run_multiword_command() {
oo().args(["echo", "hello", "world"])
.assert()
.success()
.stdout(predicate::str::contains("hello world"));
}
#[test]
fn test_passthrough_git_version() {
oo().args(["git", "--version"])
.assert()
.success()
.stdout(predicate::str::starts_with("git version"));
}
#[test]
fn test_failure_stderr_output() {
oo().args(["ls", "/nonexistent_path_xyz_abc_12345"])
.assert()
.failure()
.stdout(predicate::str::starts_with("\u{2717}")); }
#[test]
fn test_dispatch_version() {
oo().arg("version").assert().success();
}
#[test]
fn test_dispatch_forget() {
oo().arg("forget")
.assert()
.success()
.stdout(predicate::str::contains("Cleared session data"));
}
#[test]
fn test_dispatch_run() {
oo().args(["echo", "hi"])
.assert()
.success()
.stdout(predicate::str::contains("hi"));
}
#[test]
fn test_dispatch_recall_query_joined() {
oo().args(["recall", "hello", "world"]).assert().success();
}
#[test]
fn test_dispatch_help() {
oo().arg("help")
.assert()
.success()
.stdout(predicate::str::contains("Usage"));
}
#[test]
fn test_dispatch_init() {
let dir = TempDir::new().unwrap();
oo().arg("init").current_dir(dir.path()).assert().success();
}
#[test]
fn test_patterns_no_learned_patterns() {
let dir = TempDir::new().unwrap();
oo().arg("patterns")
.env("HOME", dir.path())
.env("XDG_CONFIG_HOME", dir.path().join(".config"))
.assert()
.success()
.stdout(predicate::str::contains("Built-in"))
.stdout(predicate::str::contains("User"));
}
#[test]
fn test_patterns_with_learned_pattern() {
let dir = TempDir::new().unwrap();
#[cfg(target_os = "macos")]
let patterns_dir = dir
.path()
.join("Library")
.join("Application Support")
.join("oo")
.join("patterns");
#[cfg(not(target_os = "macos"))]
let patterns_dir = dir.path().join(".config").join("oo").join("patterns");
std::fs::create_dir_all(&patterns_dir).unwrap();
std::fs::write(
patterns_dir.join("pytest.toml"),
"command_match = \"^pytest\"\n[success]\npattern = '(?P<n>\\d+) passed'\nsummary = \"{n} passed\"\n",
)
.unwrap();
oo().arg("patterns")
.env("HOME", dir.path())
.env("XDG_CONFIG_HOME", dir.path().join(".config"))
.assert()
.success()
.stdout(predicate::str::contains("^pytest"));
}
#[test]
fn test_learn_provider_logged_to_stderr() {
oo().args(["learn", "echo", "hello"])
.env_remove("ANTHROPIC_API_KEY")
.env_remove("OPENAI_API_KEY")
.env_remove("CEREBRAS_API_KEY")
.assert()
.success()
.stderr(predicate::str::contains("anthropic"));
}
#[test]
fn test_version_shows_oo_prefix() {
oo().arg("version")
.assert()
.success()
.stdout(predicate::str::starts_with("oo "));
}
#[test]
fn test_version_shows_version_number() {
let version = env!("CARGO_PKG_VERSION");
oo().arg("version")
.assert()
.success()
.stdout(predicate::str::contains(version));
}
#[test]
#[ignore = "requires network access to cheat.sh"]
fn test_help_with_valid_command() {
oo().args(["help", "ls"])
.assert()
.success()
.stdout(predicate::str::is_empty().not());
}
const RECALL_MARKER: &str = "oo148tailmarker7f3a9c";
fn write_repro_file(dir: &std::path::Path) -> std::path::PathBuf {
let mut content = String::new();
for i in 0..5000 {
content.push_str(&format!("line{i:06} {RECALL_MARKER}\n"));
}
let path = dir.join("big.txt");
std::fs::write(&path, &content).unwrap();
path
}
fn isolated_store() -> (TempDir, std::path::PathBuf) {
let dir = TempDir::new().unwrap();
let data_dir = dir.path().join("oo-data");
std::fs::create_dir_all(&data_dir).unwrap();
(dir, data_dir)
}
fn assert_recall_contains(data_dir: &std::path::Path, marker: &str) {
let out = oo()
.args(["recall", marker])
.env("OO_DATA_DIR", data_dir)
.assert()
.success()
.to_string();
assert!(
!out.contains("No results found"),
"recall on the tail marker must return a non-empty result; got: {out:?}"
);
assert!(
out.contains(marker),
"recall result must contain the tail marker token; got: {out:?}"
);
}
#[test]
fn test_content_arm_large_output_bounded_and_recallable() {
let file = TempDir::new().unwrap();
let big = write_repro_file(file.path());
let (_guard, data_dir) = isolated_store();
oo().args(["cat", big.to_str().unwrap()])
.env("OO_DATA_DIR", &data_dir)
.assert()
.success()
.stdout(predicate::function(|out: &str| out.len() < 20_000))
.stdout(predicate::str::contains(RECALL_MARKER));
assert_recall_contains(&data_dir, RECALL_MARKER);
}
#[test]
fn test_unknown_arm_large_output_bounded_and_recallable() {
let (_guard, data_dir) = isolated_store();
oo().args([
"sh",
"-c",
&format!("for i in $(seq 1 30000); do echo line; done; echo {RECALL_MARKER}"),
])
.env("OO_DATA_DIR", &data_dir)
.assert()
.success()
.stdout(predicate::function(|out: &str| out.len() < 20_000))
.stdout(predicate::str::contains(RECALL_MARKER));
assert_recall_contains(&data_dir, RECALL_MARKER);
}
#[test]
fn test_cargo_toml_has_shell_installer_enabled() {
let cargo_toml = include_str!("../Cargo.toml");
assert!(
cargo_toml.contains(r#"installers = ["shell"]"#),
"Cargo.toml must have shell installer enabled: installers = [\"shell\"]"
);
}
#[test]
fn test_cargo_toml_has_install_path_cargo_home() {
let cargo_toml = include_str!("../Cargo.toml");
assert!(
cargo_toml.contains(r#"install-path = "CARGO_HOME""#),
"Cargo.toml must have install-path = \"CARGO_HOME\""
);
}
#[test]
fn test_cargo_toml_has_cargo_dist_version() {
let cargo_toml = include_str!("../Cargo.toml");
assert!(
cargo_toml.contains("cargo-dist-version ="),
"Cargo.toml must specify cargo-dist-version for dist config"
);
}
#[test]
fn test_project_patterns_listed_when_present() {
let dir = TempDir::new().unwrap();
std::fs::create_dir_all(dir.path().join(".git")).unwrap();
let pat_dir = dir.path().join(".oo").join("patterns");
std::fs::create_dir_all(&pat_dir).unwrap();
std::fs::write(
pat_dir.join("mytest.toml"),
"command_match = \"^mytest\"\n[success]\npattern = '(?P<n>\\d+) ok'\nsummary = \"{n} ok\"\n",
)
.unwrap();
oo().arg("patterns")
.current_dir(dir.path())
.env("HOME", dir.path())
.env("XDG_CONFIG_HOME", dir.path().join(".config"))
.assert()
.success()
.stdout(predicate::str::contains("Project"))
.stdout(predicate::str::contains("^mytest"));
}
#[test]
fn test_project_patterns_override_builtins() {
let dir = TempDir::new().unwrap();
std::fs::create_dir_all(dir.path().join(".git")).unwrap();
let pat_dir = dir.path().join(".oo").join("patterns");
std::fs::create_dir_all(&pat_dir).unwrap();
std::fs::write(
pat_dir.join("echo.toml"),
"command_match = \"^echo\\\\b\"\n[success]\npattern = '(?s)(?P<all>.+)'\nsummary = \"proj-match\"\n",
)
.unwrap();
let big_arg = "x".repeat(5000);
oo().args(["echo", &big_arg])
.current_dir(dir.path())
.env("HOME", dir.path())
.env("XDG_CONFIG_HOME", dir.path().join(".config"))
.assert()
.success()
.stdout(predicate::str::contains("proj-match"));
}
fn make_fake_bin(name: &str, script_body: &str) -> (TempDir, String) {
let dir = TempDir::new().unwrap();
let bin_dir = dir.path().join("bin");
std::fs::create_dir_all(&bin_dir).unwrap();
let bin = bin_dir.join(name);
std::fs::write(&bin, script_body).unwrap();
std::fs::set_permissions(&bin, std::fs::Permissions::from_mode(0o755)).unwrap();
let path = format!(
"{}:{}",
bin_dir.display(),
std::env::var("PATH").unwrap_or_default()
);
(dir, path)
}
#[test]
fn test_quiet_success_shows_savings() {
let (keep, path) = make_fake_bin(
"go",
"#!/bin/sh\nfor i in $(seq 1 500); do echo 'building component $i ...'; done\nexit 0\n",
);
let _ = keep;
oo().args(["go", "build"])
.env("PATH", path)
.assert()
.success()
.stdout(predicate::str::starts_with("\u{2713}"))
.stdout(predicate::str::contains("[saved "))
.stdout(predicate::function(|out: &str| {
let first_line = out.lines().next().unwrap_or("");
first_line.starts_with('\u{2713}') && first_line.contains("[saved ")
}));
}
#[test]
fn test_summary_success_shows_savings() {
let (keep, path) = make_fake_bin(
"cargo",
"#!/bin/sh\nfor i in $(seq 1 500); do echo \"running test $i ...\"; done\necho \"test result: ok. 42 passed; 0 failed; finished in 1.23s\"\nexit 0\n",
);
let _ = keep;
oo().args(["cargo", "test"])
.env("PATH", path)
.assert()
.success()
.stdout(predicate::str::starts_with("\u{2713}"))
.stdout(predicate::str::contains("42 passed"))
.stdout(predicate::str::contains("[saved "))
.stdout(predicate::function(|out: &str| {
let first_line = out.lines().next().unwrap_or("");
first_line.starts_with('\u{2713}') && first_line.contains("[saved ")
}));
}
#[test]
fn test_failure_shows_savings() {
let (keep, path) = make_fake_bin(
"pytest",
"#!/bin/sh\nfor i in $(seq 1 500); do echo \"ERROR: test_failing_$i failed with assertion error\"; done\nexit 1\n",
);
let _ = keep;
oo().args(["pytest", "-x"])
.env("PATH", path)
.assert()
.failure()
.stdout(predicate::str::starts_with("\u{2717}"))
.stdout(predicate::str::contains("[saved "))
.stdout(predicate::function(|out: &str| {
let first_line = out.lines().next().unwrap_or("");
first_line.starts_with('\u{2717}') && first_line.contains("[saved ")
}));
}
#[test]
fn test_failure_indicator_blank_line_with_suffix() {
let (keep, path) = make_fake_bin(
"pytest",
"#!/bin/sh\nfor i in $(seq 1 500); do echo \"ERROR: test_failing_$i failed with assertion error\"; done\nexit 1\n",
);
let _ = keep;
oo().args(["pytest", "-x"])
.env("PATH", path)
.assert()
.failure()
.stdout(predicate::function(|out: &str| {
let mut lines = out.lines();
let indicator = lines.next().unwrap_or("");
let blank = lines.next().unwrap_or("");
indicator.starts_with('\u{2717}') && indicator.contains("[saved ") && blank.is_empty()
}));
}
#[test]
fn test_failure_indicator_blank_line_without_suffix() {
oo().args(["false"])
.assert()
.failure()
.stdout(predicate::function(|out: &str| {
let mut lines = out.lines();
let indicator = lines.next().unwrap_or("");
let blank = lines.next().unwrap_or("");
indicator.starts_with('\u{2717}') && !indicator.contains("[saved ") && blank.is_empty()
}));
}
#[test]
fn test_large_arm_wording_unchanged_no_savings() {
let dir = TempDir::new().unwrap();
Command::new("git")
.args(["init"])
.current_dir(dir.path())
.output()
.unwrap();
for i in 0..100 {
std::fs::write(dir.path().join("file.txt"), format!("content {}\n", i)).unwrap();
Command::new("git")
.args(["add", "."])
.current_dir(dir.path())
.output()
.unwrap();
Command::new("git")
.args(["commit", "-m", &format!("commit {}", i)])
.env("GIT_AUTHOR_NAME", "Test")
.env("GIT_AUTHOR_EMAIL", "test@example.com")
.env("GIT_COMMITTER_NAME", "Test")
.env("GIT_COMMITTER_EMAIL", "test@example.com")
.current_dir(dir.path())
.output()
.unwrap();
}
oo().args(["git", "log"])
.current_dir(dir.path())
.assert()
.success()
.stdout(predicate::str::starts_with("\u{25CF}"))
.stdout(predicate::str::contains("indexed"))
.stdout(predicate::str::contains("use `oo recall` to query"))
.stdout(predicate::str::contains("[saved ").not());
}
#[test]
fn test_bounded_arm_wording_unchanged_no_savings() {
let dir = TempDir::new().unwrap();
let big_file = dir.path().join("big.txt");
let content = std::iter::repeat("x\n").take(5000).collect::<String>();
std::fs::write(&big_file, &content).unwrap();
oo().args(["cat", big_file.to_str().unwrap()])
.assert()
.success()
.stdout(predicate::str::starts_with("\u{25CF}"))
.stdout(predicate::str::contains("output truncated:"))
.stdout(predicate::str::contains("use `oo recall` to query"))
.stdout(predicate::str::contains("[saved ").not());
}
#[test]
fn test_passthrough_no_savings() {
oo().args(["echo", "hello"])
.assert()
.success()
.stdout("hello\n");
}
#[test]
fn test_clap_help_lists_all_subcommands() {
oo().arg("--help")
.assert()
.success()
.stdout(predicate::str::contains(
"Context-efficient command runner for AI coding agents",
))
.stdout(predicate::str::contains("recall ("))
.stdout(predicate::str::contains("forget ("))
.stdout(predicate::str::contains("learn ("))
.stdout(predicate::str::contains("help ("))
.stdout(predicate::str::contains("init ("))
.stdout(predicate::str::contains("patterns ("))
.stdout(predicate::str::contains("version ("));
}
#[test]
fn test_clap_short_help_lists_all_subcommands() {
oo().arg("-h")
.assert()
.success()
.stdout(predicate::str::contains("Context-efficient command runner"))
.stdout(predicate::str::contains("recall ("))
.stdout(predicate::str::contains("forget ("))
.stdout(predicate::str::contains("learn ("))
.stdout(predicate::str::contains("help ("))
.stdout(predicate::str::contains("init ("))
.stdout(predicate::str::contains("patterns ("))
.stdout(predicate::str::contains("version ("));
}