use spdf_core::SpdfParser;
use spdf_types::{ParseInput, SpdfError};
#[test]
fn max_input_bytes_rejects_oversized_blob() {
let parser = SpdfParser::builder()
.ocr_enabled(false)
.max_input_bytes(64)
.build();
let payload = vec![0u8; 1024];
let err = parser
.parse(ParseInput::Bytes(payload))
.expect_err("oversized input should be rejected");
match err {
SpdfError::InvalidInput(msg) => {
assert!(msg.contains("max_input_bytes"), "unexpected msg: {msg}");
}
other => panic!("expected InvalidInput, got {other:?}"),
}
}
#[test]
fn max_input_bytes_allows_inputs_below_cap() {
let parser = SpdfParser::builder()
.ocr_enabled(false)
.max_input_bytes(10_000)
.build();
let payload = vec![0u8; 128];
let err = parser
.parse(ParseInput::Bytes(payload))
.expect_err("non-PDF bytes must still fail");
assert!(
!matches!(err, SpdfError::InvalidInput(ref m) if m.contains("max_input_bytes")),
"guard fired below cap: {err:?}"
);
}
#[test]
fn timeout_secs_produces_typed_error_when_it_fires() {
let pdf = match std::fs::read(workspace_fixture("test-ocr.pdf")) {
Ok(b) => b,
Err(_) => return, };
let parser = SpdfParser::builder()
.ocr_enabled(false)
.timeout_secs(0)
.build();
if let Err(SpdfError::InvalidInput(msg)) = parser.parse(ParseInput::Bytes(pdf)) {
assert!(
msg.contains("timeout"),
"InvalidInput from elsewhere: {msg}"
);
}
}
#[test]
fn max_pages_zero_produces_empty_result() {
let pdf = match std::fs::read(workspace_fixture("test-ocr.pdf")) {
Ok(b) => b,
Err(_) => return,
};
let parser = SpdfParser::builder()
.ocr_enabled(false)
.max_pages(0)
.build();
let result = parser
.parse(ParseInput::Bytes(pdf))
.expect("max_pages=0 must not error, just produce no pages");
assert!(result.pages.is_empty(), "pages leaked past max_pages=0");
}
fn workspace_fixture(name: &str) -> std::path::PathBuf {
let manifest = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
manifest
.parent()
.and_then(|p| p.parent())
.expect("workspace root")
.join("example")
.join(name)
}