#1714: test several comps, negative and malformed saved times

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
arnav-hiwarkar
2026-10-17 15:35:12 +05:30
co-authored by Claude Opus 5.5
parent ea67c46880
commit c28daa479b
2 changed files with 20 additions and 5 deletions
+13 -4
View File
@@ -691,6 +691,7 @@ fn reopening_a_project_restores_its_active_comp() {
/// current time it was saved at, not at 0, where a layer starting later shows nothing (#1714).
#[test]
fn reopening_a_project_restores_layer_times_and_current_time() {
use effectcraft_project::ItemId;
use effectcraft_time::{FrameRate, Tick};
let dir = std::env::temp_dir().join(format!("ec-test-1714-{}", std::process::id()));
std::fs::create_dir_all(&dir).unwrap();
@@ -706,21 +707,29 @@ fn reopening_a_project_restores_layer_times_and_current_time() {
(l.start_time, l.in_point, l.out_point) = (Tick(144_086_342_400), Tick(1_334_917_584_000), Tick(12_853_349_308_800));
s.execute("time.set", json!({"time": 6.0})).unwrap();
let t = s.time();
// A second comp keeps its own time.
let b = ItemId(s.execute("comp.new", json!({"name": "B"})).unwrap()["comp"].as_u64().unwrap());
s.execute("time.set", json!({"time": 2.0})).unwrap();
let tb = s.time();
s.execute("comp.open", json!({"comp": "C"})).unwrap();
s.execute("file.saveAs", json!({"path": path})).unwrap();
let mut s2 = Session::default();
s2.execute("file.open", json!({"path": path})).unwrap();
let l = s2.project.comp(cid).unwrap().layers.first().unwrap();
assert_eq!((l.start_time, l.in_point, l.out_point), (Tick(144_086_342_400), Tick(1_334_917_584_000), Tick(12_853_349_308_800)));
assert_eq!(s2.time(), t);
assert_eq!((s2.time(), s2.state.times.get(&b).copied()), (t, Some(tb)));
assert!(l.in_point <= s2.time() && s2.time() < l.out_point, "the layer shows at the reopened time");
assert!(!s2.is_dirty());
// A saved time past the comp's end (a hand-edited file) lands on its last frame.
let text = std::fs::read_to_string(&path).unwrap().replace(&format!("\"{}\": {}", cid.0, t.0), &format!("\"{}\": {}", cid.0, i64::MAX));
std::fs::write(&path, text).unwrap();
// Hand-edited times past the end or before the start land on the last or first frame.
let mut file: serde_json::Value = serde_json::from_str(&std::fs::read_to_string(&path).unwrap()).unwrap();
file["compTimes"] = json!({cid.0.to_string(): i64::MAX, b.0.to_string(): -5});
std::fs::write(&path, file.to_string()).unwrap();
let mut s3 = Session::default();
s3.execute("file.open", json!({"path": path})).unwrap();
let c = s3.project.comp(cid).unwrap();
assert_eq!(s3.time(), c.frame_rate.snap_nearest(c.duration - c.frame_duration()));
assert_eq!(s3.time(), c.frame_rate.snap_nearest(c.duration - c.frame_duration()));
assert_eq!(s3.state.times.get(&b).copied(), Some(Tick::ZERO));
}
+7 -1
View File
@@ -180,7 +180,13 @@ fn project_files_remember_the_open_comps() {
// Files from before #748 have no view; a garbled one is ignored, not an error.
assert_eq!(crate::saved_view(&p.to_file_json().unwrap()), crate::SavedView::default());
let odd = text.replacen(&format!("\"activeComp\": {}", cid.0), "\"activeComp\": \"Main\"", 1);
assert_eq!(crate::saved_view(&odd), crate::SavedView { active_comp: None, ..view });
assert_eq!(crate::saved_view(&odd), crate::SavedView { active_comp: None, ..view.clone() });
// Entries that aren't an id and a whole tick count are skipped; the rest are kept.
let times = text.replacen("\"compTimes\": {", "\"compTimes\": {\"x\": 1, \"7\": \"a\", \"8\": 1.5, \"9\": -4,", 1);
let expect = [(cid, effectcraft_time::Tick(4_237_833_600)), (crate::ItemId(9), effectcraft_time::Tick(-4))].into();
assert_eq!(crate::saved_view(&times).comp_times, expect);
let not_a_map = text.replacen("\"compTimes\": {", "\"compTimes\": [], \"unused\": {", 1);
assert_eq!(crate::saved_view(&not_a_map), crate::SavedView { comp_times: Default::default(), ..view });
}
/// The Project panel's "used N times": layers in every comp that use the item directly, a precomp