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 = 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) ); }