extern crate alloc;
use alloc::collections::BTreeSet;
use alloc::vec::Vec;
use crate::metis::{Composer, Rhapsody};
use proptest::prelude::*;
use super::super::strong_list::OrderLedger;
use super::d;
use self::convergence::assert_convergence;
use self::ops::{
condense_all, gossip_delta, gossip_full, order_read, retract, weave, weave_before,
};
mod convergence;
mod ops;
mod reference;
mod wire;
use crate::metis::Dot;
const REPLICAS: usize = 3;
const MAX_OPS: usize = 400;
struct Fleet {
live: Vec<Composer<Rhapsody>>,
peak_skeleton: Vec<usize>,
ever_removed: BTreeSet<Dot>,
ledger: OrderLedger,
}
proptest! {
#[test]
fn prop_rhapsody_op_tape_interpreter_matches_the_suite(
tape in prop::collection::vec(any::<u8>(), 0..512),
) {
let _ = interpret(&tape);
}
}
fn interpret(tape: &[u8]) -> Fleet {
let mut fleet = Fleet {
live: (0..REPLICAS)
.map(|i| Composer::new(station_of(i)))
.collect(),
peak_skeleton: alloc::vec![0usize; REPLICAS],
ever_removed: BTreeSet::new(),
ledger: OrderLedger::new(),
};
let mut tick: u64 = 0;
let mut condensed = false;
for pair in tape.chunks_exact(2).take(MAX_OPS) {
let opcode = pair[0];
let argument = pair[1];
let replica = usize::from(argument % 3);
let other = usize::from((argument / 3) % 3);
match opcode % 7 {
0 => weave(&mut fleet, replica, argument, &mut tick),
1 => retract(&mut fleet, replica, argument),
2 => gossip_delta(&mut fleet, replica, other),
3 => gossip_full(&mut fleet, replica, other),
4 => {
condense_all(&mut fleet);
condensed = true;
}
5 => order_read(&mut fleet, replica),
_ => weave_before(&mut fleet, replica, argument, &mut tick),
}
for i in 0..REPLICAS {
let now = fleet.live[i].state().store().skeleton_len();
fleet.peak_skeleton[i] = fleet.peak_skeleton[i].max(now);
if condensed {
assert!(
now <= fleet.peak_skeleton[i],
"the skeleton never grows past its pre-condense peak within a run",
);
} else {
assert_eq!(
fleet.peak_skeleton[i], now,
"before any condense the skeleton is grow-only",
);
}
}
}
assert_convergence(&mut fleet);
fleet
}
#[test]
fn test_a_directed_tape_drives_every_op_deterministically() {
let fleet = interpret(&[0, 0, 0, 0, 6, 0, 6, 255, 2, 1, 1, 1, 3, 3, 4, 0, 5, 0]);
assert_eq!(fleet.ledger.observations(), 36);
for replica in &fleet.live[..2] {
assert_eq!(replica.state().store().order(), [d(1, 4), d(1, 1), d(1, 2)]);
}
assert!(fleet.live[2].state().store().order().is_empty());
}
fn station_of(i: usize) -> u32 {
u32::try_from(i + 1).unwrap_or(u32::MAX)
}