use std::path::Path;
use super::*;
type TestResult = Result<(), Box<dyn std::error::Error>>;
fn tracked_document() -> std::path::PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).join("assistant-embed/assistant.awl")
}
#[test]
fn the_embedded_document_is_the_tracked_artifact() -> TestResult {
let on_disk = std::fs::read_to_string(tracked_document())?;
assert_eq!(
EMBEDDED_ASSISTANT_DOCUMENT, on_disk,
"the embedded document must be the bytes of assistant-embed/assistant.awl"
);
assert!(
!EMBEDDED_ASSISTANT_DOCUMENT.is_empty(),
"an empty embedded document would satisfy every other assertion here"
);
Ok(())
}
#[test]
fn the_embedded_document_compiles_into_a_validated_package() -> TestResult {
let embedded = EmbeddedAssistant::load()?;
assert_eq!(embedded.workflow_type(), "assistant");
assert_eq!(embedded.source(), EMBEDDED_ASSISTANT_DOCUMENT);
assert!(
!embedded.content_hash().to_string().is_empty(),
"a package with no content hash has no version identity"
);
assert_eq!(
embedded.package().manifest().entry_module,
embedded.workflow_type(),
"the workflow type is the manifest's entry module, not a name held beside it"
);
Ok(())
}
#[test]
fn the_embedded_identity_is_deterministic() -> TestResult {
let first = EmbeddedAssistant::load()?;
let second = EmbeddedAssistant::load()?;
assert_eq!(first.content_hash(), second.content_hash());
Ok(())
}
#[test]
fn the_session_contract_surfaces_are_declared_by_the_document() -> TestResult {
let embedded = EmbeddedAssistant::load()?;
let schema = embedded.continuation_schema()?;
let definition = schema["$ref"]
.as_str()
.and_then(|reference| reference.strip_prefix("#/$defs/"))
.map(|name| &schema["$defs"][name])
.ok_or("the continuation schema must reference its own definition")?;
for field in [CONTINUE_MESSAGE_FIELD, CONTINUE_END_FIELD] {
assert!(
!definition["properties"][field].is_null(),
"the `{CONTINUE_SIGNAL}` payload schema must declare `{field}`; got {schema}"
);
}
assert!(
embedded.queries().iter().any(|name| name == STATUS_QUERY),
"the document must declare the `{STATUS_QUERY}` query; got {:?}",
embedded.queries()
);
let inputs = embedded
.input_schema()
.get("properties")
.and_then(serde_json::Value::as_object)
.ok_or("the derived input schema must be an object schema")?;
for input in [OBJECTIVE_INPUT, REPO_PATH_INPUT] {
assert!(
inputs.contains_key(input),
"the start contract must carry `{input}`; got {inputs:?}"
);
}
Ok(())
}
#[test]
fn a_document_that_renames_the_objective_input_is_refused_by_name() -> TestResult {
let renamed: &'static str = Box::leak(
EMBEDDED_ASSISTANT_DOCUMENT
.replace("input objective: String", "input goal: String")
.replace(
"contract_tail + objective -> opening_prompt",
"contract_tail + goal -> opening_prompt",
)
.into_boxed_str(),
);
assert_ne!(
renamed, EMBEDDED_ASSISTANT_DOCUMENT,
"the mutation must change the document, or this test measures nothing"
);
match EmbeddedAssistant::from_source(renamed) {
Err(EmbeddedAssistantError::MissingInput { name }) => {
assert_eq!(name, OBJECTIVE_INPUT);
Ok(())
}
Err(other) => Err(format!(
"the renamed document must be refused for the MISSING INPUT, not for {other}; a \
compile failure here would mean the mutation never reached the contract check"
)
.into()),
Ok(_) => Err(format!(
"a document declaring no `{OBJECTIVE_INPUT}` input was accepted — the session \
contract verification is not on the load path"
)
.into()),
}
}
#[test]
fn the_embedded_queue_is_derived_from_the_workflow_type_and_is_never_default() -> TestResult {
let embedded = EmbeddedAssistant::load()?;
assert_eq!(
embedded.task_queue(),
private_task_queue(embedded.workflow_type()),
"the declared queue must BE the derivation, not a value beside it"
);
assert_ne!(
embedded.task_queue(),
aion_core::DEFAULT_TASK_QUEUE,
"the built-in assistant must never claim the out-of-box workers' queue (#200)"
);
let contract = embedded.package().contract()?;
let declared: Vec<&str> = contract
.workers
.iter()
.map(|worker| worker.task_queue.as_str())
.collect();
assert_eq!(
declared,
vec![embedded.task_queue()],
"the document must declare exactly the one private queue"
);
Ok(())
}
#[test]
fn a_document_that_claims_the_default_queue_is_refused_by_name() -> TestResult {
let on_default: &'static str = Box::leak(
EMBEDDED_ASSISTANT_DOCUMENT
.replace("\nworker assistant\n", "\nworker default\n")
.into_boxed_str(),
);
assert_ne!(
on_default, EMBEDDED_ASSISTANT_DOCUMENT,
"the mutation must change the document, or this test measures nothing"
);
match EmbeddedAssistant::from_source(on_default) {
Err(EmbeddedAssistantError::QueueNotDerived { declared, expected }) => {
assert_eq!(declared, aion_core::DEFAULT_TASK_QUEUE);
assert_eq!(expected, "assistant");
Ok(())
}
Err(other) => Err(format!(
"a document on `default` must be refused for its QUEUE, not for {other}; a compile \
failure here would mean the mutation never reached the queue check"
)
.into()),
Ok(_) => Err(
"a document declaring `worker default` was accepted — the queue derivation is not on \
the load path, and the assistant can ship on the out-of-box workers' queue again"
.into(),
),
}
}
#[test]
fn the_derivation_refuses_every_other_disagreement_by_name() -> TestResult {
let queue = |name: &str| aion_package::WorkerContract {
task_queue: String::from(name),
actions: Vec::new(),
};
let none = aion_package::PackageContract::default();
match verified_task_queue("assistant", &none) {
Err(EmbeddedAssistantError::MissingWorkerBlock { expected }) => {
assert_eq!(expected, "assistant");
}
other => {
return Err(format!("a contract with no queue must be refused; got {other:?}").into());
}
}
let several = aion_package::PackageContract {
workers: vec![queue("assistant"), queue("assistant_extra")],
..aion_package::PackageContract::default()
};
match verified_task_queue("assistant", &several) {
Err(EmbeddedAssistantError::AmbiguousQueue { declared, expected }) => {
assert_eq!(declared, "assistant, assistant_extra");
assert_eq!(expected, "assistant");
}
other => {
return Err(format!("two queues must be refused as ambiguous; got {other:?}").into());
}
}
let elsewhere = aion_package::PackageContract {
workers: vec![queue("something_else")],
..aion_package::PackageContract::default()
};
match verified_task_queue("assistant", &elsewhere) {
Err(EmbeddedAssistantError::QueueNotDerived { declared, expected }) => {
assert_eq!(declared, "something_else");
assert_eq!(expected, "assistant");
}
other => {
return Err(format!("an underived queue must be refused; got {other:?}").into());
}
}
let colliding = aion_package::PackageContract {
workers: vec![queue(aion_core::DEFAULT_TASK_QUEUE)],
..aion_package::PackageContract::default()
};
match verified_task_queue(aion_core::DEFAULT_TASK_QUEUE, &colliding) {
Err(EmbeddedAssistantError::QueueWouldBeDefault {
workflow_type,
default_queue,
}) => {
assert_eq!(workflow_type, aion_core::DEFAULT_TASK_QUEUE);
assert_eq!(default_queue, aion_core::DEFAULT_TASK_QUEUE);
}
other => {
return Err(format!(
"a workflow type deriving `default` must be refused; got {other:?}"
)
.into());
}
}
let derived = aion_package::PackageContract {
workers: vec![queue("assistant")],
..aion_package::PackageContract::default()
};
assert_eq!(verified_task_queue("assistant", &derived)?, "assistant");
Ok(())
}
#[test]
fn a_document_with_a_schema_import_is_refused_naming_the_import() -> TestResult {
let with_import: &'static str = Box::leak(
EMBEDDED_ASSISTANT_DOCUMENT
.replace(
"type Provisioned { exit_code: Int, stdout: String }",
"type Provisioned = schema(\"provisioned.json\")",
)
.into_boxed_str(),
);
match EmbeddedAssistant::from_source(with_import) {
Err(EmbeddedAssistantError::SchemaImport { path }) => {
assert_eq!(path, "provisioned.json");
Ok(())
}
Err(other) => Err(format!("the import must be refused as an import, got: {other}").into()),
Ok(_) => Err("a document with an unresolvable schema import was accepted".into()),
}
}
#[test]
fn the_process_wide_handle_matches_a_direct_load() -> TestResult {
let shared = embedded_assistant().map_err(ToString::to_string)?;
let direct = EmbeddedAssistant::load()?;
assert_eq!(shared.workflow_type(), direct.workflow_type());
assert_eq!(shared.content_hash(), direct.content_hash());
assert!(std::ptr::eq(
shared,
embedded_assistant().map_err(ToString::to_string)?
));
Ok(())
}
#[test]
fn property_detection_reads_the_schema_properties_map() {
let direct = serde_json::json!({"properties": {"message": {"type": "string"}}});
assert!(schema_declares_property(&direct, "message"));
assert!(!schema_declares_property(&direct, "end"));
assert!(!schema_declares_property(
&serde_json::json!({"message": {}}),
"message"
));
let referenced = serde_json::json!({
"$ref": "#/$defs/Continuation",
"$defs": {"Continuation": {"properties": {"end": {"type": "boolean"}}}},
});
assert!(schema_declares_property(&referenced, "end"));
assert!(!schema_declares_property(&referenced, "message"));
let dangling = serde_json::json!({
"$ref": "#/$defs/Missing",
"$defs": {},
"properties": {"end": {"type": "boolean"}},
});
assert!(!schema_declares_property(&dangling, "end"));
}