use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::Command;
fn supervisor_exe() -> PathBuf {
if let Some(p) = std::env::var_os("CARGO_BIN_EXE_cellos_supervisor") {
return PathBuf::from(p);
}
let root = Path::new(env!("CARGO_MANIFEST_DIR"))
.parent()
.and_then(|p| p.parent())
.expect("cellos-supervisor crate under workspace root");
let profile = std::env::var("PROFILE").unwrap_or_else(|_| "debug".into());
let bin_name = format!("cellos-supervisor{}", std::env::consts::EXE_SUFFIX);
root.join("target").join(profile).join(bin_name)
}
#[test]
fn validate_mode_prints_summary_and_skips_workload_execution() {
let dir = tempfile::tempdir().expect("tempdir");
let spec_path = dir.path().join("spec-validate-ok.json");
let spec = r#"{
"apiVersion": "cellos.io/v1",
"kind": "ExecutionCell",
"spec": {
"id": "t-validate-ok",
"authority": {
"secretRefs": []
},
"lifetime": {"ttlSeconds": 60},
"run": {
"secretDelivery": "env","argv": ["definitely-not-a-real-binary-cellos-validate-test"]}
}
}"#;
let mut f = File::create(&spec_path).expect("create spec");
f.write_all(spec.as_bytes()).expect("write spec");
drop(f);
let output = Command::new(supervisor_exe())
.env("CELLOS_DEPLOYMENT_PROFILE", "portable")
.env("CELL_OS_USE_NOOP_SINK", "1")
.arg("--validate")
.arg(&spec_path)
.output()
.expect("spawn supervisor --validate");
assert!(
output.status.success(),
"--validate should succeed, stderr={}",
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("\"mode\": \"validate\""),
"expected JSON validate summary, got stdout={stdout}"
);
assert!(
stdout.contains("\"specId\": \"t-validate-ok\""),
"summary should include spec id, stdout={stdout}"
);
}
#[test]
fn validate_mode_enforces_authority_derivation_requirement() {
let dir = tempfile::tempdir().expect("tempdir");
let spec_path = dir.path().join("spec-validate-derivation-missing.json");
let spec = r#"{
"apiVersion": "cellos.io/v1",
"kind": "ExecutionCell",
"spec": {
"id": "t-validate-missing-derivation",
"authority": {
"egressRules": [
{"host": "example.com", "port": 443, "protocol": "tls"}
]
},
"lifetime": {"ttlSeconds": 60},
"run": {
"secretDelivery": "env","argv": ["cargo", "--version"]}
}
}"#;
let mut f = File::create(&spec_path).expect("create spec");
f.write_all(spec.as_bytes()).expect("write spec");
drop(f);
let output = Command::new(supervisor_exe())
.env("CELLOS_DEPLOYMENT_PROFILE", "portable")
.env("CELL_OS_USE_NOOP_SINK", "1")
.env("CELLOS_REQUIRE_AUTHORITY_DERIVATION", "1")
.arg("--validate")
.arg(&spec_path)
.output()
.expect("spawn supervisor --validate");
assert!(
!output.status.success(),
"--validate should fail when derivation is required but missing"
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("authorityDerivation"),
"expected derivation requirement error in stderr, got={stderr}"
);
}