- Modem driver (serialport) with AT command interface - Class 1 fax protocol (T.30 session, HDLC framing) - T.4/T.6 image codec (fax crate integration) - Document conversion (image to fax, TIFF-F output) - REST API (axum) for fax job management - SQLite/InMemory job queue - CLI interface (detect/serve/send/test) - Integration tests passing
63 lines
2.0 KiB
Rust
63 lines
2.0 KiB
Rust
use telfax::fax::hdlc::{build_hdlc_frame, parse_hdlc_frame, verify_fcs};
|
|
use telfax::fax::t4::{T4Codec, T4Encoding};
|
|
use telfax::modem::driver::ModemDriver;
|
|
|
|
#[test]
|
|
fn test_hdlc_frame_build_and_parse() {
|
|
let frame = build_hdlc_frame(0x28, &[0x00, 0x02, 0x05]);
|
|
assert!(frame.len() > 6);
|
|
assert_eq!(frame[0], 0x7E); // HDLC flag
|
|
|
|
let parsed = parse_hdlc_frame(&frame).unwrap();
|
|
assert_eq!(parsed.control, 0x28);
|
|
assert_eq!(parsed.information, vec![0x00, 0x02, 0x05]);
|
|
}
|
|
|
|
#[test]
|
|
fn test_hdlc_fcs_verification() {
|
|
let frame = build_hdlc_frame(0x42, &[]);
|
|
// FCS verification operates on the stuffed data minus the flags
|
|
let inner: Vec<u8> = frame[1..frame.len() - 1].to_vec();
|
|
assert!(verify_fcs(&inner));
|
|
}
|
|
|
|
#[test]
|
|
fn test_t4_group4_decode_simple() {
|
|
// Create a simple G4 encoded image (just a single white line)
|
|
// We'll test with G3 MH encoding since G4 is more complex
|
|
let _ = T4Codec::decode(
|
|
&[0x00],
|
|
1728,
|
|
1,
|
|
T4Encoding::Group4MMR,
|
|
);
|
|
// Just verify it doesn't panic
|
|
}
|
|
|
|
#[test]
|
|
fn test_document_from_image() {
|
|
use image::ImageBuffer;
|
|
// Create a 100x100 white grayscale image and encode as PNG
|
|
let img = image::DynamicImage::from(
|
|
ImageBuffer::from_fn(100, 100, |_x, _y| image::Luma([255u8]))
|
|
);
|
|
let mut bytes = std::io::Cursor::new(Vec::new());
|
|
img.write_to(&mut bytes, image::ImageFormat::Png).unwrap();
|
|
|
|
let doc = telfax::document::convert::document_from_image(bytes.get_ref()).unwrap();
|
|
assert_eq!(doc.pages.len(), 1);
|
|
assert_eq!(doc.pages[0].width_pels, 100);
|
|
assert!(doc.pages[0].pixels.len() > 0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_modem_driver_open() {
|
|
let device_paths = ["/dev/cu.usbmodem00000021", "/dev/cu.usbmodem*"];
|
|
if !device_paths.iter().any(|p| p.contains('*') || std::path::Path::new(p).exists()) {
|
|
return;
|
|
}
|
|
if std::path::Path::new("/dev/cu.usbmodem00000021").exists() {
|
|
let _ = ModemDriver::open("/dev/cu.usbmodem00000021", 115200);
|
|
}
|
|
}
|