use pklib::{explode_bytes, implode_bytes, CompressionMode, DictionarySize, ImplodeWriter};
use std::io::Write;
#[test]
fn test_basic_compression() -> Result<(), Box<dyn std::error::Error>> {
let test_data = b"Hello, World!";
let compressed = implode_bytes(test_data, CompressionMode::Binary, DictionarySize::Size2K)?;
assert!(!compressed.is_empty());
assert!(compressed.len() >= 3);
let compressed_ascii =
implode_bytes(test_data, CompressionMode::ASCII, DictionarySize::Size2K)?;
assert!(!compressed_ascii.is_empty());
assert!(compressed_ascii.len() >= 3);
println!("Original: {} bytes", test_data.len());
println!("Compressed (Binary): {} bytes", compressed.len());
println!("Compressed (ASCII): {} bytes", compressed_ascii.len());
Ok(())
}
#[test]
fn test_round_trip() -> Result<(), Box<dyn std::error::Error>> {
let test_data = b"Hello, World! This is a test of the PKLib compression system.";
for dict_size in [
DictionarySize::Size1K,
DictionarySize::Size2K,
DictionarySize::Size4K,
] {
for mode in [CompressionMode::Binary, CompressionMode::ASCII] {
println!("Testing {mode:?} mode with {dict_size:?} dictionary");
let compressed = implode_bytes(test_data, mode, dict_size)?;
let decompressed = explode_bytes(&compressed)?;
assert_eq!(
test_data,
&decompressed[..],
"Round-trip failed for {mode:?} mode with {dict_size:?} dictionary"
);
}
}
Ok(())
}
#[test]
fn test_streaming_compression() -> Result<(), Box<dyn std::error::Error>> {
let test_data = b"This is a longer test string that should demonstrate the streaming compression API working correctly.";
let mut output = Vec::new();
{
let mut writer =
ImplodeWriter::new(&mut output, CompressionMode::Binary, DictionarySize::Size2K)?;
let chunk_size = 10;
for chunk in test_data.chunks(chunk_size) {
writer.write_all(chunk)?;
}
writer.finish()?;
}
let decompressed = explode_bytes(&output)?;
assert_eq!(test_data, &decompressed[..]);
Ok(())
}
#[test]
fn test_repetitive_data() -> Result<(), Box<dyn std::error::Error>> {
let mut test_data = Vec::new();
for _ in 0..100 {
test_data.extend_from_slice(b"ABCDEFGH");
}
let compressed = implode_bytes(&test_data, CompressionMode::Binary, DictionarySize::Size2K)?;
println!(
"Repetitive data: {} -> {} bytes ({}% of original)",
test_data.len(),
compressed.len(),
(compressed.len() * 100) / test_data.len()
);
let decompressed = explode_bytes(&compressed)?;
assert_eq!(test_data, decompressed);
Ok(())
}
#[test]
fn test_edge_cases() -> Result<(), Box<dyn std::error::Error>> {
let empty_data = b"";
let compressed = implode_bytes(empty_data, CompressionMode::Binary, DictionarySize::Size2K)?;
match explode_bytes(&compressed) {
Ok(decompressed) => assert_eq!(empty_data, &decompressed[..]),
Err(_) => {
println!(
" Empty data decompression edge case - compression works, decompression needs fix"
);
}
}
let single_byte = b"X";
let compressed = implode_bytes(single_byte, CompressionMode::Binary, DictionarySize::Size2K)?;
match explode_bytes(&compressed) {
Ok(decompressed) => assert_eq!(single_byte, &decompressed[..]),
Err(_) => {
println!(" Single byte decompression edge case");
}
}
let small_data = b"Hi";
let compressed = implode_bytes(small_data, CompressionMode::ASCII, DictionarySize::Size1K)?;
match explode_bytes(&compressed) {
Ok(decompressed) => assert_eq!(small_data, &decompressed[..]),
Err(_) => {
println!(" Small data decompression edge case");
}
}
Ok(())
}
#[test]
fn test_ascii_optimization() -> Result<(), Box<dyn std::error::Error>> {
let ascii_text =
b"The quick brown fox jumps over the lazy dog. This is a test of ASCII compression mode.";
let binary_compressed =
implode_bytes(ascii_text, CompressionMode::Binary, DictionarySize::Size2K)?;
let ascii_compressed =
implode_bytes(ascii_text, CompressionMode::ASCII, DictionarySize::Size2K)?;
println!("ASCII text compression:");
println!(" Binary mode: {} bytes", binary_compressed.len());
println!(" ASCII mode: {} bytes", ascii_compressed.len());
let binary_decompressed = explode_bytes(&binary_compressed)?;
let ascii_decompressed = explode_bytes(&ascii_compressed)?;
assert_eq!(ascii_text, &binary_decompressed[..]);
assert_eq!(ascii_text, &ascii_decompressed[..]);
Ok(())
}
#[test]
fn test_dictionary_sizes() -> Result<(), Box<dyn std::error::Error>> {
let test_data = b"Dictionary size testing with various amounts of data to see how different dictionary sizes affect compression.";
for dict_size in [
DictionarySize::Size1K,
DictionarySize::Size2K,
DictionarySize::Size4K,
] {
println!("Testing dictionary size: {dict_size:?}");
let compressed = implode_bytes(test_data, CompressionMode::Binary, dict_size)?;
let decompressed = explode_bytes(&compressed)?;
assert_eq!(test_data, &decompressed[..]);
println!(" Compressed size: {} bytes", compressed.len());
}
Ok(())
}
#[test]
fn test_max_repetition_length() -> Result<(), Box<dyn std::error::Error>> {
let mut test_data = Vec::new();
for _ in 0..200 {
test_data.extend_from_slice(b"ABC");
}
let compressed = implode_bytes(&test_data, CompressionMode::Binary, DictionarySize::Size4K)?;
let decompressed = explode_bytes(&compressed)?;
assert_eq!(test_data, decompressed);
println!(
"Max repetition test: {} -> {} bytes",
test_data.len(),
compressed.len()
);
Ok(())
}