use cellos_core::ExecutionCellDocument;
#[test]
fn execution_cell_minimal_example() {
let raw = include_str!("../../../contracts/examples/execution-cell-minimal.valid.json");
let doc: ExecutionCellDocument = serde_json::from_str(raw).expect("parse");
assert_eq!(doc.api_version, "cellos.io/v1");
assert_eq!(doc.kind, "ExecutionCell");
assert_eq!(doc.spec.id, "demo-cell-001");
assert!(doc.spec.correlation.is_none());
let again = serde_json::to_string(&doc).expect("serialize");
let doc2: ExecutionCellDocument = serde_json::from_str(&again).expect("re-parse");
assert_eq!(doc2.spec.id, doc.spec.id);
}
#[test]
fn execution_cell_with_command_example() {
use cellos_core::validate_execution_cell_document;
let raw = include_str!("../../../contracts/examples/execution-cell-with-command.valid.json");
let doc: ExecutionCellDocument = serde_json::from_str(raw).expect("parse");
validate_execution_cell_document(&doc).expect("valid spec");
assert!(doc.spec.run.is_some());
}
#[test]
fn execution_cell_with_run_limits_example() {
use cellos_core::validate_execution_cell_document;
let raw = include_str!("../../../contracts/examples/execution-cell-with-run-limits.valid.json");
let doc: ExecutionCellDocument = serde_json::from_str(raw).expect("parse");
validate_execution_cell_document(&doc).expect("valid spec");
let run = doc.spec.run.as_ref().expect("run");
assert_eq!(run.timeout_ms, Some(30_000));
let limits = run.limits.as_ref().expect("limits");
assert_eq!(limits.memory_max_bytes, Some(268_435_456));
let cpu = limits.cpu_max.as_ref().expect("cpu max");
assert_eq!(cpu.quota_micros, 50_000);
assert_eq!(cpu.period_micros, Some(100_000));
}
#[test]
fn execution_cell_ci_correlation_example() {
let raw = include_str!("../../../contracts/examples/execution-cell-ci-correlation.valid.json");
let doc: ExecutionCellDocument = serde_json::from_str(raw).expect("parse");
let c = doc.spec.correlation.as_ref().expect("correlation");
assert_eq!(c.platform.as_deref(), Some("github"));
assert_eq!(c.external_run_id.as_deref(), Some("123456789"));
assert!(c.labels.as_ref().unwrap().contains_key("repository"));
let ingress = doc.spec.ingress.as_ref().expect("ingress");
assert!(ingress.git.is_some());
assert!(ingress
.oci_image
.as_ref()
.unwrap()
.reference
.contains("ghcr.io"));
let again = serde_json::to_string(&doc).expect("serialize");
let doc2: ExecutionCellDocument = serde_json::from_str(&again).expect("re-parse");
assert_eq!(doc2.spec.policy, doc.spec.policy);
}
#[test]
fn execution_cell_github_oidc_s3_example() {
use cellos_core::{validate_execution_cell_document, ExportTarget, WorkloadIdentityKind};
let raw = include_str!("../../../contracts/examples/execution-cell-github-oidc-s3.valid.json");
let doc: ExecutionCellDocument = serde_json::from_str(raw).expect("parse");
validate_execution_cell_document(&doc).expect("valid spec");
let identity = doc.spec.identity.as_ref().expect("identity");
assert_eq!(identity.kind, WorkloadIdentityKind::FederatedOidc);
assert_eq!(identity.provider, "github-actions");
assert_eq!(identity.secret_ref, "AWS_WEB_IDENTITY");
let export = doc.spec.export.as_ref().expect("export");
let targets = export.targets.as_ref().expect("targets");
match &targets[0] {
ExportTarget::S3(target) => {
assert_eq!(target.name, "artifact-bucket");
assert_eq!(target.bucket, "acme-cellos-artifacts");
}
other => panic!("unexpected target variant: {other:?}"),
}
assert_eq!(
export.artifacts.as_ref().unwrap()[0].target.as_deref(),
Some("artifact-bucket")
);
}
#[test]
fn execution_cell_github_oidc_multi_export_example() {
use cellos_core::{validate_execution_cell_document, ExportTarget, WorkloadIdentityKind};
let raw = include_str!(
"../../../contracts/examples/execution-cell-github-oidc-multi-export.valid.json"
);
let doc: ExecutionCellDocument = serde_json::from_str(raw).expect("parse");
validate_execution_cell_document(&doc).expect("valid spec");
let identity = doc.spec.identity.as_ref().expect("identity");
assert_eq!(identity.kind, WorkloadIdentityKind::FederatedOidc);
let export = doc.spec.export.as_ref().expect("export");
let targets = export.targets.as_ref().expect("targets");
assert_eq!(targets.len(), 2);
match &targets[0] {
ExportTarget::S3(target) => {
assert_eq!(target.name, "artifact-bucket");
assert_eq!(target.bucket, "acme-cellos-artifacts");
}
other => panic!("unexpected target variant: {other:?}"),
}
match &targets[1] {
ExportTarget::Http(target) => {
assert_eq!(target.name, "artifact-api");
assert_eq!(target.base_url, "https://artifacts.acme.internal/upload");
assert_eq!(target.secret_ref.as_deref(), Some("ARTIFACT_API_TOKEN"));
}
other => panic!("unexpected target variant: {other:?}"),
}
let artifacts = export.artifacts.as_ref().expect("artifacts");
assert_eq!(artifacts[0].target.as_deref(), Some("artifact-bucket"));
assert_eq!(artifacts[1].target.as_deref(), Some("artifact-api"));
}
#[test]
fn execution_cell_with_environment_example() {
use cellos_core::validate_execution_cell_document;
let raw =
include_str!("../../../contracts/examples/execution-cell-with-environment.valid.json");
let doc: ExecutionCellDocument = serde_json::from_str(raw).expect("parse");
validate_execution_cell_document(&doc).expect("valid spec");
let env = doc.spec.environment.as_ref().expect("environment");
assert_eq!(env.image_reference, "ubuntu:24.04");
assert!(env.image_digest.as_deref().unwrap().starts_with("sha256:"));
assert_eq!(env.template_id.as_deref(), Some("ubuntu-24-04-build"));
let again = serde_json::to_string(&doc).expect("serialize");
let doc2: ExecutionCellDocument = serde_json::from_str(&again).expect("re-parse");
assert_eq!(doc2.spec.environment, doc.spec.environment);
}
#[test]
fn execution_cell_runtime_leased_secret_broker_example() {
use cellos_core::{validate_execution_cell_document, SecretDeliveryMode};
let raw = include_str!(
"../../../contracts/examples/execution-cell-runtime-leased-secret-broker.valid.json"
);
let doc: ExecutionCellDocument = serde_json::from_str(raw).expect("parse");
validate_execution_cell_document(&doc).expect("valid spec");
let run = doc.spec.run.as_ref().expect("run");
assert_eq!(run.secret_delivery, SecretDeliveryMode::RuntimeLeasedBroker);
}
#[test]
fn execution_cell_with_telemetry_example() {
use cellos_core::{validate_execution_cell_document, TelemetryChannel};
let raw = include_str!("../../../contracts/examples/execution-cell-with-telemetry.valid.json");
let doc: ExecutionCellDocument = serde_json::from_str(raw).expect("parse");
validate_execution_cell_document(&doc).expect("valid spec");
let telemetry = doc.spec.telemetry.as_ref().expect("telemetry");
assert_eq!(telemetry.channel, TelemetryChannel::VsockCbor);
assert!(telemetry
.events
.iter()
.any(|e| e.starts_with("net.connect")));
assert_eq!(telemetry.agent_version, "1.0.0");
let limits = telemetry.rate_limits.as_ref().expect("rateLimits");
assert_eq!(limits.events_per_second, Some(64));
let split = telemetry
.host_vs_guest_fields
.as_ref()
.expect("hostVsGuestFields");
assert!(split.host_fields.iter().any(|f| f == "runId"));
assert!(split.guest_fields.iter().any(|f| f == "pid"));
let again = serde_json::to_string(&doc).expect("serialize");
let doc2: ExecutionCellDocument = serde_json::from_str(&again).expect("re-parse");
assert_eq!(doc2.spec.id, doc.spec.id);
assert_eq!(
doc2.spec.telemetry.as_ref().unwrap().agent_version,
telemetry.agent_version
);
}
#[test]
fn ci_runner_policy_example_parses_and_validates() {
use cellos_core::{validate_policy_pack_document, PolicyPackDocument};
let raw = include_str!("../../../contracts/examples/ci-runner-policy.valid.json");
let doc: PolicyPackDocument = serde_json::from_str(raw).expect("parse");
validate_policy_pack_document(&doc).expect("valid policy pack");
assert_eq!(doc.api_version, "cellos.io/v1");
assert_eq!(doc.kind, "PolicyPack");
assert_eq!(doc.spec.id, "ci-runner-standard");
assert_eq!(doc.spec.rules.max_lifetime_ttl_seconds, Some(3600));
assert!(doc.spec.rules.require_egress_declared);
assert!(doc.spec.rules.require_runtime_secret_delivery);
assert!(doc.spec.rules.require_resource_limits);
assert_eq!(doc.spec.rules.allowed_egress_hosts.len(), 4);
let again = serde_json::to_string(&doc).expect("serialize");
let doc2: PolicyPackDocument = serde_json::from_str(&again).expect("re-parse");
assert_eq!(doc2.spec.id, doc.spec.id);
assert_eq!(
doc2.spec.rules.max_lifetime_ttl_seconds,
doc.spec.rules.max_lifetime_ttl_seconds
);
}
#[test]
fn evidence_bundle_valid_fixture_has_required_fields() {
let raw = include_str!("../../../contracts/examples/evidence-bundle-data.valid.json");
let v: serde_json::Value = serde_json::from_str(raw).expect("parse");
let obj = v.as_object().expect("evidence bundle is object");
assert!(
obj.contains_key("specSignatureHash"),
"valid fixture must carry specSignatureHash (ADR-0006 §6)"
);
assert!(
obj.contains_key("cellDestroyedEventRef"),
"valid fixture must carry cellDestroyedEventRef (D5 destruction gate)"
);
assert!(obj.contains_key("residueClass"));
}
#[test]
fn evidence_bundle_invalid_fixture_is_missing_spec_signature_hash() {
let raw = include_str!("../../../contracts/examples/evidence-bundle.invalid.json");
let v: serde_json::Value = serde_json::from_str(raw).expect("parse");
let obj = v.as_object().expect("evidence bundle is object");
assert!(
!obj.contains_key("specSignatureHash"),
"negative fixture must NOT carry specSignatureHash — this is the \
property the schema gate (and tests/residue.rs) rejects"
);
}
#[test]
fn evidence_bundle_emitted_data_v1_emits_required_fields() {
use cellos_core::{
evidence_bundle_emitted_data_v1, EvidenceBundleRefs, ExecutionCellDocument, ResidueClass,
};
let raw = include_str!("../../../contracts/examples/execution-cell-minimal.valid.json");
let doc: ExecutionCellDocument = serde_json::from_str(raw).expect("parse");
let refs = EvidenceBundleRefs {
started_event_ref: "urn:cellos:event:started",
cell_destroyed_event_ref: "urn:cellos:event:destroyed",
..EvidenceBundleRefs::default()
};
let v = evidence_bundle_emitted_data_v1(
&doc.spec,
"cell-1",
Some("run-1"),
"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
1_714_972_810_000,
ResidueClass::None,
&refs,
)
.expect("build evidence_bundle data");
let obj = v.as_object().expect("data is object");
assert!(obj.contains_key("specSignatureHash"));
assert_eq!(
obj.get("cellDestroyedEventRef").and_then(|x| x.as_str()),
Some("urn:cellos:event:destroyed")
);
assert_eq!(
obj.get("residueClass").and_then(|x| x.as_str()),
Some("none")
);
}