clusterflux-public/crates/disasmer-sdk/tests/macros.rs
Disasmer release dry run 2bef715211 Public dry run dryrun-20b59dc46b72
Source commit: 20b59dc46b72103c2f8a516c692b5cc3d54fab19

Public tree identity: sha256:aaa5ac7b58b2a0d23c6b11e5f76324bf3839ca1f62653a83deb736932adcfbd9
2026-07-14 10:08:15 +02:00

180 lines
5.7 KiB
Rust

use futures_executor::block_on;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, disasmer::TaskArg)]
struct CompoundBoundary {
label: String,
source: disasmer::SourceSnapshot,
optional_artifact: Option<disasmer::Artifact>,
artifacts: Vec<disasmer::Artifact>,
}
#[disasmer::main]
fn build_main() -> u32 {
1
}
#[disasmer::main(name = "release")]
fn release_main() -> u32 {
2
}
#[disasmer::task(name = "compile-linux", capabilities = "Command")]
fn compile_linux() -> u32 {
41
}
#[disasmer::task]
fn package_release() -> disasmer::Artifact {
disasmer::Artifact {
id: "artifact://package/release.tar.zst".to_owned(),
digest: "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
.to_owned(),
size_bytes: 0,
}
}
#[disasmer::main(name = "async-build")]
async fn async_build_main() -> Result<(), &'static str> {
Ok(())
}
#[disasmer::task(name = "async-compile")]
async fn async_compile(input: u32) -> Result<u32, &'static str> {
Ok(input + 1)
}
#[disasmer::task(name = "roundtrip-compound")]
async fn roundtrip_compound(input: CompoundBoundary) -> CompoundBoundary {
input
}
#[test]
fn disasmer_attributes_and_spawn_api_compile_for_rust_build_workflow() {
let program = disasmer::RegisteredProgram {
entrypoints: &[
__DISASMER_ENTRYPOINT_BUILD_MAIN,
__DISASMER_ENTRYPOINT_RELEASE_MAIN,
],
tasks: &[
__DISASMER_TASK_COMPILE_LINUX,
__DISASMER_TASK_PACKAGE_RELEASE,
],
};
assert_eq!(
program.select_entrypoint("build").unwrap().function,
"build_main"
);
assert_eq!(
program.select_entrypoint("release").unwrap().function,
"release_main"
);
assert_eq!(
program.task("compile-linux").unwrap().function,
"compile_linux"
);
let task = program.task("compile-linux").unwrap();
assert!(task.stable_id.starts_with("sha256:"));
assert_eq!(task.argument_schema, "");
assert_eq!(task.result_schema, "u32");
assert_eq!(task.required_capabilities, ["Command"]);
assert!(task.restart_compatibility_hash.starts_with("sha256:"));
assert_eq!(task.abi_version, 1);
assert!(task.source_file.ends_with("macros.rs"));
assert!(task.source_line > 0);
assert_eq!(task.probe_symbol, "disasmer.probe.compile_linux");
assert!(task.bundle_manifest_entry);
assert!(task.remotely_startable);
let entrypoint = program.select_entrypoint("build").unwrap();
assert!(entrypoint.stable_id.starts_with("sha256:"));
assert_eq!(entrypoint.result_schema, "u32");
assert_eq!(entrypoint.abi_version, 1);
assert!(entrypoint.bundle_manifest_entry);
let result = block_on(async {
let handle = disasmer::spawn::task(|| compile_linux() + build_main())
.name("compile linux")
.env(disasmer::env!("linux"))
.start()
.await
.unwrap();
assert!(handle.virtual_thread_id() > 0);
handle.join().await.unwrap()
});
assert_eq!(result, 42);
assert_eq!(release_main(), 2);
}
#[test]
fn task_boundaries_accept_small_values_and_runtime_handles() {
let small = disasmer::validate_task_arg(&7_u32, disasmer::TaskArgBudget::default()).unwrap();
assert_eq!(small.kind, disasmer::TaskArgKind::SmallSerialized);
let artifact = package_release();
let artifact = disasmer::validate_task_arg(
&artifact,
disasmer::TaskArgBudget {
max_inline_bytes: 4,
},
)
.unwrap();
assert_eq!(artifact.kind, disasmer::TaskArgKind::Handle);
}
#[test]
fn async_main_and_task_attributes_preserve_real_rust_futures_and_results() {
assert_eq!(block_on(async_build_main()), Ok(()));
assert_eq!(block_on(async_compile(41)), Ok(42));
assert_eq!(__DISASMER_ENTRYPOINT_ASYNC_BUILD_MAIN.name, "async-build");
assert_eq!(__DISASMER_TASK_ASYNC_COMPILE.name, "async-compile");
}
#[test]
fn derived_compound_boundary_keeps_nested_handles_out_of_opaque_json() {
let source = "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
let value = CompoundBoundary {
label: "release".to_owned(),
source: disasmer::SourceSnapshot {
digest: source.to_owned(),
},
optional_artifact: Some(disasmer::Artifact {
id: "optional.bin".to_owned(),
digest: source.to_owned(),
size_bytes: 0,
}),
artifacts: vec![
disasmer::Artifact {
id: "one.bin".to_owned(),
digest: source.to_owned(),
size_bytes: 0,
},
disasmer::Artifact {
id: "two.bin".to_owned(),
digest: source.to_owned(),
size_bytes: 0,
},
],
};
assert_eq!(block_on(roundtrip_compound(value.clone())), value);
let boundary = disasmer::TaskArg::task_boundary_value(&value).unwrap();
let disasmer::core::TaskBoundaryValue::Structured(structured) = boundary else {
panic!("derived boundary must be structured");
};
assert_eq!(structured.handles.len(), 4);
assert_eq!(
disasmer::core::TaskBoundaryValue::Structured(structured.clone()).source_snapshots(),
vec![disasmer::core::Digest::sha256([])]
);
assert_eq!(
disasmer::core::TaskBoundaryValue::Structured(structured.clone()).required_artifacts(),
vec![
disasmer::core::ArtifactId::from("optional.bin"),
disasmer::core::ArtifactId::from("one.bin"),
disasmer::core::ArtifactId::from("two.bin"),
]
);
let decoded: CompoundBoundary = serde_json::from_value(structured.value).unwrap();
assert_eq!(decoded, value);
}