use reifydb_codec::row::{
bytes::{QUEUE_DEDUPLICATION_HEADER_SIZE, RowBuilder, SHAPE_HEADER_SIZE},
queue_deduplication::EncodedQueueDeduplicationRow,
shape::{RowFamily, RowShape, RowShapeField},
};
use reifydb_value::{
encoding::LeBytes,
value::{datetime::DateTime, row_number::RowNumber, value_type::ValueType},
};
fn shape() -> RowShape {
RowShape::new(RowFamily::QueueDeduplication, vec![])
}
#[test]
fn the_deduplication_header_is_the_source_header_plus_row_number_and_expires_at() {
assert_eq!(
QUEUE_DEDUPLICATION_HEADER_SIZE,
SHAPE_HEADER_SIZE + RowNumber::ENCODED_SIZE + DateTime::ENCODED_SIZE
);
assert_eq!(QUEUE_DEDUPLICATION_HEADER_SIZE, 49);
assert_eq!(shape().header_size(), QUEUE_DEDUPLICATION_HEADER_SIZE);
}
#[test]
fn a_field_less_shape_carries_no_bitvec_and_ends_at_the_header() {
let shape = shape();
assert_eq!(shape.bitvec_size(), 0);
assert_eq!(shape.data_offset(), QUEUE_DEDUPLICATION_HEADER_SIZE);
assert_eq!(shape.allocate_queue_deduplication().freeze().as_slice().len(), QUEUE_DEDUPLICATION_HEADER_SIZE);
}
#[test]
fn both_header_facts_survive_a_freeze() {
let mut row = shape().allocate_queue_deduplication();
row.set_row_number(RowNumber(4_294_967_297));
row.set_expires_at(DateTime::from_nanos(1_234_567_890));
let frozen = row.freeze();
assert_eq!(frozen.row_number(), RowNumber(4_294_967_297));
assert_eq!(frozen.expires_at(), DateTime::from_nanos(1_234_567_890));
}
#[test]
fn the_row_number_and_the_expiry_occupy_disjoint_slots() {
let mut row = shape().allocate_queue_deduplication();
row.set_row_number(RowNumber(u64::MAX));
row.set_expires_at(DateTime::from_nanos(0));
assert_eq!(row.row_number(), RowNumber(u64::MAX));
assert_eq!(row.expires_at(), DateTime::from_nanos(0));
row.set_row_number(RowNumber(0));
row.set_expires_at(DateTime::from_nanos(i64::MAX as u64));
assert_eq!(row.row_number(), RowNumber(0));
assert_eq!(row.expires_at(), DateTime::from_nanos(i64::MAX as u64));
}
#[test]
fn a_view_over_raw_bytes_reads_the_same_header_facts() {
let mut row = shape().allocate_queue_deduplication();
row.set_row_number(RowNumber(77));
row.set_expires_at(DateTime::from_nanos(7));
let bytes = row.freeze_bytes();
let viewed = EncodedQueueDeduplicationRow::view(&bytes);
assert_eq!(viewed.row_number(), RowNumber(77));
assert_eq!(viewed.expires_at(), DateTime::from_nanos(7));
}
#[test]
fn the_header_facts_are_always_present_and_never_absent() {
let row = shape().allocate_queue_deduplication().freeze();
assert_eq!(row.row_number(), RowNumber(0));
assert_eq!(row.expires_at(), DateTime::from_nanos(0));
}
#[test]
fn a_freshly_allocated_row_already_carries_the_shape_it_was_allocated_from() {
let shape = shape();
let row = shape.allocate_queue_deduplication().freeze();
assert_eq!(row.fingerprint(), shape.fingerprint());
assert_ne!(row.fingerprint(), RowShape::new(RowFamily::Queue, vec![]).fingerprint());
}
#[test]
fn the_wall_clock_stamps_survive_a_freeze_and_stay_disjoint() {
let mut row = shape().allocate_queue_deduplication();
row.set_timestamps(DateTime::from_nanos(11), DateTime::from_nanos(22));
let frozen = row.freeze();
assert_eq!(frozen.created_at(), DateTime::from_nanos(11));
assert_eq!(frozen.updated_at(), DateTime::from_nanos(22));
}
#[test]
fn a_row_handed_to_storage_and_read_back_is_the_same_row() {
let mut row = shape().allocate_queue_deduplication();
row.set_row_number(RowNumber(31));
row.set_expires_at(DateTime::from_nanos(7));
let original = row.freeze();
let restored = EncodedQueueDeduplicationRow::from(original.clone().into_bytes());
assert_eq!(restored, original);
assert_eq!(restored.row_number(), RowNumber(31));
assert_eq!(restored.expires_at(), DateTime::from_nanos(7));
}
#[test]
fn thawing_a_claim_extends_its_expiry_without_moving_the_row_number() {
let mut row = shape().allocate_queue_deduplication();
row.set_timestamps(DateTime::from_nanos(1), DateTime::from_nanos(1));
row.set_row_number(RowNumber(4_294_967_297));
row.set_expires_at(DateTime::from_nanos(1_000));
let frozen = row.freeze();
let mut thawed = frozen.thaw();
assert_eq!(thawed.row_number(), RowNumber(4_294_967_297), "the claim must survive the round trip");
thawed.set_expires_at(DateTime::from_nanos(2_000));
let refrozen = thawed.freeze();
assert_eq!(refrozen.row_number(), RowNumber(4_294_967_297), "extending a claim must never repoint it");
assert_eq!(refrozen.expires_at(), DateTime::from_nanos(2_000));
assert_eq!(refrozen.created_at(), DateTime::from_nanos(1));
assert_eq!(refrozen.as_slice().len(), QUEUE_DEDUPLICATION_HEADER_SIZE, "a body-less record must not grow");
}
#[test]
#[should_panic(expected = "allocate_queue_deduplication on a shape of another family")]
fn a_shape_of_another_family_cannot_allocate_a_deduplication_row() {
RowShape::new(RowFamily::Pod, vec![RowShapeField::unconstrained("key", ValueType::Utf8)])
.allocate_queue_deduplication();
}