use super::*;
use serde_json::json;
fn sample_lifecycle() -> LifecycleEvent {
LifecycleEvent::PmThinking {
session_id: "s1".into(),
text: "considering options".into(),
}
}
fn envelope(payload: HarnessPayload, session: Option<&str>) -> HarnessEvent {
HarnessEvent {
source: HarnessSource::Agents,
session: session.map(str::to_string),
seq: 0,
at: chrono::Utc::now(),
payload,
}
}
#[test]
fn harness_source_round_trips() {
for (src, tag) in [
(HarnessSource::Agents, "\"agents\""),
(HarnessSource::Mpm, "\"mpm\""),
(HarnessSource::Code, "\"code\""),
] {
let s = serde_json::to_string(&src).expect("serialize source");
assert_eq!(s, tag);
let back: HarnessSource = serde_json::from_str(&s).expect("deserialize source");
assert_eq!(back, src);
}
}
#[test]
fn lifecycle_event_serializes_with_type_tag() {
let s = serde_json::to_string(&sample_lifecycle()).expect("serialize");
assert!(s.contains("\"type\":\"pm_thinking\""), "{s}");
assert!(s.contains("\"session_id\":\"s1\""), "{s}");
}
#[test]
fn lifecycle_session_id_returns_correct_field() {
let ev = LifecycleEvent::AgentMessage {
session_id: "abc".into(),
agent: "python".into(),
text: "hi".into(),
};
assert_eq!(ev.session_id(), Some("abc"));
}
#[test]
fn lifecycle_recap_round_trips() {
let ev = LifecycleEvent::RecapGenerated {
session_id: "s9".into(),
summary: "did a thing".into(),
table_rows: vec![("step".into(), "ok".into())],
};
let s = serde_json::to_string(&ev).expect("serialize recap");
let back: LifecycleEvent = serde_json::from_str(&s).expect("deserialize recap");
assert_eq!(back, ev);
}
#[test]
fn payload_lifecycle_round_trips() {
let p = HarnessPayload::Lifecycle(sample_lifecycle());
let s = serde_json::to_string(&p).expect("serialize");
assert!(s.contains("\"domain\":\"lifecycle\""), "{s}");
assert!(s.contains("\"event\":{"), "{s}");
assert!(s.contains("\"type\":\"pm_thinking\""), "{s}");
let back: HarnessPayload = serde_json::from_str(&s).expect("deserialize");
assert_eq!(back, p);
}
#[test]
fn payload_hook_round_trips() {
let p = HarnessPayload::Hook {
kind: "pre_tool_use".into(),
data: json!({"tool": "bash", "ok": true}),
};
let s = serde_json::to_string(&p).expect("serialize");
assert!(s.contains("\"domain\":\"hook\""), "{s}");
assert!(s.contains("\"kind\":\"pre_tool_use\""), "{s}");
let back: HarnessPayload = serde_json::from_str(&s).expect("deserialize");
assert_eq!(back, p);
}
#[test]
fn payload_ping_round_trips() {
let p = HarnessPayload::Ping;
let s = serde_json::to_string(&p).expect("serialize");
assert_eq!(s, "{\"domain\":\"ping\"}");
let back: HarnessPayload = serde_json::from_str(&s).expect("deserialize");
assert_eq!(back, p);
}
#[test]
fn payload_domain_matches_serde_tag() {
assert_eq!(
HarnessPayload::Lifecycle(sample_lifecycle()).domain(),
"lifecycle"
);
assert_eq!(
HarnessPayload::Hook {
kind: "x".into(),
data: json!(null)
}
.domain(),
"hook"
);
assert_eq!(HarnessPayload::Ping.domain(), "ping");
}
#[test]
fn harness_event_round_trips() {
let ev = envelope(HarnessPayload::Ping, Some("sess-1"));
let s = serde_json::to_string(&ev).expect("serialize");
assert!(s.contains("\"source\":\"agents\""), "{s}");
assert!(s.contains("\"session\":\"sess-1\""), "{s}");
let back: HarnessEvent = serde_json::from_str(&s).expect("deserialize");
assert_eq!(back, ev);
}
#[test]
fn harness_event_omits_none_session() {
let ev = envelope(HarnessPayload::Ping, None);
let s = serde_json::to_string(&ev).expect("serialize");
assert!(!s.contains("session"), "session should be omitted: {s}");
}
#[test]
fn filter_default_matches_all() {
let f = Filter::default();
assert!(f.matches(&envelope(HarnessPayload::Ping, None)));
assert!(f.matches(&envelope(
HarnessPayload::Lifecycle(sample_lifecycle()),
Some("x")
)));
}
#[test]
fn filter_by_source() {
let f = Filter {
source: Some(HarnessSource::Mpm),
..Default::default()
};
let mut ev = envelope(HarnessPayload::Ping, None);
ev.source = HarnessSource::Mpm;
assert!(f.matches(&ev));
ev.source = HarnessSource::Agents;
assert!(!f.matches(&ev));
}
#[test]
fn filter_by_session() {
let f = Filter {
session: Some("sess-7".into()),
..Default::default()
};
assert!(f.matches(&envelope(HarnessPayload::Ping, Some("sess-7"))));
assert!(!f.matches(&envelope(HarnessPayload::Ping, Some("other"))));
assert!(!f.matches(&envelope(HarnessPayload::Ping, None)));
}
#[test]
fn filter_by_domain() {
let f = Filter {
domains: Some(vec!["hook", "ping"]),
..Default::default()
};
assert!(f.matches(&envelope(HarnessPayload::Ping, None)));
assert!(f.matches(&envelope(
HarnessPayload::Hook {
kind: "k".into(),
data: json!({})
},
None
)));
assert!(!f.matches(&envelope(
HarnessPayload::Lifecycle(sample_lifecycle()),
Some("x")
)));
}
#[test]
fn filter_combination() {
let f = Filter {
source: Some(HarnessSource::Code),
session: Some("s".into()),
domains: Some(vec!["lifecycle"]),
};
let mut ev = envelope(HarnessPayload::Lifecycle(sample_lifecycle()), Some("s"));
ev.source = HarnessSource::Code;
assert!(f.matches(&ev));
ev.source = HarnessSource::Mpm;
assert!(!f.matches(&ev));
}
const MODULE_SOURCES: &[(&str, &str)] = &[
("control_bus/mod.rs", include_str!("mod.rs")),
("control_bus/lifecycle.rs", include_str!("lifecycle.rs")),
("control_bus/envelope.rs", include_str!("envelope.rs")),
("control_bus/filter.rs", include_str!("filter.rs")),
("control_bus/tests.rs", include_str!("tests.rs")),
];
const FORBIDDEN_SUBSTRINGS: &[&str] = &[
concat!("broadcast", "::"),
concat!("Once", "Lock"),
concat!("tokio", "::", "sync"),
concat!("lazy_", "static!"),
concat!("once_", "cell"),
];
fn strip_leading_pub(trimmed: &str) -> &str {
let Some(rest) = trimmed.strip_prefix("pub") else {
return trimmed;
};
if let Some(after_paren) = rest.strip_prefix('(') {
match after_paren.find(')') {
Some(close) => after_paren[close + 1..].trim_start(),
None => rest, }
} else if rest.starts_with(char::is_whitespace) || rest.is_empty() {
rest.trim_start()
} else {
trimmed
}
}
#[test]
fn control_bus_declares_no_transport() {
for (name, src) in MODULE_SOURCES {
for needle in FORBIDDEN_SUBSTRINGS {
assert!(
!src.contains(needle),
"{name} contains `{needle}`: control_bus holds event TYPES only \
— the bus lives in trusty-console (#6846)"
);
}
for (idx, line) in src.lines().enumerate() {
let candidate = strip_leading_pub(line.trim_start());
assert!(
!(candidate.starts_with("static ") || candidate.starts_with("static mut ")),
"{}:{} declares a global `static`: control_bus holds event TYPES \
only — no global state (#6846)\n {line}",
name,
idx + 1
);
}
}
}
#[test]
fn static_scan_catches_every_visibility_form() {
let is_static_declaration = |line: &str| -> bool {
let candidate = strip_leading_pub(line.trim_start());
candidate.starts_with("static ") || candidate.starts_with("static mut ")
};
assert!(
is_static_declaration("pub(crate) static X: u8 = 0;"),
"`pub(crate) static` must be detected as a static declaration"
);
assert!(
is_static_declaration("static mut Y: u8 = 0;"),
"`static mut` with no visibility qualifier must be detected"
);
assert!(
!is_static_declaration("let s: &'static str = \"\";"),
"`&'static` in a type position must not be flagged as a static declaration"
);
}
#[test]
fn module_source_scan_covers_every_submodule() {
let mod_rs = include_str!("mod.rs");
let declared: Vec<&str> = mod_rs
.lines()
.map(str::trim)
.filter_map(|l| {
l.strip_prefix("mod ")
.or_else(|| l.strip_prefix("pub mod "))
})
.filter_map(|rest| rest.strip_suffix(';'))
.collect();
assert!(
!declared.is_empty(),
"found no `mod` declarations in control_bus/mod.rs — the parser above is \
out of date, which would make the transport scan vacuous"
);
for name in &declared {
let expected = format!("control_bus/{name}.rs");
assert!(
MODULE_SOURCES.iter().any(|(n, _)| *n == expected),
"control_bus/mod.rs declares `mod {name};` but MODULE_SOURCES has no \
row for {expected} — add one so the transport scan covers it"
);
}
for expected in ["control_bus/mod.rs", "control_bus/tests.rs"] {
assert!(
MODULE_SOURCES.iter().any(|(n, _)| *n == expected),
"MODULE_SOURCES is missing {expected}"
);
}
}