use std::fs; use assertables::assume; use rand::prelude::*; use rand_pcg::Pcg64; use anysystem::test::TestResult; use anysystem::Message; use crate::common::{build_system, check_guarantees, check_overhead, send_messages, TestConfig}; pub fn test_normal(config: &TestConfig) -> TestResult { let mut sys = build_system(config, false); let messages = send_messages(&mut sys, 5); sys.step_until_no_events(); check_guarantees(&mut sys, &messages, config)?; // We expect no more than 5 messages from sender in normal network conditions let sent_count = sys.sent_message_count("sender"); assume!( sent_count <= 5, format!("Sender sent {} messages, expected at most 5", sent_count) ) } pub fn test_normal_non_unique(config: &TestConfig) -> TestResult { let mut sys = build_system(config, false); let messages = send_messages(&mut sys, 10); sys.step_until_no_events(); check_guarantees(&mut sys, &messages, config)?; // We expect no more than 10 messages from sender in normal network conditions (stable delay, no loss). // If solution sends multiple messages without or with too small ( TestResult { let mut sys = build_system(config, false); sys.network().set_delays(1., 3.); let messages = send_messages(&mut sys, 5); sys.step_until_no_events(); check_guarantees(&mut sys, &messages, config) } pub fn test_duplicated(config: &TestConfig) -> TestResult { let mut sys = build_system(config, false); sys.network().set_dupl_rate(0.3); let messages = send_messages(&mut sys, 5); sys.step_until_no_events(); check_guarantees(&mut sys, &messages, config) } pub fn test_delayed_duplicated(config: &TestConfig) -> TestResult { let mut sys = build_system(config, false); sys.network().set_delays(1., 3.); sys.network().set_dupl_rate(0.3); let messages = send_messages(&mut sys, 5); sys.step_until_no_events(); check_guarantees(&mut sys, &messages, config) } pub fn test_old_duplicate(config: &TestConfig) -> TestResult { let mut sys = build_system(config, false); sys.network().set_delays(1., 3.); sys.network().set_dupl_rate(1.); let first = Message::new("MESSAGE", r#"{"text": "first"}"#); let mut messages = vec![first.clone()]; sys.send_local_message("sender", first); // Stop after the first copy is delivered. while sys.local_outbox("receiver").is_empty() { if !sys.step() { return Err("The first message was not delivered".to_string()); } } // Keep the old duplicate pending while newer messages are delivered first. // Zero-delay messages are processed before the delayed copy. sys.network().set_dupl_rate(0.); sys.network().set_delay(0.); for i in 0..50 { let msg = Message::new("MESSAGE", &format!(r#"{{"text": "message-{i}"}}"#)); sys.send_local_message("sender", msg.clone()); messages.push(msg); } sys.step_until_no_events(); check_guarantees(&mut sys, &messages, config) } pub fn test_dropped(config: &TestConfig) -> TestResult { let mut sys = build_system(config, false); sys.network().set_drop_rate(0.3); let messages = send_messages(&mut sys, 5); sys.step_until_no_events(); check_guarantees(&mut sys, &messages, config) } pub fn test_chaos_monkey(config: &TestConfig) -> TestResult { let mut rand = Pcg64::seed_from_u64(config.seed); for i in 1..=config.monkeys { let mut run_config = *config; run_config.seed = rand.next_u64(); println!("Run {} (seed: {})", i, run_config.seed); let mut sys = build_system(&run_config, false); sys.network().set_delays(1., 3.); sys.network().set_dupl_rate(0.3); sys.network().set_drop_rate(0.3); let messages = send_messages(&mut sys, 50); sys.step_until_no_events(); let res = check_guarantees(&mut sys, &messages, &run_config); res.as_ref()?; } Ok(true) } pub fn test_overhead(config: &TestConfig, guarantee: &str, faulty: bool) -> TestResult { for message_count in [100, 500, 1000] { let mut sys = build_system(config, true); if faulty { sys.network().set_delays(1., 3.); sys.network().set_dupl_rate(0.3); sys.network().set_drop_rate(0.3); } let messages = send_messages(&mut sys, message_count); sys.step_until_no_events(); let res = check_guarantees(&mut sys, &messages, config); res.as_ref()?; let sender_mem = sys.max_size("sender"); let receiver_mem = sys.max_size("receiver"); let net_message_count = sys.network().network_message_count(); let net_traffic = sys.network().traffic(); let throughput = message_count as f64 / sys.time(); println!( "{message_count:<6} Send Mem: {sender_mem:<8} Recv Mem: {receiver_mem:<8} Messages: {net_message_count:<8} Traffic: {net_traffic:<8} Throughput: {throughput:.3}" ); check_overhead( guarantee, faulty, message_count, sender_mem, receiver_mem, net_message_count, net_traffic, throughput, )?; } let impl_code = fs::read_to_string(config.impl_path).unwrap(); assume!( !impl_code.contains("<<") && !impl_code.contains(">>"), "Implementation contains bitwise shift operators" )?; Ok(true) }