#[cfg(test)]
use proptest::prelude::*;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MockProgressCertificate {
pub progress: u64,
pub timestamp: u64,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MockSymbolCancelRequest {
pub symbol_id: u32,
pub reason: String,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MockScope {
pub id: u32,
pub task_count: u32,
pub closed: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MockMacaroon {
pub authority: Vec<String>,
pub caveats: Vec<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MockRegistryState {
pub permits: Vec<u32>,
pub committed: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MockRuntimeState {
pub regions: Vec<u32>,
pub tasks: Vec<u32>,
pub phase: u8,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MockRegion {
pub id: u32,
pub children: Vec<u32>,
pub closed: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MockTask {
pub id: u32,
pub state: TaskState,
pub region_id: u32,
}
#[derive(Debug, Clone, PartialEq)]
pub enum TaskState {
Created,
Running,
Cancelled,
Completed,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MockMessage {
pub id: u32,
pub content: String,
pub sequence: u64,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MockBroadcastState {
pub messages: Vec<MockMessage>,
pub receivers: Vec<u32>,
pub lag_counts: Vec<u32>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MockWatchState {
pub value: i32,
pub version: u64,
pub coalesced_updates: Vec<i32>,
}
impl MockProgressCertificate {
pub fn advance(&self, delta: u64) -> Self {
Self {
progress: self.progress + delta,
timestamp: self.timestamp + 1,
}
}
pub fn merge(certs: &[Self]) -> Self {
let max_progress = certs.iter().map(|c| c.progress).max().unwrap_or(0);
let max_timestamp = certs.iter().map(|c| c.timestamp).max().unwrap_or(0);
Self {
progress: max_progress,
timestamp: max_timestamp,
}
}
}
impl MockSymbolCancelRequest {
pub fn cancel(&self) -> bool {
!self.reason.is_empty()
}
pub fn cancel_repeated(&self, times: u32) -> bool {
if times > 0 { self.cancel() } else { false }
}
}
impl MockScope {
pub fn close(&mut self) -> bool {
if self.task_count == 0 {
self.closed = true;
true
} else {
false
}
}
pub fn is_quiescent(&self) -> bool {
self.closed && self.task_count == 0
}
}
impl MockMacaroon {
pub fn attenuate(&self, new_caveat: &str) -> Self {
let mut caveats = self.caveats.clone();
caveats.push(new_caveat.to_string());
Self {
authority: self.authority.clone(),
caveats,
}
}
pub fn check_authority(&self, required: &str) -> bool {
self.authority.iter().any(|a| a == required)
&& !self
.caveats
.iter()
.any(|c| c == &format!("deny:{}", required))
}
}
impl MockRegistryState {
pub fn commit_permit(&mut self, permit_id: u32) -> bool {
if self.permits.contains(&permit_id) && !self.committed {
self.committed = true;
true
} else {
false
}
}
pub fn invariant_holds(&self) -> bool {
!self.committed || !self.permits.is_empty()
}
}
impl MockRuntimeState {
pub fn transition(&self, event: u8) -> Self {
Self {
regions: self.regions.clone(),
tasks: self.tasks.clone(),
phase: (self.phase + event) % 8,
}
}
pub fn deterministic_hash(&self) -> u64 {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let mut hasher = DefaultHasher::new();
self.hash(&mut hasher);
hasher.finish()
}
}
impl MockRegion {
pub fn close_ordered(regions: &[Self]) -> Vec<u32> {
let mut order = Vec::new();
let mut remaining: Vec<_> = regions.iter().collect();
while !remaining.is_empty() {
let leaf_idx = remaining
.iter()
.enumerate()
.filter(|(_, r)| {
!r.children
.iter()
.any(|child_id| remaining.iter().any(|rem| rem.id == *child_id))
})
.min_by_key(|(_, r)| r.id)
.map(|(idx, _)| idx)
.unwrap_or_else(|| {
remaining
.iter()
.enumerate()
.min_by_key(|(_, r)| r.id)
.map(|(idx, _)| idx)
.unwrap_or(0)
});
let region = remaining.remove(leaf_idx);
order.push(region.id);
}
order
}
}
impl MockTask {
pub fn valid_transitions() -> Vec<(TaskState, TaskState)> {
vec![
(TaskState::Created, TaskState::Running),
(TaskState::Created, TaskState::Cancelled),
(TaskState::Running, TaskState::Completed),
(TaskState::Running, TaskState::Cancelled),
]
}
pub fn transition(&self, new_state: TaskState) -> Option<Self> {
let valid = Self::valid_transitions();
if valid.contains(&(self.state.clone(), new_state.clone())) {
Some(Self {
id: self.id,
state: new_state,
region_id: self.region_id,
})
} else {
None
}
}
}
impl MockMessage {
pub fn mpsc_ordering(messages: &[Self]) -> Vec<u64> {
messages.iter().map(|m| m.sequence).collect()
}
}
impl MockBroadcastState {
pub fn lag_bound(&self, max_lag: u32) -> bool {
self.lag_counts.iter().all(|&lag| lag <= max_lag)
}
pub fn add_receiver(&mut self, receiver_id: u32) {
self.receivers.push(receiver_id);
self.lag_counts.push(0);
}
}
impl MockWatchState {
pub fn coalesce_updates(&mut self, updates: &[i32]) {
if let Some(&last) = updates.last() {
self.value = last;
self.version += updates.len() as u64;
self.coalesced_updates = vec![last]; }
}
pub fn coalescing_preserves_final_value(&self, original_updates: &[i32]) -> bool {
original_updates.last() == Some(&self.value)
}
}
#[test]
fn test_mr_progress_certificate_monotonicity() {
proptest!(|(
certs1: Vec<(u64, u64)>,
certs2: Vec<(u64, u64)>
)| {
let certs1: Vec<MockProgressCertificate> = certs1.into_iter()
.map(|(progress, timestamp)| MockProgressCertificate { progress, timestamp })
.collect();
let certs2: Vec<MockProgressCertificate> = certs2.into_iter()
.map(|(progress, timestamp)| MockProgressCertificate { progress, timestamp })
.collect();
if certs1.is_empty() || certs2.is_empty() {
return Ok(());
}
let merged1 = MockProgressCertificate::merge(&certs1);
let merged2 = MockProgressCertificate::merge(&certs2);
let mut combined = certs1.clone();
combined.extend(certs2);
let merged_combined = MockProgressCertificate::merge(&combined);
prop_assert!(
merged_combined.progress >= merged1.progress.max(merged2.progress),
"Progress monotonicity violated: combined.progress={}, max(merge1.progress={}, merge2.progress={})={}",
merged_combined.progress, merged1.progress, merged2.progress,
merged1.progress.max(merged2.progress)
);
});
}
#[test]
fn test_mr_symbol_cancel_idempotency() {
proptest!(|(
symbol_id: u32,
reason: String,
repeat_count in 1u32..=10
)| {
let request = MockSymbolCancelRequest { symbol_id, reason };
let single_result = request.cancel();
let repeated_result = request.cancel_repeated(repeat_count);
prop_assert_eq!(
single_result, repeated_result,
"Cancel idempotency violated: single={}, repeated({}times)={}",
single_result, repeat_count, repeated_result
);
});
}
#[test]
fn test_mr_scope_close_quiescence() {
proptest!(|(
scope_id: u32,
initial_task_count: u32
)| {
let mut scope = MockScope {
id: scope_id,
task_count: initial_task_count,
closed: false,
};
let can_close = scope.close();
let is_quiescent = scope.is_quiescent();
prop_assert_eq!(
can_close, is_quiescent,
"Scope close/quiescence equivalence violated: can_close={}, is_quiescent={}, task_count={}",
can_close, is_quiescent, scope.task_count
);
if can_close {
prop_assert_eq!(scope.task_count, 0, "Closed scope should have zero tasks");
}
});
}
#[test]
fn test_mr_macaroon_attenuation_lossless() {
proptest!(|(
authority: Vec<String>,
initial_caveats: Vec<String>,
new_caveat: String,
check_authority: String
)| {
let original = MockMacaroon {
authority: authority.clone(),
caveats: initial_caveats,
};
let attenuated = original.attenuate(&new_caveat);
let original_has_auth = original.check_authority(&check_authority);
let attenuated_has_auth = attenuated.check_authority(&check_authority);
let caveat_denies = new_caveat == format!("deny:{}", check_authority);
if original_has_auth && !caveat_denies {
prop_assert!(
attenuated_has_auth,
"Macaroon attenuation lost authority: original={}, attenuated={}, authority='{}', caveat='{}'",
original_has_auth, attenuated_has_auth, check_authority, new_caveat
);
}
prop_assert_eq!(attenuated.authority, original.authority, "Authority list should be preserved");
});
}
#[test]
fn test_mr_registry_commit_permit_invariant() {
proptest!(|(
initial_permits: Vec<u32>,
permit_to_commit: u32
)| {
let mut registry = MockRegistryState {
permits: initial_permits,
committed: false,
};
let initial_invariant = registry.invariant_holds();
let commit_result = registry.commit_permit(permit_to_commit);
let final_invariant = registry.invariant_holds();
if initial_invariant {
prop_assert!(
final_invariant,
"Registry invariant violated: initial={}, final={}, commit_result={}, permits={:?}",
initial_invariant, final_invariant, commit_result, registry.permits
);
}
if commit_result {
prop_assert!(final_invariant, "Successful commit should maintain invariant");
prop_assert!(registry.committed, "Successful commit should set committed flag");
}
});
}
#[test]
fn test_mr_state_transition_determinism() {
proptest!(|(
regions: Vec<u32>,
tasks: Vec<u32>,
initial_phase in 0u8..8,
event1 in 0u8..8,
event2 in 0u8..8
)| {
let state1 = MockRuntimeState {
regions: regions.clone(),
tasks: tasks.clone(),
phase: initial_phase,
};
let state2 = state1.clone();
let result1 = state1.transition(event1);
let result2 = state2.transition(event1);
let result3 = state1.transition(event2);
prop_assert_eq!(
&result1, &result2,
"State transition non-deterministic: state1→{:?}, state2→{:?}",
result1, result2
);
prop_assert_eq!(
result1.deterministic_hash(), result2.deterministic_hash(),
"Hash determinism violated"
);
if event1 != event2 {
let may_differ = result1.phase != result3.phase;
prop_assert!(
may_differ || result1 == result3,
"Different events should potentially produce different results"
);
}
});
}
#[test]
fn test_mr_region_close_ordering() {
proptest!(|(
mut regions_data: Vec<(u32, Vec<u32>)>
)| {
regions_data.dedup_by_key(|(id, _)| *id);
if regions_data.len() < 2 {
return Ok(());
}
let regions: Vec<MockRegion> = regions_data.iter().map(|(id, children)| {
MockRegion {
id: *id,
children: children.clone(),
closed: false,
}
}).collect();
let mut shuffled = regions.clone();
let rotation = shuffled.len() / 2;
shuffled.rotate_left(rotation);
let order1 = MockRegion::close_ordered(®ions);
let order2 = MockRegion::close_ordered(&shuffled);
prop_assert_eq!(
&order1, &order2,
"Region close order should be deterministic: original={:?}, shuffled={:?}",
order1, order2
);
for region in ®ions {
for &child_id in ®ion.children {
if let (Some(parent_pos), Some(child_pos)) =
(order1.iter().position(|&id| id == region.id),
order1.iter().position(|&id| id == child_id)) {
prop_assert!(
child_pos < parent_pos,
"Child {} should close before parent {} (positions: child={}, parent={})",
child_id, region.id, child_pos, parent_pos
);
}
}
}
});
}
#[test]
fn test_mr_task_lifecycle_invariants() {
proptest!(|(
task_id: u32,
region_id: u32,
initial_state_idx in 0usize..4,
target_state_idx in 0usize..4
)| {
let states = [TaskState::Created, TaskState::Running, TaskState::Cancelled, TaskState::Completed];
let initial_state = states[initial_state_idx].clone();
let target_state = states[target_state_idx].clone();
let task = MockTask {
id: task_id,
state: initial_state.clone(),
region_id,
};
let transition_result = task.transition(target_state.clone());
let valid_transitions = MockTask::valid_transitions();
let is_valid_transition = valid_transitions.contains(&(initial_state.clone(), target_state.clone()));
prop_assert_eq!(
transition_result.is_some(), is_valid_transition,
"Task lifecycle invariant violated: {:?}→{:?} validity={}, result={}",
initial_state, target_state, is_valid_transition, transition_result.is_some()
);
if let Some(new_task) = transition_result {
prop_assert_eq!(new_task.state, target_state, "Transition should update state");
prop_assert_eq!(new_task.id, task.id, "ID should be preserved");
prop_assert_eq!(new_task.region_id, task.region_id, "Region should be preserved");
}
});
}
#[test]
fn test_mr_mpsc_message_ordering() {
proptest!(|(
messages_data: Vec<(u32, String, u64)>
)| {
let mut messages: Vec<MockMessage> = messages_data.into_iter()
.map(|(id, content, sequence)| MockMessage { id, content, sequence })
.collect();
if messages.len() < 2 {
return Ok(());
}
messages.sort_by_key(|m| m.sequence);
let send_order = MockMessage::mpsc_ordering(&messages);
let receive_order = send_order.clone();
prop_assert_eq!(
&send_order, &receive_order,
"MPSC ordering violated: send={:?}, receive={:?}",
send_order, receive_order
);
let is_monotonic = send_order.windows(2).all(|pair| pair[0] <= pair[1]);
prop_assert!(is_monotonic, "Message sequences should be monotonic");
});
}
#[test]
fn test_mr_broadcast_lag_bound() {
proptest!(|(
messages_data: Vec<(u32, String, u64)>,
initial_receivers: Vec<u32>,
additional_receivers: Vec<u32>,
lag_bound in 1u32..=100
)| {
let messages: Vec<MockMessage> = messages_data
.into_iter()
.map(|(id, content, sequence)| MockMessage { id, content, sequence })
.collect();
let initial_receiver_count = initial_receivers.len();
let mut broadcast_state = MockBroadcastState {
messages,
receivers: initial_receivers,
lag_counts: vec![0; initial_receiver_count],
};
for receiver_id in additional_receivers {
broadcast_state.add_receiver(receiver_id);
}
for lag in &mut broadcast_state.lag_counts {
*lag = (*lag).min(lag_bound);
}
let within_bounds = broadcast_state.lag_bound(lag_bound);
prop_assert!(
within_bounds,
"Broadcast lag bound violated: max_lag={}, bound={}, lags={:?}",
broadcast_state.lag_counts.iter().max().unwrap_or(&0),
lag_bound,
broadcast_state.lag_counts
);
let max_lag = broadcast_state.lag_counts.iter().max().copied().unwrap_or(0);
prop_assert!(
max_lag <= lag_bound,
"Max lag {} exceeds bound {}", max_lag, lag_bound
);
});
}
#[test]
fn test_mr_watch_coalescing() {
proptest!(|(
initial_value: i32,
updates: Vec<i32>
)| {
if updates.is_empty() {
return Ok(());
}
let mut watch_state = MockWatchState {
value: initial_value,
version: 0,
coalesced_updates: vec![],
};
watch_state.coalesce_updates(&updates);
prop_assert!(
watch_state.coalescing_preserves_final_value(&updates),
"Watch coalescing failed to preserve final value: updates={:?}, final_value={}",
updates, watch_state.value
);
prop_assert_eq!(
watch_state.version, updates.len() as u64,
"Version should track update count"
);
prop_assert_eq!(
watch_state.coalesced_updates.len(), 1,
"Coalescing should produce single update"
);
if let Some(&last_update) = updates.last() {
prop_assert_eq!(
watch_state.value, last_update,
"Final value should match last update"
);
}
});
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mock_implementations() {
let cert = MockProgressCertificate {
progress: 10,
timestamp: 100,
};
let advanced = cert.advance(5);
assert_eq!(advanced.progress, 15);
assert_eq!(advanced.timestamp, 101);
let request = MockSymbolCancelRequest {
symbol_id: 1,
reason: "timeout".to_string(),
};
assert!(request.cancel());
assert!(request.cancel_repeated(3));
let mut scope = MockScope {
id: 1,
task_count: 0,
closed: false,
};
assert!(scope.close());
assert!(scope.is_quiescent());
}
}