Files
figcraft/crates/engine/src/open_issues_tests.rs
T
5e90592e80 M1: report images a native file lost on loading (#207) (#242)
A `.figcraft` image member that is damaged, too large or missing was skipped
without a word, and saving the file again dropped it for good. The load now
lists each lost image (up to 20, then a count) with its hash and the reason,
file.open puts it in `repairs` and sets a session message, and the app shows
that as a toast.

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: bflatastic <bombayapirat@gmail.com>
2026-10-14 10:32:44 +07:00

52 lines
2.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Opening a native file that lost something (a damaged image): the session says so, with the
//! reason, and the file still opens.
use figcraft_doc::Document;
use serde_json::json;
use crate::Session;
/// A 1×1 PNG.
const PNG: [u8; 67] = [
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0x15, 0xc4, 0x89, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x44, 0x41, 0x54, 0x78, 0x9c, 0x63, 0x60, 0x00, 0x00, 0x02,
0x00, 0x00, 0x01, 0xe2, 0x21, 0xbc, 0x33, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
];
fn file(name: &str, damage: bool) -> std::path::PathBuf {
let dir = std::env::temp_dir().join(format!("figcraft-open-issues-{}-{name}", std::process::id()));
std::fs::create_dir_all(&dir).unwrap();
let mut d = Document::new("Pics");
figcraft_format::add_image(&mut d, PNG.to_vec()).unwrap();
let mut bytes = figcraft_format::save_bytes(&d, None).unwrap();
if damage {
// Images are stored as they are: change one byte of the PNG, not its checksum.
let at = bytes.windows(PNG.len()).position(|w| w == PNG).unwrap();
bytes[at + 30] ^= 0xff;
}
let path = dir.join("pics.figcraft");
std::fs::write(&path, bytes).unwrap();
path
}
#[test]
fn a_file_with_a_damaged_image_opens_and_says_what_was_lost() {
let path = file("damaged", true);
let mut s = Session::new();
let r = s.execute("file.open", &json!({"path": path.to_string_lossy()})).unwrap();
assert!(r["repairs"].as_array().is_some_and(|a| a.len() == 1), "{r}");
let m = s.message.take().expect("the session says so");
assert!(m.starts_with("pics: image ") && m.contains("couldn't be read") && m.contains("drops it"), "{m}");
let _ = std::fs::remove_dir_all(path.parent().unwrap());
}
#[test]
fn an_intact_file_opens_without_a_message() {
let path = file("intact", false);
let mut s = Session::new();
let r = s.execute("file.open", &json!({"path": path.to_string_lossy()})).unwrap();
assert!(r["repairs"].as_array().is_some_and(Vec::is_empty), "{r}");
assert!(s.message.is_none());
let _ = std::fs::remove_dir_all(path.parent().unwrap());
}