#![allow(clippy::expect_used, clippy::panic, clippy::wildcard_enum_match_arm)]
use std::path::{Path, PathBuf};
use std::process::Command;
use std::time::Duration;
use lean_rs::LeanBuiltCapability;
use lean_rs_worker::{
LeanWorkerBootstrapDiagnosticCode, LeanWorkerCapabilityBuilder, LeanWorkerCapabilityFact,
LeanWorkerCapabilityMetadata, LeanWorkerChild, LeanWorkerCommandMetadata, LeanWorkerError, LeanWorkerRestartPolicy,
};
use serde_json::json;
fn worker_binary() -> PathBuf {
PathBuf::from(env!("CARGO_BIN_EXE_lean-rs-worker-child"))
}
fn workspace_root() -> PathBuf {
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
manifest_dir
.parent()
.and_then(Path::parent)
.expect("crates/<name> lives two directories below the workspace root")
.to_path_buf()
}
fn interop_root() -> PathBuf {
workspace_root().join("fixtures").join("interop-shims")
}
fn shipped_template_root() -> PathBuf {
workspace_root().join("templates").join("shipped-lean-crate")
}
fn shipped_template_manifest() -> PathBuf {
shipped_template_root().join("Cargo.toml")
}
fn build_shipped_template() {
let output = Command::new(std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_owned()))
.args(["build", "--manifest-path"])
.arg(shipped_template_manifest())
.args(["--bins", "--examples"])
.output()
.expect("template cargo build starts");
assert!(
output.status.success(),
"template build failed\nstdout:\n{}\nstderr:\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr),
);
}
fn shipped_manifest_path() -> PathBuf {
build_shipped_template();
let build_dir = shipped_template_root().join("target").join("debug").join("build");
let mut candidates = std::fs::read_dir(&build_dir)
.expect("template build directory exists")
.filter_map(Result::ok)
.map(|entry| entry.path().join("out").join("ShipLeanDemo.lean-rs-capability.json"))
.filter(|path| path.is_file())
.collect::<Vec<_>>();
candidates.sort();
candidates.pop().expect("template build emitted a capability manifest")
}
fn env_exe_name(name: &str) -> String {
let mut name = name.to_owned();
if !std::env::consts::EXE_SUFFIX.is_empty() {
name.push_str(std::env::consts::EXE_SUFFIX);
}
name
}
fn shipped_worker_binary() -> PathBuf {
build_shipped_template();
shipped_template_root()
.join("target")
.join("debug")
.join(env_exe_name("shipped-lean-crate-worker"))
}
fn builder() -> LeanWorkerCapabilityBuilder {
LeanWorkerCapabilityBuilder::new(
interop_root(),
"lean_rs_interop_consumer",
"LeanRsInteropConsumer",
["LeanRsInteropConsumer.Callback"],
)
.worker_executable(worker_binary())
}
#[test]
fn built_capability_builder_infers_lake_root_from_dylib_path() {
let dylib = interop_root()
.join(".lake")
.join("build")
.join("lib")
.join(if cfg!(target_os = "macos") {
"liblean__rs__interop__consumer_LeanRsInteropConsumer.dylib"
} else {
"liblean__rs__interop__consumer_LeanRsInteropConsumer.so"
});
let spec = LeanBuiltCapability::path(&dylib)
.package("lean_rs_interop_consumer")
.module("LeanRsInteropConsumer");
let builder = LeanWorkerCapabilityBuilder::from_built_capability(&spec, ["LeanRsInteropConsumer.Callback"])
.expect("standard Lake dylib path is accepted")
.worker_executable(worker_binary());
assert_eq!(
builder.session_key(),
LeanWorkerCapabilityBuilder::new(
interop_root(),
"lean_rs_interop_consumer",
"LeanRsInteropConsumer",
["LeanRsInteropConsumer.Callback"],
)
.worker_executable(worker_binary())
.session_key(),
);
}
#[test]
fn app_owned_worker_child_locator_accepts_explicit_binary() {
let child = LeanWorkerChild::path(worker_binary());
let mut capability = LeanWorkerCapabilityBuilder::new(
interop_root(),
"lean_rs_interop_consumer",
"LeanRsInteropConsumer",
["LeanRsInteropConsumer.Callback"],
)
.worker_child(child)
.open()
.expect("explicit app-owned worker child opens");
capability.open_session(None, None).expect("session opens");
}
#[test]
fn builder_opens_worker_capability_and_validates_metadata() {
let mut capability = builder()
.validate_metadata(
"lean_rs_interop_consumer_worker_metadata",
json!({"caller": "builder-test"}),
)
.open()
.expect("builder opens capability");
assert!(
capability.dylib_path().is_file(),
"builder should return the built Lake dylib path"
);
assert_eq!(
capability.validated_metadata().map(|metadata| &metadata.commands),
Some(&vec![
LeanWorkerCommandMetadata {
name: "version".to_owned(),
version: "fixture-1".to_owned(),
},
LeanWorkerCommandMetadata {
name: "scan".to_owned(),
version: "fixture-2".to_owned(),
},
]),
);
assert_eq!(capability.runtime_metadata().worker_version, env!("CARGO_PKG_VERSION"));
let mut session = capability
.open_session(None, None)
.expect("session opens after builder");
let metadata = session
.capability_metadata(
"lean_rs_interop_consumer_worker_metadata",
&json!({"caller": "builder-test-second-session"}),
None,
None,
)
.expect("metadata call succeeds through reopened session");
assert_eq!(metadata.commands.len(), 2);
}
#[test]
fn missing_lake_target_is_a_build_error() {
let err = LeanWorkerCapabilityBuilder::new(
interop_root(),
"lean_rs_interop_consumer",
"MissingTarget",
["LeanRsInteropConsumer.Callback"],
)
.worker_executable(worker_binary())
.open()
.expect_err("missing Lake target should fail before worker startup");
match err {
LeanWorkerError::CapabilityBuild { diagnostic } => {
let rendered = diagnostic.to_string();
assert!(
rendered.contains("MissingTarget"),
"diagnostic should name the missing target: {rendered}"
);
}
other => panic!("expected capability build error, got {other:?}"),
}
}
#[test]
fn missing_worker_child_is_a_bootstrap_error() {
let missing = workspace_root().join("target").join("definitely-not-a-worker-child");
let err = builder()
.worker_executable(missing)
.open()
.expect_err("missing worker child should fail before spawn");
match err {
LeanWorkerError::Bootstrap { code, message } => {
assert_eq!(code, LeanWorkerBootstrapDiagnosticCode::WorkerChildNotExecutable);
assert!(message.contains("path does not point to a file"));
}
other => panic!("expected bootstrap child error, got {other:?}"),
}
}
#[test]
fn bootstrap_report_distinguishes_missing_child_without_spawning() {
let report = builder()
.worker_executable(workspace_root().join("target").join("missing-bootstrap-child"))
.check();
let first = report.first_error().expect("missing child is reported");
assert_eq!(
first.code(),
LeanWorkerBootstrapDiagnosticCode::WorkerChildNotExecutable
);
assert!(first.message().contains("path does not point to a file"));
}
#[test]
fn manifest_backed_builder_uses_manifest_capability_identity() {
let spec = LeanBuiltCapability::manifest_path(shipped_manifest_path());
let report = LeanWorkerCapabilityBuilder::from_built_capability(&spec, ["ShipLeanDemo"])
.expect("manifest-backed descriptor creates worker builder")
.worker_child(LeanWorkerChild::path(shipped_worker_binary()))
.check();
assert!(
report.is_ok(),
"manifest-backed shipped worker bootstrap should pass: {report:?}",
);
}
#[test]
fn missing_manifest_is_typed_at_manifest_backed_builder_boundary() {
let missing = std::env::temp_dir()
.join(format!("lean-rs-worker-missing-manifest-{}", std::process::id()))
.join("missing.json");
let err = LeanWorkerCapabilityBuilder::from_built_capability(
&LeanBuiltCapability::manifest_path(missing),
["ShipLeanDemo"],
)
.expect_err("missing manifest should be typed");
match err {
LeanWorkerError::Bootstrap { code, message } => {
assert_eq!(code.as_str(), "lean_rs.loader.missing_manifest");
assert!(message.contains("could not read Lean capability manifest"));
}
other => panic!("expected missing-manifest bootstrap error, got {other:?}"),
}
}
#[test]
fn stale_fingerprint_is_reported_by_bootstrap_preflight() {
let manifest = shipped_manifest_path();
let dir = std::env::temp_dir().join(format!("lean-rs-worker-stale-fingerprint-{}", std::process::id()));
std::fs::create_dir_all(&dir).expect("create temp dir");
let stale = dir.join("ShipLeanDemo.lean-rs-capability.json");
let mut contents: serde_json::Value =
serde_json::from_slice(&std::fs::read(&manifest).expect("read template manifest"))
.expect("template manifest is JSON");
contents
.get_mut("toolchain_fingerprint")
.and_then(serde_json::Value::as_object_mut)
.expect("manifest has fingerprint object")
.insert(
"header_sha256".to_owned(),
serde_json::Value::String("0000000000000000000000000000000000000000000000000000000000000000".to_owned()),
);
std::fs::write(
&stale,
serde_json::to_vec_pretty(&contents).expect("encode stale manifest"),
)
.expect("write stale manifest");
let spec = LeanBuiltCapability::manifest_path(stale);
let report = LeanWorkerCapabilityBuilder::from_built_capability(&spec, ["ShipLeanDemo"])
.expect("manifest still contains capability identity")
.worker_child(LeanWorkerChild::path(shipped_worker_binary()))
.check();
let first = report.first_error().expect("stale fingerprint should be reported");
assert_eq!(
first.code().as_str(),
"lean_rs.loader.unsupported_toolchain_fingerprint"
);
}
#[test]
fn metadata_mismatch_is_reported_by_bootstrap_check() {
let wrong_metadata = LeanWorkerCapabilityMetadata {
commands: vec![LeanWorkerCommandMetadata {
name: "wrong".to_owned(),
version: "0".to_owned(),
}],
capabilities: vec![LeanWorkerCapabilityFact {
name: "wrong-capability".to_owned(),
version: "0".to_owned(),
}],
lean_version: None,
extra: None,
};
let report = builder()
.expect_metadata(
"lean_rs_interop_consumer_worker_metadata",
json!({"caller": "builder-metadata-check"}),
wrong_metadata,
)
.check();
let first = report.first_error().expect("metadata mismatch is reported");
assert_eq!(
first.code(),
LeanWorkerBootstrapDiagnosticCode::CapabilityMetadataMismatch
);
}
#[test]
fn handshake_failure_is_a_bootstrap_diagnostic() {
let shell = PathBuf::from("/bin/sh");
if !shell.is_file() {
return;
}
let report = builder()
.worker_child(LeanWorkerChild::path(shell))
.startup_timeout(Duration::from_millis(50))
.check();
let first = report.first_error().expect("non-worker child fails bootstrap");
assert_eq!(first.code(), LeanWorkerBootstrapDiagnosticCode::WorkerHandshakeFailed);
}
#[test]
fn metadata_validation_failure_is_typed() {
let err = builder()
.validate_metadata(
"lean_rs_interop_consumer_worker_metadata_missing",
json!({"caller": "builder-test"}),
)
.open()
.expect_err("metadata validation should fail when export is missing");
match err {
LeanWorkerError::Worker { code, message } => {
assert_eq!(code, "lean_rs.symbol_lookup");
assert!(
message.contains("lean_rs_interop_consumer_worker_metadata_missing"),
"message should name missing export, got {message}",
);
}
other => panic!("expected worker symbol lookup error, got {other:?}"),
}
}
#[test]
fn restart_policy_override_is_applied_during_builder_startup() {
let capability = builder()
.restart_policy(LeanWorkerRestartPolicy::default().max_requests(1))
.open()
.expect("builder opens capability with restart policy");
let stats = capability.worker().stats();
assert!(
stats.max_request_restarts >= 1,
"health then session-open should trigger the max-request restart policy, stats={stats:?}",
);
}