blob: 3fa44e871617274009dcd168e55e5e1eb694e6cf [file] [edit]
extern crate std;
use crate as zstd_safe;
use self::std::vec::Vec;
const INPUT: &[u8] = b"Rust is a multi-paradigm system programming language focused on safety, especially safe concurrency. Rust is syntactically similar to C++, but is designed to provide better memory safety while maintaining high performance.";
const LONG_CONTENT: &str = include_str!("lib.rs");
#[cfg(feature = "std")]
#[test]
fn test_writebuf() {
use zstd_safe::WriteBuf;
let mut data = Vec::with_capacity(10);
unsafe {
data.write_from(|ptr, n| {
assert!(n >= 4);
let ptr = ptr as *mut u8;
ptr.write(0);
ptr.add(1).write(1);
ptr.add(2).write(2);
ptr.add(3).write(3);
Ok(4)
})
}
.unwrap();
assert_eq!(data.as_slice(), &[0, 1, 2, 3]);
let mut cursor = std::io::Cursor::new(&mut data);
// Here we use a position larger than the actual data.
// So expect the data to be zero-filled.
cursor.set_position(6);
unsafe {
cursor.write_from(|ptr, n| {
assert!(n >= 4);
let ptr = ptr as *mut u8;
ptr.write(4);
ptr.add(1).write(5);
ptr.add(2).write(6);
ptr.add(3).write(7);
Ok(4)
})
}
.unwrap();
assert_eq!(data.as_slice(), &[0, 1, 2, 3, 0, 0, 4, 5, 6, 7]);
}
#[cfg(feature = "std")]
#[test]
fn test_simple_cycle() {
let mut buffer = std::vec![0u8; 256];
let written = zstd_safe::compress(&mut buffer, INPUT, 3).unwrap();
let compressed = &buffer[..written];
let mut buffer = std::vec![0u8; 256];
let written = zstd_safe::decompress(&mut buffer, compressed).unwrap();
let decompressed = &buffer[..written];
assert_eq!(INPUT, decompressed);
}
#[test]
fn test_cctx_cycle() {
let mut buffer = std::vec![0u8; 256];
let mut cctx = zstd_safe::CCtx::default();
let written = cctx.compress(&mut buffer[..], INPUT, 1).unwrap();
let compressed = &buffer[..written];
let mut dctx = zstd_safe::DCtx::default();
let mut buffer = std::vec![0u8; 256];
let written = dctx.decompress(&mut buffer[..], compressed).unwrap();
let decompressed = &buffer[..written];
assert_eq!(INPUT, decompressed);
}
#[test]
fn test_dictionary() {
// Prepare some content to train the dictionary.
let bytes = LONG_CONTENT.as_bytes();
let line_sizes: Vec<usize> =
LONG_CONTENT.lines().map(|line| line.len() + 1).collect();
// Train the dictionary
let mut dict_buffer = std::vec![0u8; 100_000];
let written =
zstd_safe::train_from_buffer(&mut dict_buffer[..], bytes, &line_sizes)
.unwrap();
let dict_buffer = &dict_buffer[..written];
// Create pre-hashed dictionaries for (de)compression
let cdict = zstd_safe::create_cdict(dict_buffer, 3);
let ddict = zstd_safe::create_ddict(dict_buffer);
// Compress data
let mut cctx = zstd_safe::CCtx::default();
cctx.ref_cdict(&cdict).unwrap();
let mut buffer = std::vec![0u8; 1024 * 1024];
// First, try to compress without a dict
let big_written = zstd_safe::compress(&mut buffer[..], bytes, 3).unwrap();
let written = cctx
.compress2(&mut buffer[..], bytes)
.map_err(zstd_safe::get_error_name)
.unwrap();
assert!(big_written > written);
let compressed = &buffer[..written];
// Decompress data
let mut dctx = zstd_safe::DCtx::default();
dctx.ref_ddict(&ddict).unwrap();
let mut buffer = std::vec![0u8; 1024 * 1024];
let written = dctx
.decompress(&mut buffer[..], compressed)
.map_err(zstd_safe::get_error_name)
.unwrap();
let decompressed = &buffer[..written];
// Profit!
assert_eq!(bytes, decompressed);
}
#[test]
fn test_checksum() {
let mut buffer = std::vec![0u8; 256];
let mut cctx = zstd_safe::CCtx::default();
cctx.set_parameter(zstd_safe::CParameter::ChecksumFlag(true))
.unwrap();
let written = cctx.compress2(&mut buffer[..], INPUT).unwrap();
let compressed = &mut buffer[..written];
let mut dctx = zstd_safe::DCtx::default();
let mut buffer = std::vec![0u8; 1024*1024];
let written = dctx
.decompress(&mut buffer[..], compressed)
.map_err(zstd_safe::get_error_name)
.unwrap();
let decompressed = &buffer[..written];
assert_eq!(INPUT, decompressed);
// Now try again with some corruption
// TODO: Find a mutation that _wouldn't_ be detected without checksums.
// (Most naive changes already trigger a "corrupt block" error.)
if let Some(last) = compressed.last_mut() {
*last = last.saturating_sub(1);
}
let err = dctx
.decompress(&mut buffer[..], compressed)
.map_err(zstd_safe::get_error_name)
.err()
.unwrap();
// The error message will complain about the checksum.
assert!(err.contains("checksum"));
}
#[cfg(all(feature = "experimental", feature = "std"))]
#[test]
fn test_upper_bound() {
let mut buffer = std::vec![0u8; 256];
assert!(zstd_safe::decompress_bound(&buffer).is_err());
let written = zstd_safe::compress(&mut buffer, INPUT, 3).unwrap();
let compressed = &buffer[..written];
assert_eq!(
zstd_safe::decompress_bound(&compressed),
Ok(INPUT.len() as u64)
);
}