use std::fs;
use std::path::{Path, PathBuf};
fn crate_src() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src")
}
fn collect_rs_files(dir: &Path, out: &mut Vec<PathBuf>) {
let Ok(entries) = fs::read_dir(dir) else {
return;
};
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
collect_rs_files(&path, out);
} else if path.extension().and_then(|e| e.to_str()) == Some("rs") {
out.push(path);
}
}
}
fn is_prose_mention(line: &str) -> bool {
let t = line.trim_start();
t.starts_with("//")
|| t.starts_with("///")
|| t.starts_with("//!")
|| t.starts_with("#[")
|| t.starts_with("note =")
|| t.contains("\"") && !t.contains("tokio::spawn(") && !t.contains("spawn_blocking(")
}
fn is_documented_exception(rel: &str, line: &str) -> bool {
if is_prose_mention(line) {
return true;
}
if rel.contains("sticky_cancel.rs") {
return true;
}
false
}
fn read_proof_text(root: &Path, rel: &str) -> String {
let path = root.join(rel);
if rel == "src/transaction/lifecycle/tests.rs" || rel.ends_with("lifecycle/tests.rs") {
let dir = root.join("src/transaction/lifecycle/tests");
assert!(
dir.is_dir(),
"lifecycle tests must be composed under src/transaction/lifecycle/tests/ (LOC split)"
);
let mut files = Vec::new();
collect_rs_files(&dir, &mut files);
files.sort();
assert!(
!files.is_empty(),
"expected .rs files under src/transaction/lifecycle/tests/"
);
let mut corpus = String::new();
for f in files {
corpus.push_str(
&fs::read_to_string(&f).unwrap_or_else(|e| panic!("read {}: {e}", f.display())),
);
corpus.push('\n');
}
return corpus;
}
assert!(path.is_file(), "missing limit-proof file {rel}");
fs::read_to_string(&path).unwrap_or_else(|e| panic!("read {rel}: {e}"))
}
#[test]
fn s23_no_undocumented_ambient_tokio_spawn_in_production_src() {
let root = crate_src();
let mut files = Vec::new();
collect_rs_files(&root, &mut files);
assert!(!files.is_empty(), "expected monoloop-loop src files");
let mut hits = Vec::new();
for path in &files {
let rel = path
.strip_prefix(&root)
.map(|p| p.to_string_lossy().replace('\\', "/"))
.unwrap_or_else(|_| path.display().to_string());
if rel.contains("lifecycle/tests.rs") || rel.contains("lifecycle/tests/") {
continue;
}
let Ok(text) = fs::read_to_string(path) else {
continue;
};
for (idx, line) in text.lines().enumerate() {
if !(line.contains("tokio::spawn") || line.contains("spawn_blocking")) {
continue;
}
if is_documented_exception(&rel, line) {
continue;
}
hits.push(format!("{rel}:{}: {}", idx + 1, line.trim()));
}
}
assert!(
hits.is_empty(),
"undocumented ambient spawn in production src (§21 / §23):\n{}",
hits.join("\n")
);
}
#[test]
fn s23_exact_limit_plus_one_inventory_present() {
let root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let workspace = root
.parent()
.and_then(|p| p.parent())
.expect("crate dir under workspace");
let matrix = workspace.join("doc/S23_PUBLIC_LIMIT_MATRIX.md");
assert!(
matrix.is_file(),
"missing doc/S23_PUBLIC_LIMIT_MATRIX.md for §23 public-limit honesty"
);
let matrix_text =
fs::read_to_string(&matrix).unwrap_or_else(|e| panic!("read limit matrix: {e}"));
for field in [
"max_active_transactions",
"max_active_per_channel",
"max_actor_commands",
"max_actor_command_bytes",
"max_event_queue",
"max_event_queue_bytes",
"max_input_bytes",
"max_messages",
"max_content_parts",
"max_tools_per_transaction",
"max_tool_schema_bytes",
"max_tool_payload_bytes",
"max_tool_output_bytes",
"max_concurrent_tools_per_transaction",
"max_queued_tools_per_transaction",
"max_continuations",
"max_provider_exchanges",
"max_continuation_context_bytes",
"max_total_provider_input_bytes",
"max_total_provider_output_bytes",
"max_diagnostic_count",
"max_diagnostic_bytes",
"transaction_deadline",
"cleanup_deadline",
"terminal_event_delivery_deadline",
"callback_deadline",
] {
assert!(
matrix_text.contains(field),
"S23_PUBLIC_LIMIT_MATRIX.md must name TransactionLimits field `{field}`"
);
}
let required = [
("tests/linked_tools.rs", "capacity_limit_plus_one_rejects"),
(
"tests/linked_tools.rs",
"max_tool_output_bytes_plus_one_fails_closed",
),
(
"tests/linked_tools.rs",
"transaction_limits_max_concurrent_tools_plus_one_rejects",
),
(
"tests/linked_tools.rs",
"transaction_limits_max_queued_tools_plus_one_rejects",
),
(
"tests/direct_llm_fake_e2e.rs",
"fake_transaction_limits_max_tool_output_bytes_plus_one_fails_closed",
),
(
"tests/direct_llm_fake_e2e.rs",
"fake_transaction_limits_max_tool_payload_bytes_plus_one_rejects",
),
("tests/mcp_gateway.rs", "http_oversized_body_fails_closed"),
(
"tests/mcp_gateway.rs",
"mcp_per_capability_concurrency_plus_one_rejects",
),
(
"tests/mcp_gateway.rs",
"mcp_global_concurrency_plus_one_rejects",
),
(
"tests/mcp_gateway.rs",
"mcp_request_duration_plus_one_fails_closed",
),
(
"src/transaction/lifecycle/tests.rs",
"transaction_limits_max_actor_commands_plus_one_rejects",
),
(
"src/transaction/lifecycle/tests.rs",
"transaction_limits_terminal_event_delivery_deadline_seal_fails_closed",
),
(
"src/transaction/lifecycle/tests.rs",
"transaction_limits_transaction_deadline_hang_ends_deadline_exceeded",
),
(
"src/transaction/lifecycle/tests.rs",
"transaction_limits_max_tool_schema_bytes_exact_admits_plus_one_rejects",
),
(
"src/transaction/lifecycle/tests.rs",
"transaction_limits_max_event_queue_exact_admits_plus_one_rejects",
),
(
"src/transaction/lifecycle/tests.rs",
"transaction_limits_max_event_queue_bytes_exact_admits_plus_one_rejects",
),
(
"src/transaction/lifecycle/tests.rs",
"s22_6_event_byte_plus_one_fails_closed",
),
(
"src/transaction/lifecycle/tests.rs",
"s22_6_event_item_plus_one_fails_closed",
),
(
"src/transaction/lifecycle/tests.rs",
"d047_full_queue_seal_reports_deadline_not_published",
),
(
"src/transaction/owned_process_registry.rs",
"registry_retains_until_reap_then_empties",
),
(
"src/transaction/lifecycle/tests.rs",
"wait_stopped_times_out_during_executor_teardown_then_completes",
),
(
"src/transaction/lifecycle/tests.rs",
"capacity_plus_one_rejects",
),
(
"src/transaction/lifecycle/tests.rs",
"max_distinct_sessions_exact_admits_plus_one_rejects",
),
(
"src/transaction/lifecycle/tests.rs",
"external_agent_claim_time_distinct_sessions_plus_one_limit_exceeded",
),
(
"src/transaction/lifecycle/tests.rs",
"concurrent_global_capacity_exhaustion_admits_exactly_max",
),
(
"src/transaction/lifecycle/tests.rs",
"concurrent_per_channel_capacity_exhaustion_admits_exactly_channel_max",
),
(
"src/transaction/lifecycle/tests.rs",
"start_queue_full_rolls_back_all_permits",
),
(
"../monoloop-connector/tests/streaming_http.rs",
"absolute_request_deadline_covers_header_and_body_delay",
),
(
"../monoloop-connector/tests/streaming_http.rs",
"full_output_queue_terminates_at_overall_deadline",
),
(
"../monoloop-connector/tests/streaming_http.rs",
"max_queued_output_bytes_plus_one_fails_closed",
),
(
"../monoloop-connector/tests/streaming_http.rs",
"blocked_enqueue_honors_idle_before_overall_deadline",
),
(
"src/transaction/lifecycle/tests.rs",
"max_messages_plus_one_rejected_at_admit",
),
(
"src/transaction/lifecycle/tests.rs",
"max_messages_exact_admits_plus_one_rejects",
),
(
"src/transaction/lifecycle/tests.rs",
"submit_versus_shutdown_barrier_race_two_outcomes",
),
(
"src/transaction/lifecycle/tests.rs",
"submit_versus_shutdown_hang_barrier_both_outcomes",
),
(
"src/transaction/lifecycle/tests.rs",
"max_input_bytes_plus_one_rejected_at_admit",
),
(
"src/transaction/lifecycle/tests.rs",
"max_content_parts_plus_one_rejected_at_admit",
),
(
"src/transaction/lifecycle/tests.rs",
"max_content_parts_exact_admits_plus_one_rejects",
),
(
"src/transaction/lifecycle/tests.rs",
"max_tools_per_transaction_exact_admits_plus_one_rejects",
),
(
"src/transaction/lifecycle/tests.rs",
"max_input_bytes_exact_admits_plus_one_rejects",
),
(
"src/transaction/lifecycle/tests.rs",
"multi_channel_multi_session_concurrent_load",
),
(
"src/transaction/lifecycle/tests.rs",
"concurrent_hang_terminate_storm_all_cancelled",
),
(
"src/transaction/lifecycle/tests.rs",
"concurrent_hang_force_terminate_storm_all_terminated",
),
(
"src/transaction/lifecycle/tests.rs",
"duplicate_session_race_admits_exactly_one",
),
(
"../monoloop-connector-grok/tests/grok_connector.rs",
"concurrent_session_new_and_explicit_load",
),
(
"src/transaction/lifecycle/tests.rs",
"large_tool_arguments_counted_toward_max_input_bytes",
),
(
"../monoloop-contracts/src/input.rs",
"estimate_counts_names_ids_and_tool_arguments",
),
(
"src/transaction/lifecycle/tests.rs",
"runtime_owner_drop_joins_executor_thread_reaches_stopped",
),
(
"../monoloop-connector/tests/streaming_http.rs",
"cancel_interrupts_blocked_output_enqueue",
),
(
"src/transaction/lifecycle/tests.rs",
"s22_6_concurrent_producers_contiguous_sequence",
),
(
"tests/direct_llm_fake_e2e.rs",
"fake_inline_max_continuations_zero_ends_limit_exceeded",
),
(
"tests/direct_llm_fake_e2e.rs",
"fake_inline_max_continuations_one_exhausted_ends_limit_exceeded",
),
(
"tests/direct_llm_fake_e2e.rs",
"fake_inline_max_provider_exchanges_one_ends_limit_exceeded",
),
(
"tests/direct_llm_fake_e2e.rs",
"fake_inline_max_provider_exchanges_two_exact_then_limit_exceeded",
),
(
"tests/direct_llm_fake_e2e.rs",
"fake_inline_continuation_context_bytes_limit_exceeded",
),
(
"tests/direct_llm_fake_e2e.rs",
"fake_total_provider_input_bytes_limit_exceeded_before_open",
),
(
"tests/direct_llm_fake_e2e.rs",
"fake_total_provider_output_bytes_limit_exceeded",
),
(
"tests/direct_llm_fake_e2e.rs",
"fake_inline_cumulative_output_budget_plus_one_fails_second_pump",
),
(
"tests/direct_llm_openai_e2e.rs",
"http_inline_max_continuations_zero_ends_limit_exceeded",
),
(
"tests/direct_llm_openai_e2e.rs",
"http_inline_cumulative_output_budget_plus_one_fails_second_pump",
),
(
"../monoloop-testkit/tests/profile_bindings.rs",
"MUST NOT declare Refreshable",
),
];
for (rel, needle) in required {
let text = read_proof_text(&root, rel);
assert!(
text.contains(needle),
"limit-proof `{needle}` missing from {rel}"
);
}
}
#[test]
fn s23_lifecycle_tests_composed_under_loc_threshold() {
let dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src/transaction/lifecycle/tests");
assert!(
dir.is_dir(),
"lifecycle tests must be a composed directory (not a single tests.rs monolith)"
);
let legacy =
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src/transaction/lifecycle/tests.rs");
assert!(
!legacy.is_file(),
"lifecycle/tests.rs monolith must not return; keep proofs under lifecycle/tests/"
);
const MAX_LOC: usize = 3000;
let mut files = Vec::new();
collect_rs_files(&dir, &mut files);
assert!(
!files.is_empty(),
"expected composed lifecycle test modules"
);
let mut offenders = Vec::new();
for path in files {
let text =
fs::read_to_string(&path).unwrap_or_else(|e| panic!("read {}: {e}", path.display()));
let loc = text.lines().count();
if loc > MAX_LOC {
offenders.push(format!("{}: {loc} LOC", path.display()));
}
}
assert!(
offenders.is_empty(),
"lifecycle test module(s) exceed {MAX_LOC} LOC — prefer further composition:\n{}",
offenders.join("\n")
);
}
#[test]
fn s23_race_load_inventory_present() {
let root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let workspace = root
.parent()
.and_then(|p| p.parent())
.expect("crate dir under workspace");
let inv = workspace.join("doc/S23_RACE_LOAD_INVENTORY.md");
assert!(
inv.is_file(),
"missing doc/S23_RACE_LOAD_INVENTORY.md for §23 named race/load honesty"
);
let inv_text = fs::read_to_string(&inv).unwrap_or_else(|e| panic!("read race inventory: {e}"));
for needle in [
"concurrent_global_capacity_exhaustion_admits_exactly_max",
"concurrent_per_channel_capacity_exhaustion_admits_exactly_channel_max",
"multi_channel_multi_session_concurrent_load",
"submit_versus_shutdown_barrier_race_two_outcomes",
"submit_versus_shutdown_hang_barrier_both_outcomes",
"submit_versus_begin_shutdown_two_outcomes",
"duplicate_session_race_admits_exactly_one",
"concurrent_hang_terminate_storm_all_cancelled",
"concurrent_hang_force_terminate_storm_all_terminated",
"concurrent_hang_cancel_versus_force_terminate_one_terminal",
] {
assert!(
inv_text.contains(needle),
"S23_RACE_LOAD_INVENTORY.md must name race needle `{needle}`"
);
}
let life_text = read_proof_text(&root, "src/transaction/lifecycle/tests.rs");
for needle in [
"concurrent_hang_terminate_storm_all_cancelled",
"concurrent_hang_force_terminate_storm_all_terminated",
"concurrent_hang_cancel_versus_force_terminate_one_terminal",
"multi_channel_multi_session_concurrent_load",
"submit_versus_begin_shutdown_two_outcomes",
"submit_versus_shutdown_barrier_race_two_outcomes",
"submit_versus_shutdown_hang_barrier_both_outcomes",
"duplicate_session_race_admits_exactly_one",
"concurrent_global_capacity_exhaustion_admits_exactly_max",
"concurrent_per_channel_capacity_exhaustion_admits_exactly_channel_max",
] {
assert!(
life_text.contains(needle),
"lifecycle tests missing race needle `{needle}`"
);
}
}
#[test]
fn s23_adversarial_host_adapter_suite_present() {
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/s22_7_host_adapters.rs");
assert!(
path.is_file(),
"expected tests/s22_7_host_adapters.rs for §22.7 adversarial host proofs"
);
let text = fs::read_to_string(&path).expect("read s22_7");
for needle in [
"s22_7_completion_callback_blocks_before_future",
"s22_7_completion_future_never_yields",
"s22_7_event_consumer_stops_draining",
"s22_7_receivers_dropped_immediately",
"s22_7_host_adapter_task_destroyed",
] {
assert!(
text.contains(needle),
"s22_7 suite missing proof `{needle}`"
);
}
}
#[test]
fn s23_adversarial_lifecycle_subprocess_harness_inventory() {
let root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
{
let path = root.join("tests/s22_4_join_only_spill_sacrificial.rs");
let text = fs::read_to_string(&path).expect("read join_only sacrificial");
assert!(
text.contains("owned_tasks"),
"JoinOnly sacrificial must assert TaskSupervisor owned_tasks"
);
assert!(
!text.contains("spill_pending="),
"JoinOnly sacrificial must not require spill_pending (M5.4 delete-vaults)"
);
}
let harnesses = [
(
"tests/s22_3_non_yielding_sacrificial.rs",
"s22_3_non_yielding_sacrificial_never_false_stopped",
"MONOLOOP_S22_3_NON_YIELDING_CHILD",
"recv_timeout",
),
(
"tests/s22_4_join_only_spill_sacrificial.rs",
"s22_4_join_only_spill_sacrificial_never_false_stopped",
"MONOLOOP_S22_4_JOIN_ONLY_SPILL_CHILD",
"recv_timeout",
),
(
"tests/d048_process_isolated_sacrificial.rs",
"d048_process_isolated_sacrificial_abort_park_then_pid_not_waitable",
"MONOLOOP_D048_PROCESS_ISOLATED_CHILD",
"recv_timeout",
),
];
for (rel, test_fn, child_env, timeout_api) in harnesses {
let path = root.join(rel);
assert!(path.is_file(), "missing subprocess harness file {rel}");
let text = fs::read_to_string(&path).unwrap_or_else(|e| panic!("read {rel}: {e}"));
assert!(
text.contains(test_fn),
"harness `{rel}` missing test `{test_fn}`"
);
assert!(
text.contains(child_env),
"harness `{rel}` missing child env `{child_env}`"
);
assert!(
text.contains(timeout_api),
"harness `{rel}` must bound the parent wait with `{timeout_api}`"
);
assert!(
text.contains("child.kill()") || text.contains("child.kill();"),
"harness `{rel}` must kill the sacrificial child"
);
assert!(
text.contains("never false") || text.contains("false Stopped"),
"harness `{rel}` must document fail-closed / never-false-Stopped intent"
);
}
}