use serde_json::{Value, json};
use super::{REPLIES, editions, project, reword};
use crate::corpus::ledger::{self, FLOOR};
use crate::corpus::{ADVERTISED, QUEUED, REFUSAL};
use crate::gestures::{self, Reply};
const UNHEARD: &str = "fhtagn";
fn frame(text: &str) -> Value {
serde_json::from_str(text).expect("a corpus frame is JSON")
}
#[test]
fn every_reply_shape_decodes_at_every_edition_an_engine_can_be_at() {
let mut replayed = 0;
for (name, frames) in REPLIES {
let signature = ledger::signature(name).expect("a shape this foot speaks");
for edition in editions() {
for text in frames {
let projected = project(&frame(text), signature, edition);
assert!(
gestures::decode(&projected).is_ok(),
"{name} at edition {edition} refused {projected}"
);
replayed += 1;
}
}
}
assert!(replayed > 0, "the replay walked no frame at all");
}
#[test]
fn the_replay_always_has_at_least_the_floor_to_replay_at() {
let editions = editions();
assert_eq!(editions.first(), Some(&FLOOR));
assert_eq!(editions.last(), Some(&FLOOR.max(ledger::edition())));
}
#[test]
fn a_key_stamped_above_the_floor_is_deleted_and_the_strict_reader_says_so() {
const AFTER_THE_FLOOR: [(&str, u32); 4] = [
("/kind:string", 8),
("/ok:bool", 8),
("/wrote:bool", 19),
(":object", 8),
];
let projected = project(&frame(ADVERTISED[1]), &AFTER_THE_FLOOR, FLOOR);
assert_eq!(projected, json!({"kind": "advertised", "ok": true}));
assert_eq!(
gestures::decode(&projected),
Err("reply: missing field \"wrote\"".to_owned())
);
}
#[test]
fn an_unheard_of_word_refuses_nothing_but_the_kind() {
let mut reworded = 0;
for (name, frames) in REPLIES {
let signature = ledger::signature(name).expect("a shape this foot speaks");
for path in ledger::paths_of_type(signature, "string") {
if path == "/kind" {
continue;
}
let Some(mutated) = frames
.iter()
.find_map(|text| reword(&frame(text), path, UNHEARD))
else {
panic!("{name}: the ledger stamps {path} and no vendored frame carries it");
};
assert!(
gestures::decode(&mutated).is_ok(),
"{name} refused an unheard-of word at {path}: {mutated}"
);
reworded += 1;
}
}
assert!(reworded > 0, "the ledger stamps no word-shaped path");
}
#[test]
fn the_kind_stays_strict_under_the_same_mutation() {
let mutated = reword(&frame(ADVERTISED[0]), "/kind", UNHEARD).expect("a kind to reword");
assert_eq!(
gestures::decode(&mutated),
Err(format!("reply: unusable kind {UNHEARD:?}"))
);
}
#[test]
fn a_path_the_frame_does_not_carry_is_not_a_mutation() {
assert_eq!(reword(&frame(REFUSAL), "/kind", UNHEARD), None);
}
#[test]
fn a_post_floor_key_on_a_row_is_deleted_and_a_defaulting_reader_goes_on() {
const AFTER_THE_FLOOR: [(&str, u32); 4] = [
("/kind:string", 2),
("/ok:bool", 2),
("/rows/[]/cwd:string", 19),
("/rows/[]/tool:string", 2),
];
let projected = project(&frame(QUEUED[2]), &AFTER_THE_FLOOR, FLOOR);
assert_eq!(projected["rows"][0].get("cwd"), None);
let Ok(Ok(Reply::Invocations(rows))) = gestures::decode(&projected) else {
panic!("a row an older engine wrote still decodes");
};
assert_eq!(rows[0].cwd, None);
}
#[test]
fn a_path_the_frames_shape_does_not_admit_changes_nothing() {
for path in ["", "/kind/[]", "/rows/[]/tool/deeper"] {
assert_eq!(reword(&frame(QUEUED[1]), path, UNHEARD), None, "{path}");
}
}