molframe 0.1.0

A batteries-included structural bioinformatics engine
Documentation
use super::*;
use molframe_core::{ScratchPolicy, TempStoragePolicy, collect_structure};
use std::io::Write;

const PDB: &str = concat!(
    "ATOM      1  N   GLY A   1      11.104  13.207  10.111  1.00 20.00           N  \n",
    "ATOM      2  CA  GLY A   1      12.104  13.207  10.111  1.00 21.00           C  \n",
    "END\n",
);

fn context() -> ExecutionContext {
    ExecutionContext::builder()
        .scratch_policy(ScratchPolicy::new(0))
        .build()
        .expect("valid context")
}

#[test]
#[cfg(feature = "pdb")]
fn dispatch_and_collector_never_reserve_from_the_input_length() {
    let mut file = tempfile::Builder::new()
        .suffix(".pdb")
        .tempfile()
        .expect("temporary input");
    file.write_all(PDB.as_bytes()).expect("fixture write");
    let context = context();
    let mut source = open_structure_batches(file.path(), &ReadOptions::new(), &context)
        .expect("bounded PDB source");
    let (structure, diagnostics) =
        collect_structure(&mut source, &context).expect("budgeted collector");

    assert_eq!(structure.atom_count(), 2);
    assert!(diagnostics.is_empty());
    assert!(context.peak_reserved_bytes() < 16 * 1024 * 1024);
    assert_eq!(context.live_batches(), 0);
}

#[test]
#[cfg(all(feature = "bcif", feature = "pdb"))]
fn binary_cif_dispatch_uses_the_bounded_reader() {
    let input = molframe_core::InputBuffer::from_bytes(PDB.as_bytes().to_vec());
    let (structure, diagnostics) =
        molframe_pdb::read(&input, &ReadOptions::new()).expect("PDB structure fixture");
    assert!(diagnostics.is_empty());
    let write_options = molframe_cif::CifWriteOptions::new().with_block_id("batch");
    let bytes = molframe_bcif::write_structure_with_options(&structure, &write_options)
        .expect("BinaryCIF fixture");
    let mut file = tempfile::Builder::new()
        .suffix(".bcif")
        .tempfile()
        .expect("temporary BinaryCIF input");
    file.write_all(&bytes).expect("BinaryCIF fixture write");
    let context = context();
    let mut source = open_structure_batches(file.path(), &ReadOptions::new(), &context)
        .expect("bounded BinaryCIF source");
    let (decoded, findings) =
        collect_structure(&mut source, &context).expect("budgeted BinaryCIF collector");

    assert_eq!(decoded.atom_count(), structure.atom_count());
    assert!(findings.is_empty());
    assert!(context.peak_reserved_bytes() < 16 * 1024 * 1024);
    assert_eq!(context.live_batches(), 0);
}

#[test]
#[cfg(all(feature = "gzip", feature = "pdb"))]
fn compressed_batches_require_and_use_explicit_bounded_spill() {
    let directory = tempfile::tempdir().expect("temporary directory");
    let mut file = tempfile::Builder::new()
        .suffix(".pdb.gz")
        .tempfile_in(directory.path())
        .expect("temporary gzip input");
    let mut encoder =
        flate2::write::GzEncoder::new(file.as_file_mut(), flate2::Compression::fast());
    encoder.write_all(PDB.as_bytes()).expect("gzip fixture");
    encoder.finish().expect("finish gzip fixture");

    let disabled = context();
    assert!(open_structure_batches(file.path(), &ReadOptions::new(), &disabled).is_err());

    let context = ExecutionContext::builder()
        .scratch_policy(ScratchPolicy::new(0))
        .temp_storage_policy(TempStoragePolicy::directory(
            directory.path().join("spill"),
            1024 * 1024,
        ))
        .build()
        .expect("spill context");
    let mut source = open_structure_batches(file.path(), &ReadOptions::new(), &context)
        .expect("bounded compressed source");
    assert!(context.spill_bytes() > 0);
    let (structure, diagnostics) =
        collect_structure(&mut source, &context).expect("compressed collection");
    assert_eq!(structure.atom_count(), 2);
    assert!(diagnostics.is_empty());
    drop(source);
    assert_eq!(context.spill_bytes(), 0);
}