minerva 0.2.0

Causal ordering for distributed systems
extern crate alloc;

use alloc::vec::Vec;

use crate::metis::{DotSet, HaveSetDecodeError};

#[test]
fn test_have_set_from_bytes_rejects_empty_station() {
    // One station, floor 0, run_count 0: a value no encoder produces (canonical
    // form holds an empty station absent).
    let mut frame = Vec::new();
    frame.push(0x01u8);
    frame.extend_from_slice(&1u32.to_be_bytes());
    frame.extend_from_slice(&9u32.to_be_bytes()); // station 9
    frame.extend_from_slice(&0u64.to_be_bytes()); // floor 0
    frame.extend_from_slice(&0u32.to_be_bytes()); // run_count 0
    assert_eq!(
        DotSet::from_bytes(&frame),
        Err(HaveSetDecodeError::EmptyStation { station: 9 })
    );
}

#[test]
fn test_have_set_from_bytes_rejects_non_ascending_stations() {
    // Stations 5 then 3: not strictly ascending. Both carry floor 1 (canonical).
    let mut frame = Vec::new();
    frame.push(0x01u8);
    frame.extend_from_slice(&2u32.to_be_bytes());
    for station in [5u32, 3u32] {
        frame.extend_from_slice(&station.to_be_bytes());
        frame.extend_from_slice(&1u64.to_be_bytes()); // floor 1
        frame.extend_from_slice(&0u32.to_be_bytes()); // no runs
    }
    assert_eq!(
        DotSet::from_bytes(&frame),
        Err(HaveSetDecodeError::NonAscendingStations {
            previous: 5,
            found: 3,
        })
    );

    // A duplicate station is also non-ascending (not strictly greater).
    let mut duplicate = Vec::new();
    duplicate.push(0x01u8);
    duplicate.extend_from_slice(&2u32.to_be_bytes());
    for _ in 0..2 {
        duplicate.extend_from_slice(&4u32.to_be_bytes()); // station 4, twice
        duplicate.extend_from_slice(&1u64.to_be_bytes());
        duplicate.extend_from_slice(&0u32.to_be_bytes());
    }
    assert_eq!(
        DotSet::from_bytes(&duplicate),
        Err(HaveSetDecodeError::NonAscendingStations {
            previous: 4,
            found: 4,
        })
    );
}