use zipora::entropy::{
FseEncoder, FseDecoder, FseConfig, FseTable,
fse_compress, fse_decompress, fse_compress_with_config, fse_decompress_with_config
};
use zipora::compression::dict_zip::compression_types::{
apply_fse_compression, remove_fse_compression,
fse_zip_reference, fse_unzip_reference,
FseConfig as PaZipFseConfig, FseCompressor
};
use zipora::error::ZiporaError;
#[test]
fn test_fse_basic_functionality() {
let config = FseConfig::default();
assert!(config.validate().is_ok());
let encoder_result = FseEncoder::new(config.clone());
#[cfg(feature = "zstd")]
{
let mut encoder = encoder_result.unwrap();
let decoder = FseDecoder::new();
let empty_compressed = encoder.compress(b"").unwrap();
assert!(empty_compressed.is_empty());
let small_data = b"hello";
let small_compressed = encoder.compress(small_data).unwrap();
assert!(!small_compressed.is_empty());
}
#[cfg(not(feature = "zstd"))]
{
assert!(encoder_result.is_ok());
}
}
#[test]
fn test_fse_config_presets() {
let fast = FseConfig::fast_compression();
let high = FseConfig::high_compression();
let balanced = FseConfig::balanced();
let realtime = FseConfig::realtime();
assert!(fast.validate().is_ok());
assert!(high.validate().is_ok());
assert!(balanced.validate().is_ok());
assert!(realtime.validate().is_ok());
assert!(fast.table_log <= balanced.table_log);
assert!(balanced.table_log <= high.table_log);
assert!(realtime.table_log <= fast.table_log);
assert!(fast.compression_level <= balanced.compression_level);
assert!(balanced.compression_level <= high.compression_level);
assert!(realtime.compression_level <= fast.compression_level);
assert!(high.dict_size >= balanced.dict_size);
assert!(balanced.dict_size >= fast.dict_size);
assert!(!realtime.adaptive);
assert!(realtime.fast_decode);
}
#[test]
#[cfg(feature = "zstd")]
fn test_fse_table_creation() {
let mut frequencies = [0u32; 256];
frequencies[b'a' as usize] = 1000;
frequencies[b'b' as usize] = 500;
frequencies[b'c' as usize] = 250;
frequencies[b'd' as usize] = 125;
frequencies[b'e' as usize] = 125;
let config = FseConfig::default();
let table_result = FseTable::new(&frequencies, &config);
assert!(table_result.is_ok());
let table = table_result.unwrap();
assert_eq!(table.table_log, config.table_log);
assert_eq!(table.max_symbol, b'e');
assert!(!table.states.is_empty());
assert_eq!(table.states.len(), 1 << config.table_log);
for symbol in [b'a', b'b', b'c', b'd', b'e'] {
if let Some((new_state, nb_bits)) = table.encode_symbol(symbol, 1024) {
assert!(nb_bits <= 16); assert!(new_state > 0);
}
}
let zero_frequencies = [0u32; 256];
let invalid_table = FseTable::new(&zero_frequencies, &config);
assert!(invalid_table.is_err());
}
#[test]
#[cfg(feature = "zstd")]
fn test_fse_compression_data_types() {
let mut encoder = FseEncoder::new(FseConfig::balanced()).unwrap();
let mut decoder = FseDecoder::new();
let test_cases = vec![
b"The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.".to_vec(),
vec![0x00, 0x01, 0x02, 0x03].repeat(50),
vec![b'A'; 200],
b"AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ".to_vec(),
(0..=255).collect::<Vec<u8>>(),
];
for (i, data) in test_cases.iter().enumerate() {
println!("Testing data type {}: {} bytes", i, data.len());
let compressed = encoder.compress(data).unwrap();
let decompressed = decoder.decompress(&compressed).unwrap();
assert_eq!(data, &decompressed, "Roundtrip failed for test case {}", i);
let stats = encoder.stats();
assert_eq!(stats.input_size, data.len());
assert_eq!(stats.output_size, compressed.len());
assert!(stats.entropy >= 0.0);
println!(" Compression ratio: {:.3}", stats.compression_ratio);
println!(" Entropy: {:.3} bits", stats.entropy);
println!(" Efficiency: {:.3}", stats.efficiency);
}
}
#[test]
#[cfg(feature = "zstd")]
fn test_fse_with_dictionary() {
let dictionary = b"The quick brown fox jumps over the lazy dog".to_vec();
let config = FseConfig::high_compression();
let mut encoder = FseEncoder::with_dictionary(config.clone(), dictionary.clone()).unwrap();
let mut decoder = FseDecoder::with_config(config).unwrap();
let test_data = b"The quick brown fox runs fast over the lazy cat";
let compressed = encoder.compress(test_data).unwrap();
let decompressed = decoder.decompress(&compressed).unwrap();
assert_eq!(test_data, &decompressed[..]);
let stats = encoder.stats();
println!("Dictionary compression ratio: {:.3}", stats.compression_ratio);
println!("Dictionary efficiency: {:.3}", stats.efficiency);
}
#[test]
fn test_fse_convenience_functions() {
let test_data = b"FSE convenience function test data with some patterns and repetition";
let compressed = fse_compress(test_data);
#[cfg(feature = "zstd")]
{
let compressed = compressed.unwrap();
let decompressed = fse_decompress(&compressed).unwrap();
assert_eq!(test_data, &decompressed[..]);
let config = FseConfig::fast_compression();
let custom_compressed = fse_compress_with_config(test_data, config).unwrap();
let custom_decompressed = fse_decompress_with_config(&custom_compressed, FseConfig::fast_compression()).unwrap();
assert_eq!(test_data, &custom_decompressed[..]);
}
#[cfg(not(feature = "zstd"))]
{
assert!(compressed.is_ok());
}
}
#[test]
fn test_entropy_algorithm_selection() {
#[cfg(feature = "zstd")]
{
let config = FseConfig::default();
let encoder_result = FseEncoder::new(config);
assert!(encoder_result.is_ok());
}
#[cfg(not(feature = "zstd"))]
{
let config = FseConfig::default();
let encoder_result = FseEncoder::new(config);
assert!(encoder_result.is_ok()); }
}
#[test]
fn test_auto_algorithm_selection() {
let repetitive_data = b"AAAAAAAAAA".repeat(100);
#[cfg(feature = "zstd")]
{
let mut encoder = FseEncoder::new(FseConfig::balanced()).unwrap();
let compressed = encoder.compress(&repetitive_data).unwrap();
assert!(!compressed.is_empty());
let stats = encoder.stats();
assert!(stats.compression_ratio < 0.5); }
let random_data: Vec<u8> = (0..=255).collect();
#[cfg(feature = "zstd")]
{
let mut encoder = FseEncoder::new(FseConfig::balanced()).unwrap();
let compressed = encoder.compress(&random_data).unwrap();
assert!(!compressed.is_empty());
let stats = encoder.stats();
assert!(stats.compression_ratio > 0.8); }
}
#[test]
fn test_universal_entropy_encoder() {
let test_data = b"Universal entropy encoder test data with various patterns";
#[cfg(feature = "zstd")]
{
let mut encoder = FseEncoder::new(FseConfig::balanced()).unwrap();
let mut decoder = FseDecoder::new();
let compressed = encoder.compress(test_data).unwrap();
let decompressed = decoder.decompress(&compressed).unwrap();
assert_eq!(test_data, &decompressed[..]);
}
#[cfg(not(feature = "zstd"))]
{
let compressed = fse_compress(test_data).unwrap_or_default();
assert!(!compressed.is_empty() || test_data.is_empty());
}
}
#[test]
fn test_pa_zip_fse_integration() {
let test_data = b"PA-Zip FSE integration test with encoded bit stream simulation";
let config = PaZipFseConfig::for_pa_zip();
assert_eq!(config.table_log, 11);
assert_eq!(config.compression_level, 6);
let compressed = apply_fse_compression(test_data, &config).unwrap();
let decompressed = remove_fse_compression(&compressed, &config).unwrap();
#[cfg(feature = "zstd")]
{
assert_eq!(test_data, &decompressed[..]);
if test_data.len() > 32 {
assert!(compressed.len() <= test_data.len() + 2);
}
}
#[cfg(not(feature = "zstd"))]
{
assert!(!compressed.is_empty());
}
let fast_config = PaZipFseConfig::fast_pa_zip();
assert_eq!(fast_config.table_log, 9);
assert_eq!(fast_config.compression_level, 1);
assert!(!fast_config.adaptive);
assert!(fast_config.fast_decode);
let fast_compressed = apply_fse_compression(test_data, &fast_config).unwrap();
let fast_decompressed = remove_fse_compression(&fast_compressed, &fast_config).unwrap();
#[cfg(feature = "zstd")]
{
assert_eq!(test_data, &fast_decompressed[..]);
}
}
#[test]
fn test_fse_reference_compatibility() {
let test_data = b"Reference implementation compatibility test data with patterns";
let mut compressed_buffer = vec![0u8; test_data.len() * 2];
let mut compressed_size = 0;
let compress_result = fse_zip_reference(test_data, &mut compressed_buffer, &mut compressed_size);
assert!(compress_result.is_ok());
#[cfg(feature = "zstd")]
{
if let Ok(true) = compress_result {
assert!(compressed_size > 0);
assert!(compressed_size <= test_data.len());
let mut decompressed_buffer = vec![0u8; test_data.len() * 2];
let decompressed_size = fse_unzip_reference(
&compressed_buffer[..compressed_size],
&mut decompressed_buffer
).unwrap();
assert_eq!(decompressed_size, test_data.len());
assert_eq!(&decompressed_buffer[..decompressed_size], test_data);
}
}
let small_data = b"ab";
let small_result = fse_zip_reference(small_data, &mut compressed_buffer, &mut compressed_size);
assert!(small_result.is_ok());
assert_eq!(small_result.unwrap(), false);
let tiny_data = b"a";
let tiny_result = fse_zip_reference(tiny_data, &mut compressed_buffer, &mut compressed_size);
assert!(tiny_result.is_ok());
assert_eq!(tiny_result.unwrap(), false);
}
#[test]
#[cfg(feature = "zstd")]
fn test_fse_compressor_state() {
let config = PaZipFseConfig::for_pa_zip();
let result = FseCompressor::with_config(config);
#[cfg(feature = "zstd")]
{
let mut compressor = result.unwrap();
let test_data = b"FSE compressor state management test data";
let compressed1 = compressor.compress(test_data).unwrap();
let decompressed1 = compressor.decompress(&compressed1).unwrap();
assert_eq!(&decompressed1, test_data);
if let Some(stats) = compressor.stats() {
assert_eq!(stats.input_size, test_data.len());
assert!(stats.entropy >= 0.0);
}
compressor.reset().unwrap();
let compressed2 = compressor.compress(test_data).unwrap();
let decompressed2 = compressor.decompress(&compressed2).unwrap();
assert_eq!(&decompressed2, test_data);
let empty_compressed = compressor.compress(b"").unwrap();
assert!(empty_compressed.is_empty());
let empty_decompressed = compressor.decompress(&empty_compressed).unwrap();
assert!(empty_decompressed.is_empty());
}
#[cfg(not(feature = "zstd"))]
{
assert!(result.is_ok());
}
}
#[test]
fn test_fse_error_handling() {
let invalid_config = FseConfig {
table_log: 25, max_symbol: 70000, compression_level: 30, ..Default::default()
};
assert!(invalid_config.validate().is_err());
let encoder_result = FseEncoder::new(invalid_config);
assert!(encoder_result.is_err());
let test_data = b"test data for buffer overflow testing";
let mut small_buffer = vec![0u8; 5]; let mut compressed_size = 0;
let result = fse_zip_reference(test_data, &mut small_buffer, &mut compressed_size);
#[cfg(feature = "zstd")]
{
if result.is_err() {
assert!(format!("{:?}", result).contains("buffer"));
}
}
}
#[test]
#[cfg(feature = "zstd")]
fn test_fse_data_sizes() {
let mut encoder = FseEncoder::new(FseConfig::balanced()).unwrap();
let mut decoder = FseDecoder::new();
let test_sizes = vec![
0, 1, 2, 10, 100, 1000, 10000, ];
for size in test_sizes {
println!("Testing size: {} bytes", size);
let test_data = if size == 0 {
Vec::new()
} else if size <= 2 {
vec![b'A'; size]
} else {
"ABCDEF".repeat((size + 5) / 6)[..size].as_bytes().to_vec()
};
let compressed = encoder.compress(&test_data).unwrap();
if size == 0 {
assert!(compressed.is_empty());
} else {
let decompressed = decoder.decompress(&compressed).unwrap();
assert_eq!(test_data, decompressed);
let stats = encoder.stats();
println!(" Ratio: {:.3}, Entropy: {:.3}", stats.compression_ratio, stats.entropy);
}
}
}
#[test]
#[cfg(feature = "zstd")]
fn bench_fse_performance() {
use std::time::Instant;
let mut encoder = FseEncoder::new(FseConfig::balanced()).unwrap();
let mut decoder = FseDecoder::new();
let test_data = "The quick brown fox jumps over the lazy dog. ".repeat(2000);
let data = test_data.as_bytes();
println!("FSE Performance Benchmark");
println!("Data size: {} bytes", data.len());
let start = Instant::now();
let compressed = encoder.compress(data).unwrap();
let compress_time = start.elapsed();
let compress_speed = (data.len() as f64 / 1024.0 / 1024.0) / compress_time.as_secs_f64();
let start = Instant::now();
let decompressed = decoder.decompress(&compressed).unwrap();
let decompress_time = start.elapsed();
let decompress_speed = (decompressed.len() as f64 / 1024.0 / 1024.0) / decompress_time.as_secs_f64();
assert_eq!(data, &decompressed[..]);
let stats = encoder.stats();
println!("Results:");
println!(" Compression ratio: {:.3}", stats.compression_ratio);
println!(" Entropy: {:.3} bits", stats.entropy);
println!(" Efficiency: {:.3}", stats.efficiency);
println!(" Compression speed: {:.2} MB/s", compress_speed);
println!(" Decompression speed: {:.2} MB/s", decompress_speed);
println!(" Compressed size: {} bytes", compressed.len());
assert!(compress_speed > 1.0); assert!(decompress_speed > 1.0); assert!(stats.compression_ratio < 1.0); assert!(stats.efficiency > 0.5); }
#[test]
fn test_fse_cross_module_integration() {
let entropy_compressed = fse_compress(b"entropy module test").unwrap_or_default();
let pa_zip_config = PaZipFseConfig::for_pa_zip();
let pa_zip_compressed = apply_fse_compression(b"pa-zip module test", &pa_zip_config).unwrap();
assert!(!entropy_compressed.is_empty() || cfg!(not(feature = "zstd")));
assert!(!pa_zip_compressed.is_empty());
let entropy_config = FseConfig::balanced();
let pa_zip_config_default = PaZipFseConfig::default();
assert!(entropy_config.validate().is_ok());
#[cfg(feature = "zstd")]
{
let config = FseConfig::balanced();
let encoder_result = FseEncoder::new(config);
assert!(encoder_result.is_ok());
}
}