use aok::{OK, Void};
use log::info;
use wrecord::{
CollectionType, CompactHash, CompactHashCodec, CompactSet, CompactSetCodec, CompactZSet,
CompactZSetCodec, FieldValueRef, HashEntryRef, META_VALUE_SIZE, MetaValue, StorageEncoding,
ZSetEntryRef, encode_order_preserving_f64,
};
#[ctor::ctor(unsafe)]
fn _log_init() {
log_init::init();
}
#[test]
fn test_meta_value_storage_encoding() -> Void {
info!("测试 MetaValue 的 StorageEncoding 扩展与二进制兼容性");
let mut meta = MetaValue::new(1001, CollectionType::Hash, 1, 0);
assert_eq!(meta.encoding(), StorageEncoding::Compact);
assert_eq!(meta.reserved[0], 0);
meta.set_encoding(StorageEncoding::Flattened);
assert_eq!(meta.encoding(), StorageEncoding::Flattened);
assert_eq!(meta.reserved[0], 1);
let bytes = meta.to_bytes();
assert_eq!(bytes.len(), META_VALUE_SIZE);
assert_eq!(bytes[9], 1);
let restored = MetaValue::from_bytes(bytes)?;
assert_eq!(restored.encoding(), StorageEncoding::Flattened);
assert_eq!(restored, meta);
meta.set_encoding(StorageEncoding::Compact);
assert_eq!(meta.encoding(), StorageEncoding::Compact);
let bytes2 = meta.to_bytes();
assert_eq!(bytes2[9], 0);
let restored2 = MetaValue::from_bytes(bytes2)?;
assert_eq!(restored2.encoding(), StorageEncoding::Compact);
OK
}
#[test]
fn test_compact_hash_encode_decode() -> Void {
info!("测试 CompactHashCodec 基础编码与解码(含过期时间)");
let entries = [
(b"user".as_slice(), b"alice".as_slice(), None),
(
b"token".as_slice(),
b"jwt_secret_token_value".as_slice(),
Some(1_700_000_000_000_u64),
),
(b"role".as_slice(), b"admin".as_slice(), None),
];
let encoded = CompactHashCodec::encode(entries.iter().copied())?;
assert_eq!(CompactHashCodec::count(&encoded)?, 3);
let decoded: Vec<HashEntryRef> = CompactHashCodec::iter_fields(&encoded).collect();
assert_eq!(decoded.len(), 3);
assert_eq!(decoded[0].field, b"user");
assert_eq!(decoded[0].value, b"alice");
assert_eq!(decoded[0].expire_at_ms, None);
assert_eq!(decoded[1].field, b"token");
assert_eq!(decoded[1].value, b"jwt_secret_token_value");
assert_eq!(decoded[1].expire_at_ms, Some(1_700_000_000_000_u64));
assert_eq!(decoded[2].field, b"role");
assert_eq!(decoded[2].value, b"admin");
assert_eq!(decoded[2].expire_at_ms, None);
OK
}
#[test]
fn test_compact_hash_find_field_zero_alloc() -> Void {
info!("测试 CompactHashCodec 零堆分配切片就地查找");
let mut buf = Vec::new();
CompactHashCodec::set_field(&mut buf, b"k1", b"v1", None)?;
CompactHashCodec::set_field(&mut buf, b"k2", b"v2_with_expire", Some(999_888_777))?;
CompactHashCodec::set_field(&mut buf, b"k3", b"v3", None)?;
assert_eq!(
CompactHashCodec::find_field(&buf, b"k1"),
Some(b"v1".as_slice())
);
assert_eq!(
CompactHashCodec::find_field(&buf, b"k2"),
Some(b"v2_with_expire".as_slice())
);
assert_eq!(
CompactHashCodec::find_field(&buf, b"k3"),
Some(b"v3".as_slice())
);
assert_eq!(CompactHashCodec::find_field(&buf, b"k4"), None);
let ref1: FieldValueRef<'_> = CompactHashCodec::find(&buf, b"k1").expect("k1 应该存在");
assert_eq!(ref1.value, b"v1");
assert_eq!(ref1.expire_at_ms, None);
assert_eq!(&*ref1, b"v1");
let ref2: FieldValueRef<'_> = CompactHashCodec::find(&buf, b"k2").expect("k2 应该存在");
assert_eq!(ref2.value, b"v2_with_expire");
assert_eq!(ref2.expire_at_ms, Some(999_888_777));
assert!(CompactHashCodec::find(&buf, b"not_found").is_none());
OK
}
#[test]
fn test_compact_hash_set_field_update_and_append() -> Void {
info!("测试 CompactHash 字段追加与原地/变长更新");
let mut hash = CompactHash::new();
assert!(hash.is_empty());
assert_eq!(hash.len(), 0);
assert!(hash.set_field(b"name", b"alice", None)?); assert_eq!(hash.len(), 1);
assert_eq!(hash.find_field(b"name"), Some(b"alice".as_slice()));
assert!(hash.set_field(b"city", b"beijing", None)?);
assert_eq!(hash.len(), 2);
assert!(!hash.set_field(b"name", b"clark", None)?); assert_eq!(hash.len(), 2);
assert_eq!(hash.find_field(b"name"), Some(b"clark".as_slice()));
assert!(!hash.set_field(b"name", b"alexander_the_great", None)?);
assert_eq!(hash.len(), 2);
assert_eq!(
hash.find_field(b"name"),
Some(b"alexander_the_great".as_slice())
);
assert_eq!(hash.find_field(b"city"), Some(b"beijing".as_slice()));
assert!(!hash.set_field(b"name", b"al", None)?);
assert_eq!(hash.len(), 2);
assert_eq!(hash.find_field(b"name"), Some(b"al".as_slice()));
assert_eq!(hash.find_field(b"city"), Some(b"beijing".as_slice()));
assert!(!hash.set_field(b"city", b"shanghai", Some(12345678))?);
let city_ref = hash.find(b"city").expect("city 应存在");
assert_eq!(city_ref.value, b"shanghai");
assert_eq!(city_ref.expire_at_ms, Some(12345678));
OK
}
#[test]
fn test_compact_hash_delete_field() -> Void {
info!("测试 CompactHash 字段删除");
let mut hash = CompactHash::new();
hash.set_field(b"k1", b"v1", None)?;
hash.set_field(b"k2", b"v2", None)?;
hash.set_field(b"k3", b"v3", None)?;
assert_eq!(hash.len(), 3);
assert!(!hash.delete_field(b"k_none")?);
assert_eq!(hash.len(), 3);
assert!(hash.delete_field(b"k2")?);
assert_eq!(hash.len(), 2);
assert_eq!(hash.find_field(b"k1"), Some(b"v1".as_slice()));
assert_eq!(hash.find_field(b"k2"), None);
assert_eq!(hash.find_field(b"k3"), Some(b"v3".as_slice()));
assert!(hash.delete_field(b"k1")?);
assert_eq!(hash.len(), 1);
assert_eq!(hash.find_field(b"k1"), None);
assert_eq!(hash.find_field(b"k3"), Some(b"v3".as_slice()));
assert!(hash.delete_field(b"k3")?);
assert_eq!(hash.len(), 0);
assert!(hash.is_empty());
assert_eq!(hash.find_field(b"k3"), None);
OK
}
#[test]
fn test_compact_hash_iter_fields() -> Void {
info!("测试 CompactHash 全量迭代");
let mut buf = Vec::new();
for i in 0..10 {
let k = format!("key_{:02}", i);
let v = format!("val_{:02}", i);
CompactHashCodec::set_field(&mut buf, k.as_bytes(), v.as_bytes(), None)?;
}
let mut count = 0;
for (idx, entry) in CompactHashCodec::iter_fields(&buf).enumerate() {
let expected_k = format!("key_{:02}", idx);
let expected_v = format!("val_{:02}", idx);
assert_eq!(entry.field, expected_k.as_bytes());
assert_eq!(entry.value, expected_v.as_bytes());
assert_eq!(entry.expire_at_ms, None);
count += 1;
}
assert_eq!(count, 10);
OK
}
#[test]
fn test_compact_hash_boundary_limits() -> Void {
info!("测试 CompactHash 极限边界:空、单字段、512 满载、重复覆盖");
let empty_buf = vec![0, 0];
assert_eq!(CompactHashCodec::count(&empty_buf)?, 0);
assert_eq!(CompactHashCodec::find_field(&empty_buf, b"any"), None);
assert_eq!(CompactHashCodec::iter_fields(&empty_buf).count(), 0);
let mut hash = CompactHash::new();
hash.set_field(b"solo", b"value", None)?;
assert_eq!(hash.len(), 1);
assert_eq!(hash.find_field(b"solo"), Some(b"value".as_slice()));
let mut big_hash = CompactHash::with_capacity(16384);
for i in 0..512 {
let k = format!("f_{:04}", i);
let v = format!("v_{:04}", i);
let inserted = big_hash.set_field(k.as_bytes(), v.as_bytes(), None)?;
assert!(inserted);
}
assert_eq!(big_hash.len(), 512);
assert_eq!(big_hash.find_field(b"f_0000"), Some(b"v_0000".as_slice()));
assert_eq!(big_hash.find_field(b"f_0255"), Some(b"v_0255".as_slice()));
assert_eq!(big_hash.find_field(b"f_0511"), Some(b"v_0511".as_slice()));
assert_eq!(big_hash.find_field(b"f_0512"), None);
assert_eq!(big_hash.iter_fields().count(), 512);
for i in 0..100 {
let v = format!("updated_{}", i);
let inserted = big_hash.set_field(b"f_0000", v.as_bytes(), None)?;
assert!(!inserted); }
assert_eq!(big_hash.len(), 512);
assert_eq!(
big_hash.find_field(b"f_0000"),
Some(b"updated_99".as_slice())
);
OK
}
#[test]
fn test_compact_set_ordered_insert_and_dedup() -> Void {
info!("测试 CompactSetCodec 有序插入与去重");
let mut set = CompactSet::new();
assert!(set.is_empty());
assert_eq!(set.len(), 0);
assert!(set.insert(b"banana")?);
assert!(set.insert(b"apple")?);
assert!(set.insert(b"date")?);
assert!(set.insert(b"cherry")?);
assert_eq!(set.len(), 4);
assert!(!set.insert(b"apple")?);
assert!(!set.insert(b"banana")?);
assert_eq!(set.len(), 4);
let members: Vec<&[u8]> = set.iter_members().collect();
assert_eq!(
members,
vec![
b"apple".as_slice(),
b"banana".as_slice(),
b"cherry".as_slice(),
b"date".as_slice()
]
);
OK
}
#[test]
fn test_compact_set_binary_search_contains() -> Void {
info!("测试 CompactSetCodec 零堆分配二分查找 contains");
let mut buf = Vec::new();
CompactSetCodec::insert(&mut buf, b"car")?;
CompactSetCodec::insert(&mut buf, b"boat")?;
CompactSetCodec::insert(&mut buf, b"plane")?;
CompactSetCodec::insert(&mut buf, b"train")?;
assert!(CompactSetCodec::contains(&buf, b"boat"));
assert!(CompactSetCodec::contains(&buf, b"car"));
assert!(CompactSetCodec::contains(&buf, b"plane"));
assert!(CompactSetCodec::contains(&buf, b"train"));
assert!(!CompactSetCodec::contains(&buf, b"airplane"));
assert!(!CompactSetCodec::contains(&buf, b"bus"));
assert!(!CompactSetCodec::contains(&buf, b"rocket"));
assert!(!CompactSetCodec::contains(&buf, b"zebra"));
OK
}
#[test]
fn test_compact_set_remove() -> Void {
info!("测试 CompactSetCodec 成员二分定位与删除");
let mut set = CompactSet::new();
set.insert(b"m1")?;
set.insert(b"m2")?;
set.insert(b"m3")?;
set.insert(b"m4")?;
assert_eq!(set.len(), 4);
assert!(!set.remove(b"m0")?);
assert!(!set.remove(b"m5")?);
assert_eq!(set.len(), 4);
assert!(set.remove(b"m2")?);
assert_eq!(set.len(), 3);
assert!(!set.contains(b"m2"));
assert!(set.contains(b"m1"));
assert!(set.contains(b"m3"));
assert!(set.contains(b"m4"));
assert!(set.remove(b"m1")?);
assert_eq!(set.len(), 2);
assert!(!set.contains(b"m1"));
assert!(set.remove(b"m4")?);
assert_eq!(set.len(), 1);
assert!(!set.contains(b"m4"));
assert!(set.contains(b"m3"));
assert!(set.remove(b"m3")?);
assert_eq!(set.len(), 0);
assert!(set.is_empty());
OK
}
#[test]
fn test_compact_set_iter_members() -> Void {
info!("测试 CompactSetCodec 全量迭代");
let mut buf = Vec::new();
for i in (0..20).rev() {
let s = format!("user_{:03}", i);
CompactSetCodec::insert(&mut buf, s.as_bytes())?;
}
assert_eq!(CompactSetCodec::count(&buf)?, 20);
let members: Vec<String> = CompactSetCodec::iter_members(&buf)
.map(|m| String::from_utf8(m.to_vec()).unwrap())
.collect();
for (i, member) in members.iter().enumerate().take(20) {
let expected = format!("user_{:03}", i);
assert_eq!(member, &expected);
}
OK
}
#[test]
fn test_compact_set_boundary_limits() -> Void {
info!("测试 CompactSet 极限边界:空、单元素、128 满载");
let empty = vec![0, 0];
assert_eq!(CompactSetCodec::count(&empty)?, 0);
assert!(!CompactSetCodec::contains(&empty, b"x"));
assert_eq!(CompactSetCodec::iter_members(&empty).count(), 0);
let mut single = CompactSet::new();
assert!(single.insert(b"only_one")?);
assert_eq!(single.len(), 1);
assert!(single.contains(b"only_one"));
assert!(!single.contains(b"other"));
assert!(single.remove(b"only_one")?);
assert_eq!(single.len(), 0);
let mut full_set = CompactSet::with_capacity(4096);
for i in 0..128 {
let s = format!("member_{:03}", i);
assert!(full_set.insert(s.as_bytes())?);
}
assert_eq!(full_set.len(), 128);
for i in 0..128 {
let s = format!("member_{:03}", i);
assert!(full_set.contains(s.as_bytes()));
}
assert!(!full_set.contains(b"member_128"));
assert_eq!(full_set.iter_members().count(), 128);
OK
}
#[test]
fn test_compact_set_binary_search_accuracy() -> Void {
info!("测试 CompactSetCodec 与 CompactSet 二分查找准确率与插入点定位");
let mut set = CompactSet::new();
set.insert(b"banana")?;
set.insert(b"apple")?;
set.insert(b"date")?;
set.insert(b"cherry")?;
assert_eq!(set.binary_search(b"apple")?, Ok(0));
assert_eq!(set.binary_search(b"banana")?, Ok(1));
assert_eq!(set.binary_search(b"cherry")?, Ok(2));
assert_eq!(set.binary_search(b"date")?, Ok(3));
assert_eq!(set.binary_search(b"aaa")?, Err(0));
assert_eq!(set.binary_search(b"bb")?, Err(2));
assert_eq!(set.binary_search(b"cz")?, Err(3));
assert_eq!(set.binary_search(b"zzz")?, Err(4));
OK
}
#[test]
fn test_compact_set_validate_and_batch_encode() -> Void {
info!("测试 CompactSetCodec validate 异常数据拦截与 batch encode 排序去重");
let raw_members = vec![
b"zebra".as_slice(),
b"apple".as_slice(),
b"banana".as_slice(),
b"apple".as_slice(), b"cherry".as_slice(),
b"banana".as_slice(), ];
let encoded = CompactSetCodec::encode(raw_members)?;
let decoded = CompactSet::from_vec(encoded)?;
assert_eq!(decoded.len(), 4);
let decoded_items: Vec<&[u8]> = decoded.iter_members().collect();
assert_eq!(
decoded_items,
vec![
b"apple".as_slice(),
b"banana".as_slice(),
b"cherry".as_slice(),
b"zebra".as_slice(),
]
);
let mut bad_buf = Vec::new();
bad_buf.extend_from_slice(&2u16.to_be_bytes());
bad_buf.extend_from_slice(&(b"zoo".len() as u16).to_be_bytes());
bad_buf.extend_from_slice(b"zoo");
bad_buf.extend_from_slice(&(b"ant".len() as u16).to_be_bytes());
bad_buf.extend_from_slice(b"ant");
assert!(CompactSet::from_vec(bad_buf).is_err());
let truncated_buf = vec![0, 1, 0, 5, b'a', b'b'];
assert!(CompactSet::from_vec(truncated_buf).is_err());
OK
}
#[test]
fn test_compact_zset_score_ordering_and_tie_breaker() -> Void {
info!("测试 CompactZSet 按分值递增及同分字典序(tie-breaker)排序");
let mut zset = CompactZSet::new();
zset.insert(10.0, b"charlie")?;
zset.insert(5.0, b"bob")?;
zset.insert(20.0, b"david")?;
zset.insert(10.0, b"alice")?;
zset.insert(10.0, b"zach")?;
assert_eq!(zset.len(), 5);
let entries: Vec<ZSetEntryRef> = zset.iter_members().collect();
assert_eq!(entries.len(), 5);
assert_eq!(entries[0].score, 5.0);
assert_eq!(entries[0].member, b"bob");
assert_eq!(entries[1].score, 10.0);
assert_eq!(entries[1].member, b"alice");
assert_eq!(entries[2].score, 10.0);
assert_eq!(entries[2].member, b"charlie");
assert_eq!(entries[3].score, 10.0);
assert_eq!(entries[3].member, b"zach");
assert_eq!(entries[4].score, 20.0);
assert_eq!(entries[4].member, b"david");
OK
}
#[test]
fn test_compact_zset_binary_search_entry() -> Void {
info!("测试 CompactZSetCodec::binary_search_entry 按 (分值, 成员) 复合键二分定位");
let mut zset = CompactZSet::new();
zset.insert(5.0, b"bob")?;
zset.insert(10.0, b"alice")?;
zset.insert(10.0, b"charlie")?;
zset.insert(20.0, b"david")?;
let alice = CompactZSetCodec::binary_search_entry(
zset.as_slice(),
encode_order_preserving_f64(10.0),
b"alice",
)?;
assert_eq!(alice, Ok(1));
let david = CompactZSetCodec::binary_search_entry(
zset.as_slice(),
encode_order_preserving_f64(20.0),
b"david",
)?;
assert_eq!(david, Ok(3));
let charlie = CompactZSetCodec::binary_search_entry(
zset.as_slice(),
encode_order_preserving_f64(10.0),
b"charlie",
)?;
assert_eq!(charlie, Ok(2));
let absent = CompactZSetCodec::binary_search_entry(
zset.as_slice(),
encode_order_preserving_f64(10.0),
b"bob",
)?;
assert_eq!(absent, Err(2));
let tail = CompactZSetCodec::binary_search_entry(
zset.as_slice(),
encode_order_preserving_f64(30.0),
b"eve",
)?;
assert_eq!(tail, Err(4));
let empty = CompactZSet::new();
let hit = CompactZSetCodec::binary_search_entry(
empty.as_slice(),
encode_order_preserving_f64(1.0),
b"any",
)?;
assert_eq!(hit, Err(0));
OK
}
#[test]
fn test_compact_zset_rank_and_key_at_rank() -> Void {
info!("测试 CompactZSet 排名计算 (rank_of) 与按排名提取 (key_at_rank)");
let mut zset = CompactZSet::new();
zset.insert(100.0, b"p1")?;
zset.insert(200.0, b"p2")?;
zset.insert(300.0, b"p3")?;
zset.insert(400.0, b"p4")?;
zset.insert(500.0, b"p5")?;
assert_eq!(zset.rank_of(b"p1"), Some(0));
assert_eq!(zset.rank_of(b"p2"), Some(1));
assert_eq!(zset.rank_of(b"p3"), Some(2));
assert_eq!(zset.rank_of(b"p4"), Some(3));
assert_eq!(zset.rank_of(b"p5"), Some(4));
assert_eq!(zset.rank_of(b"p_unknown"), None);
assert_eq!(CompactZSetCodec::rank_of(&zset, b"p1"), Some(0));
assert_eq!(
CompactZSetCodec::key_at_rank(&zset, 0),
Some(b"p1".as_slice())
);
assert_eq!(CompactZSetCodec::count_range(&zset, 150.0, 450.0), 3);
assert_eq!(zset.key_at_rank(0), Some(b"p1".as_slice()));
assert_eq!(zset.key_at_rank(1), Some(b"p2".as_slice()));
assert_eq!(zset.key_at_rank(2), Some(b"p3".as_slice()));
assert_eq!(zset.key_at_rank(3), Some(b"p4".as_slice()));
assert_eq!(zset.key_at_rank(4), Some(b"p5".as_slice()));
assert_eq!(zset.key_at_rank(5), None);
assert_eq!(zset.score_of(b"p1"), Some(100.0));
assert_eq!(zset.score_of(b"p3"), Some(300.0));
assert_eq!(zset.score_of(b"none"), None);
OK
}
#[test]
fn test_compact_zset_insert_update_and_delete() -> Void {
info!("测试 CompactZSet 插入、分值更新导致的重排序以及删除");
let mut zset = CompactZSet::new();
assert!(zset.insert(10.0, b"player")?);
assert!(zset.insert(20.0, b"other")?);
assert_eq!(zset.rank_of(b"player"), Some(0));
assert!(!zset.insert(30.0, b"player")?); assert_eq!(zset.len(), 2);
assert_eq!(zset.score_of(b"player"), Some(30.0));
assert_eq!(zset.rank_of(b"player"), Some(1));
assert_eq!(zset.key_at_rank(0), Some(b"other".as_slice()));
assert_eq!(zset.key_at_rank(1), Some(b"player".as_slice()));
assert!(!zset.insert(5.0, b"player")?);
assert_eq!(zset.score_of(b"player"), Some(5.0));
assert_eq!(zset.rank_of(b"player"), Some(0));
assert_eq!(zset.key_at_rank(0), Some(b"player".as_slice()));
assert!(zset.remove(b"player")?);
assert_eq!(zset.len(), 1);
assert_eq!(zset.rank_of(b"player"), None);
assert_eq!(zset.score_of(b"player"), None);
assert!(!zset.remove(b"player")?);
assert_eq!(zset.len(), 1);
OK
}
#[test]
fn test_compact_zset_count_range_and_streaming_iter() -> Void {
info!("测试 CompactZSet count_range 区间统计与流式切片迭代");
let mut zset = CompactZSet::new();
zset.insert(10.0, b"m10")?;
zset.insert(20.0, b"m20")?;
zset.insert(30.0, b"m30")?;
zset.insert(40.0, b"m40")?;
zset.insert(50.0, b"m50")?;
assert_eq!(zset.count_range(20.0, 40.0), 3);
assert_eq!(zset.count_range(15.0, 45.0), 3);
assert_eq!(zset.count_range(25.0, 35.0), 1);
assert_eq!(zset.count_range(0.0, 100.0), 5);
assert_eq!(zset.count_range(60.0, 100.0), 0);
assert_eq!(zset.count_range(50.0, 100.0), 1);
assert_eq!(zset.count_range(50.0, 10.0), 0);
let range_items: Vec<ZSetEntryRef> = zset.range(20.0, 40.0).collect();
assert_eq!(range_items.len(), 3);
assert_eq!(range_items[0].member, b"m20");
assert_eq!(range_items[1].member, b"m30");
assert_eq!(range_items[2].member, b"m40");
OK
}
#[test]
fn test_compact_zset_extreme_floats_and_boundaries() -> Void {
info!("测试 CompactZSet 极端浮点数(负无穷、正无穷、-0.0 vs +0.0)与 128 满载");
let mut zset = CompactZSet::new();
zset.insert(f64::INFINITY, b"pos_inf")?;
zset.insert(f64::NEG_INFINITY, b"neg_inf")?;
zset.insert(0.0, b"plus_zero")?;
zset.insert(-0.0, b"minus_zero")?;
zset.insert(-1000.0, b"neg_thousand")?;
zset.insert(1000.0, b"pos_thousand")?;
assert_eq!(zset.len(), 6);
let items: Vec<ZSetEntryRef> = zset.iter_members().collect();
assert_eq!(items[0].member, b"neg_inf");
assert_eq!(items[0].score, f64::NEG_INFINITY);
assert_eq!(items[1].member, b"neg_thousand");
assert_eq!(items[1].score, -1000.0);
assert_eq!(items[2].member, b"minus_zero");
assert_eq!(items[2].score.to_bits(), (-0.0_f64).to_bits());
assert_eq!(items[3].member, b"plus_zero");
assert_eq!(items[3].score.to_bits(), 0.0_f64.to_bits());
assert_eq!(items[4].member, b"pos_thousand");
assert_eq!(items[4].score, 1000.0);
assert_eq!(items[5].member, b"pos_inf");
assert_eq!(items[5].score, f64::INFINITY);
let mut full_zset = CompactZSet::with_capacity(4096);
for i in 0..128 {
let m = format!("z_{:03}", i);
let score = (i as f64) * 1.5;
assert!(full_zset.insert(score, m.as_bytes())?);
}
assert_eq!(full_zset.len(), 128);
assert_eq!(full_zset.rank_of(b"z_000"), Some(0));
assert_eq!(full_zset.rank_of(b"z_127"), Some(127));
assert_eq!(full_zset.key_at_rank(0), Some(b"z_000".as_slice()));
assert_eq!(full_zset.key_at_rank(127), Some(b"z_127".as_slice()));
assert_eq!(full_zset.count_range(0.0, 150.0), 101);
OK
}
#[test]
fn test_compact_zset_redis_style_api() -> Void {
info!("测试 CompactZSet Redis 风格 API 与 Bitcode 往返");
let mut zset = CompactZSet::new();
for i in 0..5 {
let score = (i as f64) * 10.0;
let member = format!("m{i}").into_bytes();
assert!(zset.insert(score, &member)?);
}
let snapshot = CompactZSet::from_bytes(zset.as_bytes())?;
assert_eq!(snapshot.as_bytes(), zset.as_bytes());
assert_eq!(snapshot.zcard(), 5);
assert_eq!(snapshot.zcard(), snapshot.len());
assert_eq!(zset.zrank(b"m0"), Some(0));
assert_eq!(zset.zrank(b"m4"), Some(4));
assert_eq!(zset.zrevrank(b"m0"), Some(4));
assert_eq!(zset.zrevrank(b"m4"), Some(0));
assert_eq!(zset.zrevrank(b"missing"), None);
assert_eq!(zset.zscore(b"m2"), Some(20.0));
assert_eq!(zset.zscore(b"missing"), None);
let names = |v: Vec<(Vec<u8>, f64)>| -> Vec<String> {
v.iter()
.map(|(m, _)| String::from_utf8_lossy(m).to_string())
.collect()
};
assert_eq!(
names(zset.zrange(0, -1, false)),
vec!["m0", "m1", "m2", "m3", "m4"]
);
assert_eq!(
names(zset.zrange(0, -1, true)),
vec!["m4", "m3", "m2", "m1", "m0"]
);
assert_eq!(names(zset.zrange(-2, -1, false)), vec!["m3", "m4"]);
assert_eq!(names(zset.zrange(2, 10, false)), vec!["m2", "m3", "m4"]);
assert!(zset.zrange(5, 9, false).is_empty());
let (min_m, min_s) = zset.pop_min().expect("非空必可弹");
assert_eq!((min_m.as_slice(), min_s), (b"m0".as_slice(), 0.0));
let (max_m, max_s) = zset.pop_max().expect("非空必可弹");
assert_eq!((max_m.as_slice(), max_s), (b"m4".as_slice(), 40.0));
assert_eq!(zset.zcard(), 3);
assert_eq!(zset.zrank(b"m4"), None);
let restored = CompactZSet::from_bitcode(&zset.to_bitcode())?;
assert_eq!(restored.as_slice(), zset.as_slice());
let mut empty = CompactZSet::new();
assert!(empty.pop_min().is_none());
assert!(empty.pop_max().is_none());
assert_eq!(
CompactZSet::from_bitcode(&empty.to_bitcode())?.as_slice(),
&[0, 0]
);
OK
}
#[test]
fn test_compact_zset_batch_encode_dedup_and_order() -> Void {
info!("测试 CompactZSetCodec::encode 同成员覆盖与批量有序构建");
let entries = vec![
(5.0, b"a".as_slice()),
(1.0, b"b".as_slice()),
(9.0, b"a".as_slice()),
(3.0, b"c".as_slice()),
];
let buf = CompactZSetCodec::encode(entries)?;
let zset = CompactZSet::from_vec(buf)?;
assert_eq!(zset.len(), 3);
let items: Vec<(f64, &[u8])> = zset.iter_members().map(|e| (e.score, e.member)).collect();
assert_eq!(
items,
vec![
(1.0, b"b".as_slice()),
(3.0, b"c".as_slice()),
(9.0, b"a".as_slice())
]
);
let empty = CompactZSetCodec::encode(Vec::<(f64, &[u8])>::new())?;
assert_eq!(empty.len(), 2);
assert_eq!(CompactZSetCodec::count(&empty)?, 0);
OK
}