use super::*;
#[test]
fn plain_bytes_are_returned_as_they_were_given() {
let input = InputBuffer::from_bytes(b"data_test\n".to_vec());
assert_eq!(input.as_bytes(), b"data_test\n");
assert_eq!(input.len(), 10);
assert!(!input.is_empty());
assert_eq!(input.origin(), None);
}
#[test]
fn taking_owned_bytes_preserves_the_vector_allocation() {
let bytes = vec![1_u8, 2, 3, 4];
let pointer = bytes.as_ptr();
let input = InputBuffer::from_bytes(bytes);
assert_eq!(input.as_bytes().as_ptr(), pointer);
assert_eq!(input.as_bytes(), [1, 2, 3, 4]);
}
#[test]
fn a_compression_container_is_recognised_from_its_leading_bytes() {
assert_eq!(Compression::sniff(&[0x1f, 0x8b, 0x08]), Compression::Gzip);
assert_eq!(
Compression::sniff(&[0x28, 0xb5, 0x2f, 0xfd]),
Compression::Zstd
);
assert_eq!(Compression::sniff(b"data_x"), Compression::None);
assert_eq!(Compression::sniff(&[]), Compression::None);
}
#[test]
fn an_input_can_name_where_it_came_from_for_a_diagnostic_to_quote() {
let input = InputBuffer::from_bytes(Vec::new()).with_origin("entry.cif");
assert_eq!(input.origin(), Some("entry.cif"));
assert!(input.is_empty());
}
#[test]
fn a_buffer_that_expands_beyond_the_limit_is_refused_rather_than_obeyed() {
let limits = Limits {
decompressed_bytes: 100,
..Limits::default()
};
assert!(check_expansion(101, 10, limits).is_err());
assert!(check_expansion(99, 10, limits).is_ok());
}
#[test]
fn a_buffer_that_expands_faster_than_the_ratio_allows_is_refused() {
let limits = Limits {
compression_ratio: 10,
..Limits::default()
};
assert!(
check_expansion(100, 10, limits).is_ok(),
"tenfold is at the limit"
);
assert!(check_expansion(2_000, 10, limits).is_err());
}
#[test]
fn standard_limits_do_not_impose_historical_dataset_caps() {
let limits = Limits::default();
assert_eq!(limits.decompressed_bytes, u64::MAX);
assert_eq!(limits.rows_per_category, u64::MAX);
assert_eq!(limits.dictionary_entries, u32::MAX - 1);
}
#[test]
fn opening_a_file_that_is_not_there_reports_a_resource_finding() {
let error = InputBuffer::open("no/such/entry.cif", Limits::default());
assert_eq!(error.err().map(|finding| finding.code()), Some(Code::E1901));
}
#[test]
fn a_stream_is_read_and_bounded_like_a_file() {
let input = InputBuffer::from_reader(std::io::Cursor::new(b"data_stream\n"), Limits::default());
assert_eq!(
input.as_ref().map(InputBuffer::as_bytes),
Ok(b"data_stream\n".as_slice())
);
let limits = Limits {
decompressed_bytes: 4,
..Limits::default()
};
assert!(InputBuffer::from_reader(std::io::Cursor::new(b"12345"), limits).is_err());
}
#[cfg(feature = "mmap")]
#[test]
fn a_stream_uses_disk_backed_storage_instead_of_retaining_an_input_vector() {
let input =
match InputBuffer::from_reader(std::io::Cursor::new(b"data_stream\n"), Limits::default()) {
Ok(input) => input,
Err(finding) => panic!("stream failed: {finding}"),
};
assert_eq!(input.kind(), InputKind::Mapped);
assert_eq!(input.as_bytes(), b"data_stream\n");
}
#[cfg(feature = "mmap")]
#[test]
fn a_large_stream_is_consumed_through_a_fixed_size_window() {
use std::io::Read;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
struct RepeatingReader {
remaining: usize,
largest_request: Arc<AtomicUsize>,
}
impl Read for RepeatingReader {
fn read(&mut self, destination: &mut [u8]) -> std::io::Result<usize> {
self.largest_request
.fetch_max(destination.len(), Ordering::Relaxed);
let count = destination.len().min(self.remaining);
destination[..count].fill(b'x');
self.remaining -= count;
Ok(count)
}
}
let largest_request = Arc::new(AtomicUsize::new(0));
let reader = RepeatingReader {
remaining: 2 * 1024 * 1024,
largest_request: Arc::clone(&largest_request),
};
let input = match InputBuffer::from_reader(reader, Limits::default()) {
Ok(input) => input,
Err(finding) => panic!("stream failed: {finding}"),
};
assert_eq!(input.kind(), InputKind::Mapped);
assert_eq!(input.len(), 2 * 1024 * 1024);
assert!(largest_request.load(Ordering::Relaxed) <= 64 * 1024);
}
#[cfg(all(feature = "gzip", feature = "mmap"))]
#[test]
fn a_compressed_stream_maps_only_the_finished_expansion() {
use flate2::Compression as GzipLevel;
use flate2::write::GzEncoder;
use std::io::Write as _;
let mut compressed_writer = GzEncoder::new(Vec::new(), GzipLevel::fast());
if let Err(error) = compressed_writer.write_all(b"data_stream\n") {
panic!("compression failed: {error}")
}
let compressed_bytes = match compressed_writer.finish() {
Ok(bytes) => bytes,
Err(error) => panic!("finish failed: {error}"),
};
let input =
match InputBuffer::from_reader(std::io::Cursor::new(compressed_bytes), Limits::default()) {
Ok(input) => input,
Err(finding) => panic!("stream failed: {finding}"),
};
assert_eq!(input.kind(), InputKind::Mapped);
assert_eq!(input.as_bytes(), b"data_stream\n");
}
#[cfg(feature = "mmap")]
#[test]
fn a_large_plain_local_file_is_parsed_directly_from_a_mapping() {
use std::io::Write as _;
let path = std::env::temp_dir().join(format!("molframe-input-{}", std::process::id()));
let mut file = match File::create(&path) {
Ok(file) => file,
Err(error) => panic!("create failed: {error}"),
};
let Ok(mmap_min_bytes) = usize::try_from(MMAP_MIN_BYTES) else {
panic!("mmap threshold fits this platform")
};
let mut bytes = vec![b' '; mmap_min_bytes];
bytes[..10].copy_from_slice(b"data_test\n");
if let Err(error) = file.write_all(&bytes) {
panic!("write failed: {error}")
}
drop(file);
let input = match InputBuffer::open(&path, Limits::default()) {
Ok(input) => input,
Err(finding) => panic!("open failed: {finding}"),
};
assert_eq!(input.kind(), InputKind::Mapped);
assert!(input.as_bytes().starts_with(b"data_test\n"));
let _removed = std::fs::remove_file(path);
}
#[cfg(feature = "mmap")]
#[test]
fn a_small_local_file_avoids_mapping_overhead() {
use std::io::Write as _;
let path = std::env::temp_dir().join(format!("molframe-small-input-{}", std::process::id()));
let mut file = match File::create(&path) {
Ok(file) => file,
Err(error) => panic!("create failed: {error}"),
};
if let Err(error) = file.write_all(b"data_test\n") {
panic!("write failed: {error}")
}
drop(file);
let input = match InputBuffer::open(&path, Limits::default()) {
Ok(input) => input,
Err(finding) => panic!("open failed: {finding}"),
};
assert_eq!(input.kind(), InputKind::Owned);
let _removed = std::fs::remove_file(path);
}
#[cfg(all(feature = "gzip", feature = "mmap"))]
#[test]
fn a_gzip_file_expands_into_private_mapped_storage() {
use flate2::Compression as GzipLevel;
use flate2::write::GzEncoder;
use std::io::Write as _;
let path = std::env::temp_dir().join(format!("molframe-gzip-input-{}", std::process::id()));
let file = match File::create(&path) {
Ok(file) => file,
Err(error) => panic!("create failed: {error}"),
};
let mut encoder = GzEncoder::new(file, GzipLevel::fast());
if let Err(error) = encoder.write_all(b"data_test\n") {
panic!("compression failed: {error}")
}
if let Err(error) = encoder.finish() {
panic!("finish failed: {error}")
}
let input = match InputBuffer::open(&path, Limits::default()) {
Ok(input) => input,
Err(finding) => panic!("open failed: {finding}"),
};
assert_eq!(input.kind(), InputKind::Mapped);
assert_eq!(input.as_bytes(), b"data_test\n");
let _removed = std::fs::remove_file(path);
}
#[cfg(all(feature = "mmap", feature = "zstd"))]
#[test]
fn a_zstd_file_expands_into_private_mapped_storage() {
let path = std::env::temp_dir().join(format!("molframe-zstd-input-{}", std::process::id()));
let encoded = match zstd::stream::encode_all(b"data_test\n".as_slice(), 1) {
Ok(encoded) => encoded,
Err(error) => panic!("compression failed: {error}"),
};
if let Err(error) = std::fs::write(&path, encoded) {
panic!("write failed: {error}")
}
let input = match InputBuffer::open(&path, Limits::default()) {
Ok(input) => input,
Err(finding) => panic!("open failed: {finding}"),
};
assert_eq!(input.kind(), InputKind::Mapped);
assert_eq!(input.as_bytes(), b"data_test\n");
let _removed = std::fs::remove_file(path);
}
#[test]
fn owner_backed_input_adopts_stable_bytes_and_clones_only_the_handle() {
let owner: std::sync::Arc<[u8]> = std::sync::Arc::from(&b"data_block"[..]);
let pointer = owner.as_ptr();
let input = InputBuffer::from_owner(std::sync::Arc::clone(&owner));
assert_eq!(input.kind(), InputKind::OwnerBacked);
assert_eq!(input.as_bytes().as_ptr(), pointer);
let clone = input.clone();
drop(input);
assert_eq!(clone.as_bytes(), &b"data_block"[..]);
assert_eq!(clone.as_bytes().as_ptr(), pointer);
}