use crate::sync_codec::ids::SyncNodeId;
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Ballot {
pub counter: u64,
pub node: SyncNodeId,
}
impl Ballot {
#[must_use]
pub fn bottom() -> Self {
Self {
counter: 0,
node: SyncNodeId::new(""),
}
}
#[must_use]
pub const fn new(counter: u64, node: SyncNodeId) -> Self {
Self { counter, node }
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Stamp {
pub epoch: Ballot,
pub seq: u64,
}
impl Stamp {
#[must_use]
pub const fn new(epoch: Ballot, seq: u64) -> Self {
Self { epoch, seq }
}
#[must_use]
pub fn bottom() -> Self {
Self {
epoch: Ballot::bottom(),
seq: 0,
}
}
}
#[cfg(test)]
mod tests {
use super::Ballot;
use crate::sync_codec::ids::SyncNodeId;
fn ballot(counter: u64, node: &str) -> Ballot {
Ballot::new(counter, SyncNodeId::from(node))
}
#[test]
fn counter_dominates_node_in_ordering() {
assert!(ballot(1, "z") < ballot(2, "a"));
}
#[test]
fn node_breaks_ties_at_equal_counter() {
assert!(ballot(1, "a") < ballot(1, "b"));
}
#[test]
fn bottom_is_below_every_real_ballot() {
assert!(Ballot::bottom() < ballot(1, ""));
assert!(Ballot::bottom() < ballot(1, "a"));
assert!(Ballot::bottom() < ballot(0, "a"));
assert_eq!(Ballot::bottom(), ballot(0, ""));
}
#[test]
fn stamp_epoch_dominates_seq_in_ordering() {
use super::Stamp;
let lower_epoch_high_seq = Stamp::new(ballot(1, "z"), u64::MAX);
let higher_epoch_zero_seq = Stamp::new(ballot(2, "a"), 0);
assert!(lower_epoch_high_seq < higher_epoch_zero_seq);
}
#[test]
fn stamp_seq_breaks_ties_at_equal_epoch() {
use super::Stamp;
assert!(Stamp::new(ballot(3, "a"), 4) < Stamp::new(ballot(3, "a"), 5));
}
#[test]
fn stamp_bottom_is_below_every_real_stamp() {
use super::Stamp;
assert!(Stamp::bottom() < Stamp::new(ballot(1, "a"), 0));
assert!(Stamp::bottom() < Stamp::new(Ballot::bottom(), 1));
assert_eq!(Stamp::bottom(), Stamp::new(Ballot::bottom(), 0));
}
#[test]
fn ballot_is_clone_eq_hash_debug() {
let original = ballot(7, "node-a");
let copy = original.clone();
assert_eq!(original, copy);
let mut set = std::collections::HashSet::new();
set.insert(original);
assert!(set.contains(©));
assert!(format!("{copy:?}").contains("node-a"));
}
}