use aion_awl::{Keyword, POSITIONAL_WORDS};
use super::{json, render_all, render_one};
#[test]
fn the_text_form_prints_every_word_of_the_language() {
let rendered = render_all();
for keyword in Keyword::ALL {
assert!(
rendered.contains(&format!(" {} ", keyword.as_word()))
|| rendered.contains(&format!(" {} ", keyword.as_word())),
"`{}` is a word of the language and must be listed",
keyword.as_word()
);
}
for word in POSITIONAL_WORDS {
assert!(
rendered.contains(word),
"`{word}` is a word of the language and must be listed"
);
}
}
#[test]
fn the_text_form_names_the_documents_an_author_needs() {
let rendered = render_all();
for path in [
"docs/authoring/AWL.md",
"docs/assistant/grounding/AWL-REFERENCE.md",
"docs/assistant/grounding/AWL-AUTHORING.md",
"docs/assistant/grounding/WORKERS.md",
"docs/assistant/grounding/COMMANDS.md",
"docs/workers/DECLARED-COMMANDS.md",
] {
assert!(rendered.contains(path), "the guide must name {path}");
}
}
#[test]
fn each_reference_section_is_printed_once_in_order() {
let rendered = render_all();
let headings: Vec<u8> = rendered
.lines()
.filter_map(|line| line.strip_prefix('§'))
.filter_map(|line| line.split_once(' ').map(|(number, _)| number.to_owned()))
.filter_map(|number| number.parse::<u8>().ok())
.collect();
assert!(
!headings.is_empty(),
"the guide must print section headings"
);
let mut sorted = headings.clone();
sorted.sort_unstable();
sorted.dedup();
assert_eq!(
headings, sorted,
"sections must appear once each, in reference order"
);
}
#[test]
fn one_word_prints_its_sentence_examples_and_citation() {
let entry = aion_awl::guide::for_word("collect");
assert!(entry.is_some(), "`collect` is a word of the language");
let rendered = entry.map(render_one).unwrap_or_default();
assert!(rendered.starts_with("collect (reserved word)\n"));
assert!(rendered.contains("Closes the nearest region"));
assert!(
rendered.contains("AWL reference §8 — Parallel and sequential work"),
"{rendered}"
);
assert!(
!rendered.contains("AWL-REFERENCE.md"),
"the citation must not name a repository path an installed binary cannot resolve: \
{rendered}"
);
assert!(
rendered.contains("\n collect health -> results\n"),
"the example document must be printed, indented as a block: {rendered}"
);
assert!(
rendered.contains("\n workflow check_services\n"),
"the example must be a complete document, not a fragment: {rendered}"
);
assert!(
rendered.contains(" Example 1:\n") && rendered.contains(" Example 2:\n"),
"a word with several forms must number its examples: {rendered}"
);
assert!(
rendered.contains("collect report? -> reports"),
"the tolerant form must be among the examples: {rendered}"
);
assert!(
rendered.contains("Full reference: aion awl guide --reference"),
"the entry must say how to open the full reference from this binary: {rendered}"
);
}
#[test]
fn a_single_form_word_prints_one_unnumbered_example() {
let entry = aion_awl::guide::for_word("spawn");
assert!(entry.is_some(), "`spawn` is a word of the language");
let rendered = entry.map(render_one).unwrap_or_default();
assert!(
!rendered.contains("Example 1:"),
"a single example must not be numbered: {rendered}"
);
assert!(
rendered.contains("\n spawn notify_archived(report_id: report_id)\n"),
"the single example must still be printed: {rendered}"
);
}
#[test]
fn the_embedded_reference_is_the_whole_document() {
let text = aion_awl::guide::reference_text();
assert!(
text.contains("## 1. Document structure"),
"the embedded reference must open with its first numbered section"
);
assert!(
text.contains("## 16. Worker documents"),
"the embedded reference must reach its final numbered section"
);
}
#[test]
fn a_positional_word_is_labelled_as_positional() {
let entry = aion_awl::guide::for_word("run");
assert!(entry.is_some(), "`run` is a word of the language");
let rendered = entry.map(render_one).unwrap_or_default();
assert!(
rendered.starts_with("run (positional word)\n"),
"{rendered}"
);
}
#[test]
fn the_json_form_carries_the_whole_inventory_and_the_paths() {
let rendered = json(None);
assert!(rendered.is_ok(), "the glossary must render as JSON");
let text = rendered.unwrap_or_default();
assert!(text.ends_with('\n'), "the asset must end in a newline");
let parsed: serde_json::Value = serde_json::from_str(&text).unwrap_or(serde_json::Value::Null);
assert_eq!(
parsed["entries"].as_array().map(Vec::len),
Some(Keyword::ALL.len() + POSITIONAL_WORDS.len())
);
assert_eq!(parsed["guide"].as_str(), Some("docs/authoring/AWL.md"));
assert_eq!(
parsed["reference"].as_str(),
Some("docs/assistant/grounding/AWL-REFERENCE.md")
);
assert_eq!(parsed["entries"][0]["word"].as_str(), Some("workflow"));
for entry in parsed["entries"].as_array().cloned().unwrap_or_default() {
let examples = entry["examples"].as_array().cloned().unwrap_or_default();
assert!(
!examples.is_empty(),
"every entry must carry at least one example document: {entry}"
);
for example in &examples {
assert!(
example
.as_str()
.is_some_and(|example| example.starts_with("//!")),
"every example must be a complete narrated document: {entry}"
);
}
}
}
#[test]
fn the_json_form_carries_the_grammar_axis_and_the_reference() {
let text = json(None).unwrap_or_default();
let parsed: serde_json::Value = serde_json::from_str(&text).unwrap_or(serde_json::Value::Null);
let forms = parsed["forms"].as_array().cloned().unwrap_or_default();
let form_ids: Vec<&str> = forms
.iter()
.filter_map(|form| form["id"].as_str())
.collect();
assert_eq!(
form_ids.len(),
aion_awl::guide::GrammarForm::ALL.len(),
"every form of the taxonomy must ride the wire: {forms:?}"
);
for form in &forms {
for field in ["id", "label", "description"] {
assert!(
form[field].as_str().is_some_and(|value| !value.is_empty()),
"a form is missing `{field}`: {form}"
);
}
}
let positions = parsed["positions"].as_array().cloned().unwrap_or_default();
let position_ids: Vec<&str> = positions
.iter()
.filter_map(|position| position["id"].as_str())
.collect();
assert_eq!(
position_ids.len(),
aion_awl::guide::GrammarPosition::ALL.len(),
"every grammar position must ride the wire: {positions:?}"
);
for entry in parsed["entries"].as_array().cloned().unwrap_or_default() {
let form = entry["form"].as_str().unwrap_or_default();
assert!(
form_ids.contains(&form),
"an entry names a form the taxonomy does not carry: {entry}"
);
let stands = entry["positions"].as_array().cloned().unwrap_or_default();
assert!(
!stands.is_empty(),
"an entry stands in no position: {entry}"
);
for position in &stands {
assert!(
position
.as_str()
.is_some_and(|position| position_ids.contains(&position)),
"an entry stands in a position the inventory does not carry: {entry}"
);
}
}
let reference = parsed["reference_text"].as_str().unwrap_or_default();
assert!(
reference.contains("## 1. Document structure")
&& reference.contains("## 16. Worker documents"),
"the wire must carry the whole reference, first section to last"
);
assert_eq!(
reference,
aion_awl::guide::reference_text(),
"the wire's reference must be the embedded reference, verbatim"
);
}
#[test]
fn the_json_form_is_byte_stable() {
assert_eq!(
json(None).unwrap_or_default(),
json(None).unwrap_or_default()
);
}
#[test]
fn one_word_as_json_carries_only_that_word() {
let text = json(Some("distribute")).unwrap_or_default();
let parsed: serde_json::Value = serde_json::from_str(&text).unwrap_or(serde_json::Value::Null);
assert_eq!(parsed["entries"].as_array().map(Vec::len), Some(1));
assert_eq!(parsed["entries"][0]["word"].as_str(), Some("distribute"));
assert_eq!(parsed["entries"][0]["kind"].as_str(), Some("keyword"));
assert_eq!(parsed["entries"][0]["section"]["number"].as_u64(), Some(8));
assert_eq!(parsed["entries"][0]["form"].as_str(), Some("statement"));
}
#[test]
fn a_word_the_language_does_not_have_resolves_to_nothing() {
assert!(aion_awl::guide::for_word("select").is_none());
let text = json(Some("select")).unwrap_or_default();
let parsed: serde_json::Value = serde_json::from_str(&text).unwrap_or(serde_json::Value::Null);
assert_eq!(parsed["entries"].as_array().map(Vec::len), Some(0));
}
#[test]
fn one_word_prints_where_it_stands_in_the_language() {
let entry = aion_awl::guide::for_word("workflow");
assert!(entry.is_some(), "`workflow` is a word of the language");
let rendered = entry.map(render_one).unwrap_or_default();
assert!(
rendered.contains(
" Inside it input, signal, outcome, timeout, type, route, success, failure,\n \
\x20 query, send\n"
),
"the words a workflow header admits must print under the sentence: {rendered}"
);
assert!(
rendered.contains(
" Alongside workloop, type, worker, child, detached, const, subflow, \
step,\n retire, set, export, recipe, wall, artifact\n"
),
"the words a workflow stands beside must print: {rendered}"
);
let sentence = "one `.awl` file declares exactly one workflow, named here.\n";
let rows = rendered
.split_once(sentence)
.map(|(_, rest)| rest)
.unwrap_or_default();
assert!(
rows.starts_with(" Inside it"),
"the rows must sit directly under the sentence: {rendered}"
);
}
#[test]
fn a_top_level_word_lives_in_the_document() {
let entry = aion_awl::guide::for_word("workflow");
let rendered = entry.map(render_one).unwrap_or_default();
assert!(
rendered.contains(" Lives in the document\n"),
"a top-level declaration must name the document as what encloses it: {rendered}"
);
let nested = aion_awl::guide::for_word("step")
.map(render_one)
.unwrap_or_default();
assert!(
nested.contains(" Lives in the document, recipe\n"),
"`step` stands at the top level AND inside a recipe: {nested}"
);
}
#[test]
fn a_word_with_no_such_relation_prints_no_empty_row() {
let rendered = aion_awl::guide::for_word("filter")
.map(render_one)
.unwrap_or_default();
assert!(
rendered.contains(" Alongside sort, map, count, any, all, route\n"),
"`filter` stands beside the other pipeline stages: {rendered}"
);
assert!(
!rendered.contains("Inside it"),
"`filter` opens nothing, so it must print no containment row: {rendered}"
);
assert!(
!rendered.contains("Lives in"),
"`filter` is reached by a cue on the line, so nothing encloses it: {rendered}"
);
}
#[test]
fn a_long_relation_row_wraps_under_its_heading() {
let rendered = aion_awl::guide::for_word("step")
.map(render_one)
.unwrap_or_default();
let row: Vec<&str> = rendered
.lines()
.skip_while(|line| !line.starts_with(" Inside it"))
.take_while(|line| !line.trim_start().starts_with("Alongside"))
.collect();
assert!(
row.len() > 1,
"the step body's twenty-six words must wrap over several lines: {rendered}"
);
for line in &row {
assert!(
line.len() <= 78,
"a wrapped row must not run past the measure: `{line}`"
);
}
for line in row.iter().skip(1) {
assert!(
line.starts_with(" ") && !line.starts_with(" "),
"a continuation must align under the first word, not under the heading: `{line}`"
);
}
let words: String = row.join(" ");
for word in aion_awl::guide::children_of("step") {
assert!(
words.contains(word),
"the row must carry every word the step body admits, `{word}` included: {rendered}"
);
}
}
#[test]
fn the_json_form_carries_the_structural_relations() {
let text = json(None).unwrap_or_default();
let parsed: serde_json::Value = serde_json::from_str(&text).unwrap_or(serde_json::Value::Null);
let relations = parsed["relations"].as_array().cloned().unwrap_or_default();
let relation_ids: Vec<&str> = relations
.iter()
.filter_map(|relation| relation["id"].as_str())
.collect();
assert_eq!(
relation_ids,
vec!["children", "siblings", "parents"],
"the relation taxonomy must ride the wire in its own order: {relations:?}"
);
for relation in &relations {
for field in ["id", "label", "description"] {
assert!(
relation[field]
.as_str()
.is_some_and(|value| !value.is_empty()),
"a relation is missing `{field}`: {relation}"
);
}
}
let entries = parsed["entries"].as_array().cloned().unwrap_or_default();
let words: Vec<&str> = entries
.iter()
.filter_map(|entry| entry["word"].as_str())
.collect();
assert_eq!(
words.len(),
99,
"the sweep below is only as wide as the entries it reads: {}",
words.len()
);
let mut edges = 0usize;
for entry in &entries {
for relation in &relation_ids {
let related = entry[*relation].as_array().cloned().unwrap_or_default();
for id in &related {
edges += 1;
let id = id.as_str().unwrap_or_default();
assert!(
words.contains(&id),
"an entry's `{relation}` names `{id}`, which is no entry of this document"
);
}
}
assert!(
entry["at_document_level"].as_bool().is_some(),
"every entry must say whether the document is what encloses it: {entry}"
);
}
assert!(
edges > 500,
"the control failed: only {edges} relation ids were read, so the sweep measured an empty \
harness"
);
}