use crate::sink::WriteOutcome;
use proptest::prelude::*;
use spate_core::record::PartitionId;
use spate_core::source::LaneId;
use std::time::Duration;
pub fn payloads(max_items: usize, max_len: usize) -> impl Strategy<Value = Vec<Vec<u8>>> {
prop::collection::vec(
prop::collection::vec(any::<u8>(), 0..=max_len),
0..=max_items,
)
}
pub fn lane_layout(
max_lanes: usize,
max_partitions: u32,
) -> impl Strategy<Value = Vec<(LaneId, PartitionId)>> {
let all: Vec<u32> = (0..max_partitions).collect();
prop::sample::subsequence(all, 1..=max_lanes.min(max_partitions as usize)).prop_map(
|partitions| {
partitions
.into_iter()
.enumerate()
.map(|(i, p)| {
(
LaneId(u32::try_from(i).expect("dense lane id")),
PartitionId(p),
)
})
.collect()
},
)
}
#[derive(Clone, Debug)]
pub enum ScriptOp {
Push {
partition_index: usize,
payload: Vec<u8>,
},
Revoke {
lane_index: usize,
},
Assign {
lane_index: usize,
},
}
pub fn source_script(
max_ops: usize,
layout_len: usize,
max_payload_len: usize,
) -> impl Strategy<Value = Vec<ScriptOp>> {
let op = prop_oneof![
8 => (0..layout_len, prop::collection::vec(any::<u8>(), 0..=max_payload_len))
.prop_map(|(partition_index, payload)| ScriptOp::Push { partition_index, payload }),
1 => (0..layout_len).prop_map(|lane_index| ScriptOp::Revoke { lane_index }),
1 => (0..layout_len).prop_map(|lane_index| ScriptOp::Assign { lane_index }),
];
prop::collection::vec(op, 0..=max_ops)
}
pub fn write_outcomes(max: usize) -> impl Strategy<Value = Vec<WriteOutcome>> {
let outcome = prop_oneof![
8 => Just(WriteOutcome::ok()),
2 => Just(WriteOutcome::retryable("scripted retryable failure")),
1 => (1u64..50)
.prop_map(|ms| WriteOutcome::ok().after(Duration::from_millis(ms))),
1 => Just(WriteOutcome::fatal("scripted fatal failure")),
];
prop::collection::vec(outcome, 0..=max)
}