Files
cadcraft/crates/engine/tests/image_decoder_panic.rs
T
2026-11-04 19:48:04 -05:00

56 lines
2.4 KiB
Rust

//! A raster image decoder that panics on a damaged file fails that image only (#956): the
//! drawing it belongs to still opens, and IMAGEATTACH reports an error.
use cadcraft_engine::Session;
use cadcraft_engine::cmd::file::{IoHooks, base64_encode, set_image_decoder, set_io};
use cadcraft_engine::doc::geom::{Vec2, Vec3};
use cadcraft_engine::doc::{Common, Drawing, EntityKind, Image, Line, Space};
use serde_json::json;
fn hooks() {
set_io(IoHooks {
read: |b, name| cadcraft_io::read(b, name).map_err(|e| e.to_string()),
write: |d, name| cadcraft_io::write(d, name).map_err(|e| e.to_string()),
plot: None,
});
set_image_decoder(|_| panic!("decoder bug"));
}
#[test]
fn a_panicking_decoder_fails_the_image_not_the_drawing() {
hooks();
let dir = std::env::temp_dir().join(format!("cadcraft-image-panic-{}", std::process::id()));
let _ = std::fs::remove_dir_all(&dir);
std::fs::create_dir_all(&dir).unwrap();
std::fs::write(dir.join("map.png"), b"anything").unwrap();
let mut d = Drawing::new_metric();
d.add(&Space::Model, Common::default(), EntityKind::Line(Line { a: Vec3::ZERO, b: Vec3::new(5.0, 5.0, 0.0) })).unwrap();
let i = Image {
u: Vec3::new(1.0, 0.0, 0.0),
v: Vec3::new(0.0, 1.0, 0.0),
size: Vec2::new(4.0, 2.0),
path: "map.png".into(),
name: "map".into(),
..Image::default()
};
d.add(&Space::Model, Common::default(), EntityKind::Image(i)).unwrap();
let host = dir.join("host.dxf");
std::fs::write(&host, cadcraft_io::write(&d, "host.dxf").unwrap()).unwrap();
let mut s = Session::new();
s.execute("open", &json!({ "path": host.to_string_lossy() })).unwrap();
let doc = s.doc().unwrap();
assert_eq!(doc.model.len(), 2, "the drawing opened with everything in it");
assert!(doc.rasters.is_empty());
assert!(s.log.iter().any(|l| l.contains("map.png") && l.contains("damaged")), "{:?}", s.log);
let before = s.doc().unwrap().model.len();
let e = s.execute("imageattach", &json!({ "path": "other.png", "data": base64_encode(b"bytes") })).unwrap_err().to_string();
assert!(e.contains("damaged"), "{e}");
assert_eq!(s.doc().unwrap().model.len(), before);
// The session still works.
s.execute("line", &json!({ "points": [[0, 0], [1, 1]] })).unwrap();
assert_eq!(s.doc().unwrap().model.len(), before + 1);
let _ = std::fs::remove_dir_all(&dir);
}