use spate_core::ops::ChunkConfig;
use spate_core::record::{PartitionId, RawPayload, stable_key_hash};
use spate_core::sink::{KeyHashRouter, ShardRouter};
use std::collections::BTreeSet;
#[path = "../benches/support/ack_traffic.rs"]
mod ack_traffic;
#[path = "../benches/support/chain_rig.rs"]
mod chain_rig;
#[path = "../benches/support/poll_traffic.rs"]
mod poll_traffic;
#[path = "../benches/support/split_rig.rs"]
mod split_rig;
use ack_traffic::{BATCHES, Order, PARTITIONS};
use chain_rig::{BATCH, BORROWED_BATCH_BYTES, Routing};
use poll_traffic::{ITERATIONS, Profile};
use split_rig::{PAYLOADS, Tags};
fn digest(bytes: &[u8]) -> u64 {
let mut hash = 0xcbf2_9ce4_8422_2325_u64;
for &byte in bytes {
hash ^= u64::from(byte);
hash = hash.wrapping_mul(0x1000_0000_01b3);
}
hash
}
fn pin(bytes: &[u8]) -> (usize, u64) {
(bytes.len(), digest(bytes))
}
fn chain_payloads(routing: Routing) -> Vec<u8> {
chain_rig::corpus(routing).payloads().concat()
}
fn chain_keys(routing: Routing) -> Vec<u8> {
chain_rig::corpus(routing).keys().concat()
}
fn split_payloads(tags: Tags) -> Vec<u8> {
split_rig::corpus(tags).concat()
}
fn ack_schedule(per_tick: usize, order: Order) -> Vec<u8> {
ack_traffic::rig(per_tick, order).corpus()
}
fn poll_script(profile: Profile) -> Vec<u8> {
poll_traffic::rig(profile, expected_transitions(profile)).corpus()
}
fn expected_transitions(profile: Profile) -> usize {
match profile {
Profile::Quiet => 0,
Profile::Congested => 1,
Profile::Flapping => 2048,
}
}
fn meta_for(key: Option<&[u8]>) -> spate_core::record::RecordMeta {
RawPayload {
bytes: b"",
key,
partition: PartitionId(0),
offset: 0,
timestamp_ms: 0,
}
.meta()
}
#[test]
fn the_corpora_are_reproducible() {
for routing in [Routing::Fixed, Routing::KeyHash] {
assert_eq!(chain_payloads(routing), chain_payloads(routing));
assert_eq!(chain_keys(routing), chain_keys(routing));
}
for tags in [
Tags::TwoBranches,
Tags::FourBranches,
Tags::FourBranchesQuarterUnrouted,
] {
assert_eq!(split_payloads(tags), split_payloads(tags));
}
for order in [Order::Issued, Order::Scrambled] {
assert_eq!(ack_schedule(256, order), ack_schedule(256, order));
}
for profile in [Profile::Quiet, Profile::Congested, Profile::Flapping] {
assert_eq!(poll_script(profile), poll_script(profile));
}
}
#[test]
fn the_corpora_are_pinned_across_revisions() {
assert_eq!(
pin(&chain_payloads(Routing::Fixed)),
(19_968, 0x8945_1814_bc2e_0e09),
"chain payloads"
);
assert_eq!(
pin(&chain_keys(Routing::KeyHash)),
(4_096, 0x12b9_8fcc_2436_7301),
"chain keys"
);
assert!(
chain_keys(Routing::Fixed).is_empty(),
"the keyless corpus grew keys, so `Routing::Fixed` is no longer keyless"
);
assert_eq!(
pin(&split_payloads(Tags::TwoBranches)),
(229_376, 0x258a_6632_fbdb_f559),
"split two_branches"
);
assert_eq!(
pin(&split_payloads(Tags::FourBranches)),
(229_376, 0x1102_1f17_7a54_6f19),
"split four_branches"
);
assert_eq!(
pin(&split_payloads(Tags::FourBranchesQuarterUnrouted)),
(229_376, 0xab84_8eab_a083_7129),
"split four_branches_quarter_unrouted"
);
assert_eq!(
pin(&ack_schedule(256, Order::Issued)),
ACK_SCHEDULE_PIN,
"ack schedule"
);
assert_eq!(
pin(&poll_script(Profile::Quiet)),
POLL_QUIET_PIN,
"poll quiet script"
);
assert_eq!(
pin(&poll_script(Profile::Congested)),
POLL_CONGESTED_PIN,
"poll congested script"
);
assert_eq!(
pin(&poll_script(Profile::Flapping)),
POLL_FLAPPING_PIN,
"poll flapping script"
);
}
const ACK_SCHEDULE_PIN: (usize, u64) = (98_304, 0xb805_bf3f_d145_a605);
const POLL_QUIET_PIN: (usize, u64) = (589_824, 0x6605_f527_400e_e502);
const POLL_CONGESTED_PIN: (usize, u64) = (589_824, 0x79e5_ec3b_66f3_72c5);
const POLL_FLAPPING_PIN: (usize, u64) = (589_824, 0xe3fb_64f3_9e0d_2545);
#[test]
fn each_corpus_is_the_length_its_constants_imply() {
assert_eq!(
ACK_SCHEDULE_PIN.0,
BATCHES * (4 + 8),
"the schedule is one partition and one offset per batch"
);
assert_eq!(
POLL_QUIET_PIN.0,
ITERATIONS * (8 + 8 + 1 + 1),
"the script is one add, sub, rejection and queue reading per iteration"
);
assert_eq!(POLL_QUIET_PIN.0, POLL_CONGESTED_PIN.0);
assert_eq!(POLL_QUIET_PIN.0, POLL_FLAPPING_PIN.0);
}
#[test]
fn the_ack_schedule_is_independent_of_tick_width_and_driver() {
let wide = ack_schedule(256, Order::Issued);
assert_eq!(wide, ack_schedule(16, Order::Issued), "tick width");
assert_eq!(
wide,
ack_schedule(256, Order::Scrambled),
"resolution order is a property of the driver, not the corpus"
);
for threads in [1, 2, 4] {
assert_eq!(
wide,
ack_traffic::threaded(256, Order::Issued, threads).corpus(),
"the {threads}-thread driver issues a different schedule"
);
}
}
#[test]
fn the_routing_axis_changes_only_the_keys() {
assert_eq!(
chain_payloads(Routing::Fixed),
chain_payloads(Routing::KeyHash),
"the two routings no longer share a payload corpus"
);
}
#[test]
fn every_element_is_the_declared_width() {
let payloads = chain_rig::corpus(Routing::KeyHash);
for payload in payloads.payloads() {
assert_eq!(payload.len(), 39, "a chain payload is not 39 bytes");
}
for key in payloads.keys() {
assert_eq!(key.len(), 8, "a chain key is not 8 bytes");
}
assert_eq!(payloads.payloads().len(), BATCH);
assert_eq!(payloads.keys().len(), BATCH);
for tags in [
Tags::TwoBranches,
Tags::FourBranches,
Tags::FourBranchesQuarterUnrouted,
] {
let corpus = split_rig::corpus(tags);
assert_eq!(corpus.len(), PAYLOADS);
for payload in &corpus {
assert_eq!(payload.len(), 28, "a split payload is not 28 bytes");
}
}
}
#[test]
fn the_split_corpora_are_the_same_quantity_of_bytes() {
let two = split_payloads(Tags::TwoBranches).len();
assert_eq!(two, split_payloads(Tags::FourBranches).len());
assert_eq!(two, split_payloads(Tags::FourBranchesQuarterUnrouted).len());
}
#[test]
fn the_chain_emits_the_row_counts_the_counters_declare() {
assert_eq!(chain_rig::borrowed_rig().drive(), 1536, "borrowed rows");
assert_eq!(chain_rig::owned_rig().drive(), 512, "owned rows");
}
#[test]
fn the_split_rigs_produce_the_rows_they_expect() {
let mut two = split_rig::two_branch_rig();
assert_eq!(two.drive(), two.expect_rows, "two_branches");
assert_eq!(two.expect_rows, PAYLOADS);
let mut four = split_rig::four_branch_rig(Tags::FourBranches);
assert_eq!(four.drive(), four.expect_rows, "four_branches");
assert_eq!(four.expect_rows, PAYLOADS);
let mut partial = split_rig::four_branch_rig(Tags::FourBranchesQuarterUnrouted);
assert_eq!(partial.drive(), partial.expect_rows, "quarter_unrouted");
assert_eq!(
partial.expect_rows,
PAYLOADS - PAYLOADS / 4,
"the unrouted share is not the quarter the case name claims"
);
}
#[test]
fn a_second_drive_is_the_same_work_as_the_first() {
for per_tick in [16, 256] {
for order in [Order::Issued, Order::Scrambled] {
let mut rig = ack_traffic::rig(per_tick, order);
for drive in 1..=3 {
assert_eq!(
rig.drive(),
rig.expect_watermarks,
"ack drive {drive} at per_tick {per_tick}"
);
assert_eq!(rig.pending(), 0, "ack pending after drive {drive}");
}
}
}
for profile in [Profile::Quiet, Profile::Congested, Profile::Flapping] {
let expect = expected_transitions(profile);
let mut rig = poll_traffic::rig(profile, expect);
let mut settled = Vec::new();
for drive in 1..=3 {
rig.reset();
assert_eq!(rig.usage(), 0, "poll budget after reset {drive}");
assert_eq!(rig.drive(), expect, "poll drive {drive}");
settled.push(rig.usage());
}
assert!(
settled[0] > 0,
"a drive left the budget at zero, so it moved nothing"
);
assert!(
settled.windows(2).all(|w| w[0] == w[1]),
"a drive left the budget somewhere its predecessor did not: {settled:?}"
);
}
}
#[test]
fn the_backpressure_rig_drifts_without_a_reset() {
let mut congested = poll_traffic::rig(Profile::Congested, 1);
assert_eq!(congested.drive(), 1, "the first drive crosses into a pause");
assert_eq!(
congested.drive(),
0,
"a second drive without a reset should find the controller still \
paused; if this now reports 1, the controller's state no longer \
survives a drive and `reset` may have stopped being needed"
);
let mut quiet = poll_traffic::rig(Profile::Quiet, 0);
let counts: Vec<usize> = (0..6).map(|_| quiet.drive()).collect();
assert_eq!(
counts[0], 0,
"the first drive is the quiet profile by construction"
);
assert!(
counts.iter().any(|&n| n > 0),
"the quiet script should climb out of its band without a reset, and \
did not in six drives ({counts:?}); if the budget's movements are no \
longer relative, the reason `reset` exists has changed"
);
}
#[test]
fn the_threaded_driver_agrees_with_the_single_threaded_one() {
let mut plain = ack_traffic::rig(256, Order::Issued);
let expect = plain.drive();
assert_eq!(expect, plain.expect_watermarks);
for threads in [1, 2, 4] {
let mut rig = ack_traffic::threaded(256, Order::Issued, threads);
for drive in 1..=3 {
assert_eq!(
rig.drive(),
expect,
"{threads} threads, drive {drive}: a different number of \
watermark pairs than the single-threaded driver produces"
);
assert_eq!(rig.pending(), 0, "{threads} threads, drive {drive}");
}
assert_eq!(
rig.expect_watermarks, plain.expect_watermarks,
"the thread count moved the expected watermark total, so the \
cases are no longer measuring one axis"
);
}
}
#[test]
fn a_thread_count_must_divide_the_partitions() {
let Err(panic) = std::panic::catch_unwind(|| ack_traffic::threaded(256, Order::Issued, 3))
else {
panic!("three threads over {PARTITIONS} partitions was accepted");
};
let message = panic
.downcast_ref::<String>()
.map(String::as_str)
.or_else(|| panic.downcast_ref::<&str>().copied())
.unwrap_or_default();
assert!(
message.contains("do not divide"),
"the builder panicked for some other reason: {message}"
);
}
#[test]
fn the_scramble_window_is_a_workers_share_of_a_tick() {
for threads in [1, 2, 4] {
let mut rig = ack_traffic::threaded(256, Order::Scrambled, threads);
for drive in 1..=2 {
assert_eq!(
rig.drive(),
rig.expect_watermarks,
"{threads} threads scrambled, drive {drive}"
);
assert_eq!(rig.pending(), 0, "{threads} threads scrambled");
}
}
}
#[test]
fn every_chunk_target_seals_on_a_record_boundary() {
assert_eq!(
BORROWED_BATCH_BYTES, 25_088,
"the batch's encoding moved, so every chunk target divides something else"
);
for divisor in [2, 4, 16] {
let mut rig =
chain_rig::borrowed_rig_with(Routing::Fixed, 1, BORROWED_BATCH_BYTES / divisor);
assert_eq!(rig.drive(), 1536, "chunk target 1/{divisor}");
}
assert!(
ChunkConfig::default().target_bytes > BORROWED_BATCH_BYTES,
"the default chunk target no longer clears a whole batch, so the \
baseline cases seal mid-push like the chunk cases do"
);
}
#[test]
fn the_keyed_corpus_spreads_and_the_keyless_one_does_not() {
for shards in [1, 4, 16] {
let mut rig = chain_rig::borrowed_rig_with(
Routing::KeyHash,
shards,
ChunkConfig::default().target_bytes,
);
assert_eq!(rig.drive(), 1536, "{shards} shards");
}
let keyless = meta_for(None);
for shards in [1, 4, 16] {
assert_eq!(
KeyHashRouter.route(&keyless, shards),
0,
"a keyless record no longer routes to shard 0, so `Routing::Fixed` \
is not the controlled baseline the keyed cases are read against"
);
}
}
#[test]
fn the_keys_hash_to_distinct_values() {
let corpus = chain_rig::corpus(Routing::KeyHash);
let hashes: BTreeSet<u64> = corpus.keys().iter().map(|k| stable_key_hash(k)).collect();
assert_eq!(hashes.len(), BATCH, "the keyed corpus has hash collisions");
let residues: BTreeSet<usize> = corpus
.keys()
.iter()
.map(|k| KeyHashRouter.route(&meta_for(Some(k)), 16))
.collect();
assert_eq!(residues.len(), 16, "the keys leave some of 16 shards empty");
}
#[test]
fn the_split_corpora_distribute_their_tags_as_claimed() {
let tally = |tags: Tags| {
let mut counts = [0usize; 5]; for payload in split_rig::corpus(tags) {
match payload[0] {
b'0'..=b'3' => counts[usize::from(payload[0] - b'0')] += 1,
_ => counts[4] += 1,
}
}
counts
};
assert_eq!(
tally(Tags::TwoBranches),
[4096, 4096, 0, 0, 0],
"two_branches is no longer an even split over exactly two branches"
);
assert_eq!(
tally(Tags::FourBranches),
[2048, 2048, 2048, 2048, 0],
"four_branches is no longer an even split over exactly four branches"
);
assert_eq!(
tally(Tags::FourBranchesQuarterUnrouted),
[1536, 1536, 1536, 1536, 2048],
"the unrouted payloads are not spread evenly, so this is not a \
match-rate case over four branches"
);
}