The real conformance laws of whiskers-conformance, one by one, against a running host's hubs.
Each law is run on its own under catch_unwind so one failing law does not hide the rest, and the
report names it. fresh makes a new household (an empty hub: a new Durable Object); restart runs the
host's restart command, so a law about surviving a restart restarts the real process.
7use std::panic::{AssertUnwindSafe, catch_unwind};
9use whiskers_conformance::suite::hubs; 10use whiskers_core::{ChatState, Household, MemorySnapshot}; 11 12use crate::host::Host; 13use crate::hub::{HttpHub, Named}; 14use crate::ids::Households; 15 16pub struct Outcome { 17 pub law: &'static str, 18 pub failure: Option<String>, 19} 20 21fn message(panic: Box<dyn std::any::Any + Send>) -> String { 22 panic.downcast_ref::<String>().cloned().or_else(|| panic.downcast_ref::<&str>().map(|s| (*s).to_owned())).unwrap_or_else(|| "a panic".into()) 23}
Runs every law the host can be asked, returning each outcome.
26pub fn run_all(host: &Host, ids: &Households, restart: &dyn Fn()) -> Vec<Outcome> { 27 let mut out = Vec::new(); 28 // A law that needs a restart when the host cannot be restarted is reported, not skipped silently. 29 let fresh = |_: ()| HttpHub::<MemorySnapshot>::new(host, &ids.next()); 30 let fresh_m = || fresh(()); 31 let fresh_h = || HttpHub::<Household>::new(host, &ids.next()); 32 let fresh_c = || HttpHub::<ChatState>::new(host, &ids.next()); 33 let again_m = |h: HttpHub<MemorySnapshot>| { 34 restart(); 35 h 36 }; 37 let again_h = |h: HttpHub<Household>| { 38 restart(); 39 h 40 }; 41 let again_c = |h: HttpHub<ChatState>| { 42 restart(); 43 h 44 }; 45 46 macro_rules! law { 47 ($name:literal, $body:expr) => {{ 48 let r = catch_unwind(AssertUnwindSafe(|| $body)); 49 out.push(Outcome { law: $name, failure: r.err().map(message) }); 50 }}; 51 } 52 53 law!("memory_takes_facts_and_numbers_them", hubs::memory_takes_facts_and_numbers_them(fresh_m())); 54 law!("memory_merge_twice_changes_nothing", hubs::memory_merge_twice_changes_nothing(fresh_m())); 55 law!("memory_merge_is_order_independent", hubs::memory_merge_is_order_independent(&fresh_m)); 56 law!("memory_forgotten_wins_and_stays_forgotten", hubs::memory_forgotten_wins_and_stays_forgotten(&fresh_m)); 57 law!("memory_ignores_facts_with_no_identity", hubs::memory_ignores_facts_with_no_identity(fresh_m())); 58 law!("memory_the_same_words_twice_are_one_fact", hubs::memory_the_same_words_twice_are_one_fact(fresh_m())); 59 law!("memory_an_embedding_computed_anywhere_serves_everywhere", hubs::memory_an_embedding_computed_anywhere_serves_everywhere(&fresh_m)); 60 law!("memory_current_changes_nothing", hubs::memory_current_changes_nothing(fresh_m())); 61 law!("memory_a_hide_is_kept_and_the_later_write_wins", hubs::memory_a_hide_is_kept_and_the_later_write_wins(&fresh_m)); 62 law!("memory_a_hidden_fact_is_not_a_forgotten_one", hubs::memory_a_hidden_fact_is_not_a_forgotten_one(&fresh_m)); 63 law!("memory_a_picture_chosen_anywhere_serves_everywhere", hubs::memory_a_picture_chosen_anywhere_serves_everywhere(&fresh_m)); 64 law!("memory_survives_a_restart", hubs::memory_survives_a_restart(&fresh_m, &again_m)); 65 66 law!("household_takes_the_later_choice", hubs::household_takes_the_later_choice(&fresh_h)); 67 law!("household_merge_twice_changes_nothing", hubs::household_merge_twice_changes_nothing(fresh_h())); 68 law!("household_merge_is_order_independent", hubs::household_merge_is_order_independent(&fresh_h)); 69 law!("household_time_is_summed_across_devices_and_a_later_day_wins", hubs::household_time_is_summed_across_devices_and_a_later_day_wins(fresh_h())); 70 law!("household_survives_a_restart", hubs::household_survives_a_restart(&fresh_h, &again_h)); 71 72 law!("chat_the_newer_copy_wins_whole", hubs::chat_the_newer_copy_wins_whole(fresh_c())); 73 law!("chat_merge_twice_changes_nothing", hubs::chat_merge_twice_changes_nothing(fresh_c())); 74 law!("chat_survives_a_restart", hubs::chat_survives_a_restart(&fresh_c, &again_c)); 75 let _ = (<MemorySnapshot as Named>::NAME,); 76 out 77}