use std::path::Path;
use tempfile::TempDir;
use super::super::test_support::{bind_script, edge, landing_with, log_at, log_lines};
use super::fold;
use crate::config::EffectiveConfig;
use crate::edge::Edge;
use crate::log::Level;
use crate::plugin::DEPTH_CAP;
use crate::registry::Registry;
use crate::verb::Verb;
fn fold_at(tmp: &Path, edge: &Edge, verb: Verb, id: Option<&str>) -> String {
fold(edge, tmp, verb, id, &EffectiveConfig::default(), &log_at(tmp, Level::Debug, verb))
}
const SHOW_WIRED: &str = "[hooks]\n\"show\" = [\"fake\"]\n";
#[test]
fn fold_captures_a_wired_plugins_stdout_verbatim() {
let tmp = TempDir::new().unwrap();
let edge = edge(tmp.path(), 0);
let landing = landing_with(&edge, SHOW_WIRED);
bind_script(
tmp.path(),
&landing,
"fake",
"#!/bin/sh\npayload=$(cat)\ncase \"$payload\" in *'\"bl-id\":[\"bl-7\"]'*) ;; *) exit 1;; esac\necho \"line $1 $2 $BALLS_PLUGIN_NAME\"\n",
);
assert_eq!(fold_at(tmp.path(), &edge, Verb::Show, Some("bl-7")), "line show read fake\n");
assert!(log_lines(tmp.path()).contains(r#""lvl":"debug","src":"core","op":"show","msg":"invoke fake""#));
}
#[test]
fn a_target_free_read_dispatches_with_empty_metadata() {
let tmp = TempDir::new().unwrap();
let edge = edge(tmp.path(), 0);
let landing = landing_with(&edge, "[hooks]\n\"list\" = [\"fake\"]\n");
bind_script(
tmp.path(),
&landing,
"fake",
"#!/bin/sh\npayload=$(cat)\ncase \"$payload\" in *bl-id*) exit 1;; esac\necho \"bare $1 $2\"\n",
);
assert_eq!(fold_at(tmp.path(), &edge, Verb::List, None), "bare list read\n");
}
#[test]
fn fold_skips_a_failing_plugin_but_keeps_the_others_lines() {
let tmp = TempDir::new().unwrap();
let edge = edge(tmp.path(), 0);
let landing = landing_with(&edge, "[hooks]\n\"show\" = [\"bad\", \"good\"]\n");
bind_script(tmp.path(), &landing, "bad", "#!/bin/sh\ncat > /dev/null\necho noise\nexit 3\n");
bind_script(tmp.path(), &landing, "good", "#!/bin/sh\ncat > /dev/null\necho kept\n");
assert_eq!(fold_at(tmp.path(), &edge, Verb::Show, Some("bl-1")), "kept\n");
assert!(log_lines(tmp.path())
.contains(r#""lvl":"error","src":"core","op":"show","msg":"plugin bad failed the show read dispatch""#));
}
#[test]
fn plugin_stderr_is_enveloped_at_info() {
let tmp = TempDir::new().unwrap();
let edge = edge(tmp.path(), 0);
let landing = landing_with(&edge, SHOW_WIRED);
bind_script(tmp.path(), &landing, "fake", "#!/bin/sh\ncat > /dev/null\necho diagnostic >&2\necho line\n");
let log = log_at(tmp.path(), Level::Info, Verb::Show);
let out = fold(&edge, tmp.path(), Verb::Show, Some("bl-1"), &EffectiveConfig::default(), &log);
assert_eq!(out, "line\n");
let lines = log_lines(tmp.path());
assert!(lines.contains(r#""lvl":"info","src":"fake","op":"show","msg":"diagnostic""#));
assert!(!lines.contains("invoke")); }
#[test]
fn fold_is_empty_at_the_recursion_cap() {
let tmp = TempDir::new().unwrap();
assert_eq!(fold_at(tmp.path(), &edge(tmp.path(), DEPTH_CAP), Verb::Show, Some("bl-1")), "");
}
#[test]
fn fold_is_empty_when_nothing_is_wired_or_the_schedule_is_malformed() {
let tmp = TempDir::new().unwrap();
assert_eq!(fold_at(tmp.path(), &edge(tmp.path(), 0), Verb::Show, Some("bl-1")), "");
let broken = TempDir::new().unwrap();
let e = edge(broken.path(), 0);
landing_with(&e, "[hooks");
assert_eq!(fold_at(broken.path(), &e, Verb::Show, Some("bl-1")), "");
}
#[test]
fn fold_skips_a_dangling_binding_and_an_unspawnable_binary() {
let tmp = TempDir::new().unwrap();
let e = edge(tmp.path(), 0);
landing_with(&e, SHOW_WIRED);
assert_eq!(fold_at(tmp.path(), &e, Verb::Show, Some("bl-1")), "");
let tmp2 = TempDir::new().unwrap();
let e2 = edge(tmp2.path(), 0);
let landing2 = landing_with(&e2, SHOW_WIRED);
let bin = tmp2.path().join("fake");
std::fs::write(&bin, "not executable").unwrap();
Registry::at(&landing2).bind("fake", &bin).unwrap();
assert_eq!(fold_at(tmp2.path(), &e2, Verb::Show, Some("bl-1")), "");
assert!(log_lines(tmp2.path()).contains(r#""lvl":"error","src":"core""#));
}