#![allow(clippy::module_name_repetitions)]
pub mod filter;
pub mod params;
pub mod bitvec;
pub use filter::{
BloomFilter,
MutableBloomFilter,
ConcurrentBloomFilter,
SharedBloomFilter,
DeletableBloomFilter,
MergeableBloomFilter,
ScalableBloomFilter,
};
pub use bitvec::BitVec;
pub use params::{
optimal_bit_count,
optimal_hash_count,
expected_fp_rate,
calculate_filter_params,
validate_params,
bits_per_element,
};
pub mod prelude {
pub use super::filter::{
BloomFilter,
ConcurrentBloomFilter,
SharedBloomFilter,
DeletableBloomFilter,
MergeableBloomFilter,
ScalableBloomFilter,
};
pub use super::params::{
optimal_bit_count,
optimal_hash_count,
calculate_filter_params,
};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_prelude_imports_compile() {
use prelude::*;
let _ = optimal_bit_count(1000, 0.01);
let _ = optimal_hash_count(9585, 1000);
}
#[test]
fn test_module_reexports() {
let bv = BitVec::new(100).expect("BitVec creation should succeed");
assert_eq!(bv.len(), 100);
let m = optimal_bit_count(1000, 0.01).unwrap();
assert!(m > 9500 && m < 9600);
}
#[test]
fn test_integration_params_and_bitvec() {
let n = 1000;
let fp_rate = 0.01;
let m = optimal_bit_count(n, fp_rate).unwrap();
let k = optimal_hash_count(m, n).unwrap();
let bv = BitVec::new(m).expect("BitVec creation should succeed");
assert_eq!(bv.len(), m);
assert!(k >= 5 && k <= 10);
}
#[test]
fn test_bitvec_basic_operations() {
let bv = BitVec::new(1000).expect("BitVec creation should succeed");
bv.set(42);
bv.set(100);
bv.set(999);
assert!(bv.get(42));
assert!(bv.get(100));
assert!(bv.get(999));
assert!(!bv.get(43));
assert_eq!(bv.count_ones(), 3);
}
#[test]
fn test_parameter_validation() {
assert!(validate_params(1000, 100, 7).is_ok());
assert!(validate_params(0, 100, 7).is_err());
assert!(validate_params(1000, 0, 7).is_err());
assert!(validate_params(1000, 100, 100).is_err());
}
#[test]
fn test_calculate_filter_params_consistency() {
let n = 5000;
let target_fp = 0.01;
let (m, k) = calculate_filter_params(n, target_fp).unwrap();
assert!(validate_params(m, n, k).is_ok());
let actual_fp = expected_fp_rate(m, n, k).unwrap();
assert!((actual_fp - target_fp).abs() / target_fp < 0.15);
}
#[test]
fn test_bits_per_element_calculation() {
let bpe = bits_per_element(0.01).unwrap();
assert!((bpe - 9.6).abs() < 0.1);
let n = 1000;
let m = optimal_bit_count(n, 0.01).unwrap();
let calculated_bpe = m as f64 / n as f64;
assert!((calculated_bpe - bpe).abs() < 0.1);
}
#[test]
fn test_bitvec_concurrent_safety() {
use std::sync::Arc;
use std::thread;
let bv = Arc::new(BitVec::new(10000).expect("BitVec creation should succeed"));
let mut handles = vec![];
for t in 0..8 {
let bv = Arc::clone(&bv);
let handle = thread::spawn(move || {
for i in 0..100 {
bv.set(t * 100 + i);
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
assert_eq!(bv.count_ones(), 800);
}
#[test]
fn test_expected_fp_rate_empty_filter() {
let fp = expected_fp_rate(1000, 0, 7).unwrap();
assert_eq!(fp, 0.0);
}
#[test]
fn test_expected_fp_rate_full_filter() {
let fp = expected_fp_rate(1000, 1000, 7).unwrap();
assert!(fp > 0.5);
}
#[test]
fn test_bitvec_set_multiple_and_test_all() {
let bv = BitVec::new(1000).expect("BitVec creation should succeed");
let indices = [10, 20, 30, 40, 50];
for &idx in &indices {
bv.set(idx);
}
assert!(indices.iter().all(|&idx| bv.get(idx)));
assert!(!bv.get(99));
}
#[test]
fn test_bitvec_union_operation() {
let bv1 = BitVec::new(1000).expect("BitVec creation should succeed");
let bv2 = BitVec::new(1000).expect("BitVec creation should succeed");
bv1.set(10);
bv1.set(20);
bv2.set(20);
bv2.set(30);
let result = bv1.union(&bv2).unwrap();
assert!(result.get(10));
assert!(result.get(20));
assert!(result.get(30));
assert_eq!(result.count_ones(), 3);
}
#[test]
fn test_bitvec_intersect_operation() {
let bv1 = BitVec::new(1000).expect("BitVec creation should succeed");
let bv2 = BitVec::new(1000).expect("BitVec creation should succeed");
bv1.set(10);
bv1.set(20);
bv1.set(30);
bv2.set(20);
bv2.set(30);
bv2.set(40);
let result = bv1.intersect(&bv2).unwrap();
assert!(!result.get(10)); assert!(result.get(20)); assert!(result.get(30)); assert!(!result.get(40));
assert_eq!(result.count_ones(), 2);
}
#[test]
fn test_bitvec_fill_fraction() {
let bv = BitVec::new(1000).expect("BitVec creation should succeed");
assert_eq!(bv.count_ones(), 0);
for i in 0..250 {
bv.set(i);
}
let one_fraction = bv.count_ones() as f64 / bv.len() as f64;
assert!((one_fraction - 0.25).abs() < 0.01);
}
#[test]
fn test_bitvec_clear() {
let mut bv = BitVec::new(1000).expect("BitVec creation should succeed");
bv.set(10);
bv.set(20);
bv.set(30);
assert_eq!(bv.count_ones(), 3);
bv.clear();
assert_eq!(bv.count_ones(), 0);
}
#[test]
fn test_bitvec_is_full() {
let bv = BitVec::new(64).expect("BitVec creation should succeed");
assert!(bv.count_ones() < bv.len());
for i in 0..64 {
bv.set(i);
}
assert_eq!(bv.count_ones(), bv.len());
}
#[test]
fn test_bitvec_memory_usage() {
let bv = BitVec::new(1000).expect("BitVec creation should succeed");
assert!(bv.memory_usage() >= 128);
let bv2 = BitVec::new(64).expect("BitVec creation should succeed");
assert!(bv2.memory_usage() >= 8);
}
#[test]
fn test_optimal_bit_count_various_fp_rates() {
let n = 1000;
let test_cases = vec![
(0.1, 4792),
(0.01, 9585),
(0.001, 14377),
(0.0001, 19170),
];
for (fp_rate, expected_m) in test_cases {
let m = optimal_bit_count(n, fp_rate).unwrap();
assert!(
(m as i32 - expected_m).abs() <= 1,
"For fp_rate={}, expected ~{}, got {}",
fp_rate,
expected_m,
m
);
}
}
#[test]
fn test_optimal_hash_count_various_ratios() {
let test_cases = vec![
(1000, 100, 7), (2000, 100, 14), (500, 100, 3), ];
for (m, n, expected_k) in test_cases {
let k = optimal_hash_count(m, n).unwrap();
assert_eq!(
k, expected_k,
"For m={}, n={}, expected k={}, got {}",
m, n, expected_k, k
);
}
}
#[test]
fn test_parameter_error_conditions() {
assert!(optimal_bit_count(0, 0.01).is_err());
assert!(optimal_bit_count(1000, 0.0).is_err());
assert!(optimal_bit_count(1000, 1.0).is_err());
assert!(optimal_bit_count(1000, -0.1).is_err());
assert!(optimal_bit_count(1000, 1.5).is_err());
assert!(optimal_hash_count(0, 1000).is_err());
assert!(expected_fp_rate(1000, 100, 0).is_err());
assert!(expected_fp_rate(1000, 100, 100).is_err());
}
#[test]
fn test_roundtrip_parameter_calculation() {
let n = 5000;
let target_fp = 0.005;
let (m, k) = calculate_filter_params(n, target_fp).unwrap();
let actual_fp = expected_fp_rate(m, n, k).unwrap();
let error = (actual_fp - target_fp).abs() / target_fp;
assert!(
error < 0.15,
"FP rate error {:.1}% exceeds 15%. Target: {}, Actual: {}",
error * 100.0,
target_fp,
actual_fp
);
}
#[test]
fn test_bitvec_alignment() {
let bv = BitVec::new(1000).expect("BitVec creation should succeed");
let ptr = &bv as *const _ as usize;
assert!(ptr % 8 == 0, "BitVec should be at least 8-byte aligned");
}
#[test]
fn test_bitvec_basic() {
let bv = BitVec::new(1000).expect("BitVec creation should succeed");
assert_eq!(bv.len(), 1000);
assert_eq!(bv.count_ones(), 0);
assert!(!bv.is_empty());
}
#[test]
fn test_mathematical_consistency() {
let n = 10000;
let fp_rate = 0.001;
let m = optimal_bit_count(n, fp_rate).unwrap();
let bpe = bits_per_element(fp_rate).unwrap();
let expected_m = (n as f64 * bpe).ceil() as usize;
assert_eq!(m, expected_m);
}
#[test]
fn test_validate_params_edge_cases() {
assert!(validate_params(1, 1, 1).is_ok());
assert!(validate_params(100, 1, 1).is_ok());
assert!(validate_params(5, 100, 10).is_err());
assert!(validate_params(100, 250, 7).is_err());
}
#[test]
fn test_validate_params_allows_moderate_saturation() {
assert!(validate_params(100, 150, 7).is_ok());
assert!(validate_params(100, 200, 7).is_ok());
}
}