#![allow(clippy::expect_used)]
use std::io::Write;
use libmagic_rs::{EvaluationConfig, MagicDatabase};
use tempfile::NamedTempFile;
fn db_from_magic(magic: &str) -> MagicDatabase {
let mut f = NamedTempFile::new().expect("temp magic file");
f.write_all(magic.as_bytes()).expect("write magic");
f.flush().expect("flush magic");
MagicDatabase::load_from_file_with_config(f.path(), EvaluationConfig::default())
.expect("magic must load")
}
#[test]
fn bare_search_recovers_pdf_page_count() {
let magic = "0\tname\tpdf\n\
>8\tsearch\t\t/Count\n\
>>&0\tregex\t\t[0-9]+\t\\b, %s pages\n\
0\tstring\t%PDF-\tPDF document\n\
>0\tuse\tpdf\n";
let db = db_from_magic(magic);
let mut buf = b"%PDF-1.3\n".to_vec();
buf.extend_from_slice(b"1 0 obj\n<< /Type /Pages /Count 3 /Kids [] >>\nendobj\n");
let result = db.evaluate_buffer(&buf).expect("evaluate PDF buffer");
assert_eq!(
result.description.as_str(),
"PDF document, 3 pages",
"bare `search /Count` must recover the page count via the regex grandchild"
);
}
#[test]
fn bare_search_scans_to_end_of_buffer() {
let magic = "0\tstring\tSTART\tmarker\n\
>0\tsearch\t\tDEEP\t\\b, found deep\n";
let db = db_from_magic(magic);
let mut buf = b"START".to_vec();
buf.extend(std::iter::repeat_n(b'.', 6000));
buf.extend_from_slice(b"DEEP");
let result = db.evaluate_buffer(&buf).expect("evaluate deep buffer");
assert_eq!(
result.description.as_str(),
"marker, found deep",
"bare search must scan the whole remaining buffer, not a bounded window"
);
}
#[test]
fn bounded_search_respects_its_window() {
let magic = "0\tstring\tSTART\tmarker\n\
>0\tsearch/16\tDEEP\t\\b, found deep\n";
let db = db_from_magic(magic);
let mut buf = b"START".to_vec();
buf.extend(std::iter::repeat_n(b'.', 100));
buf.extend_from_slice(b"DEEP");
let result = db.evaluate_buffer(&buf).expect("evaluate bounded buffer");
assert_eq!(
result.description.as_str(),
"marker",
"search/16 must not find a pattern 100+ bytes past the offset"
);
}