mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-24 09:57:08 -06:00
Tests: spread three format-by-geometry matrices over the days, and build one precheck state per case
The tilt-shift reference tests and tiled_clear_and_fill_match_one_pass_over_the_area cross pixel formats or channel counts with independent geometry and fill settings. Each run takes a quarter of the combinations through Sweep, a different quarter each UTC day. precheck_agrees_with_execute built all five document states for every call and kept one; it now builds only the state the call needs.
This commit is contained in:
@@ -60,6 +60,7 @@ photocraft-ipp = { workspace = true }
|
||||
photocraft-affinity = { workspace = true, features = ["synth"] }
|
||||
# Synthetic camera raw files for the open tests.
|
||||
photocraft-raw = { workspace = true, features = ["testgen"] }
|
||||
photocraft-testkit = { workspace = true }
|
||||
# WebAssembly text -> binary for plug-in test modules (Apache-2.0 WITH LLVM-exception).
|
||||
wat = "1.228"
|
||||
# Synthetic multi-part EXR fixtures for the parts-commands tests.
|
||||
|
||||
@@ -183,19 +183,29 @@ fn tiled_clear_and_fill_match_one_pass_over_the_area() {
|
||||
let sr = Rect::new(0, 0, 600, 400);
|
||||
soft.write_region(sr, &(0..sr.height()).flat_map(|_| (0..sr.width()).map(|x| (1.0 - (x as f32 - 256.0).max(0.0) / 300.0).max(0.0))).collect::<Vec<_>>());
|
||||
let canvas = Rect::new(0, 0, 700, 600);
|
||||
// Pixel formats and fill settings are independent: a run takes a quarter of their combinations,
|
||||
// a different quarter each day.
|
||||
let sweep = photocraft_testkit::Sweep::new(4);
|
||||
let mut case = 0;
|
||||
let mut runs = || {
|
||||
case += 1;
|
||||
sweep.includes(case)
|
||||
};
|
||||
for fmt in formats {
|
||||
let s = clear_layer(fmt);
|
||||
for sel in [None, Some(&soft)] {
|
||||
let area = sel.map_or(canvas, |m| m.content_bounds());
|
||||
let what = format!("{fmt:?} selection {}", sel.is_some());
|
||||
let mut got = s.clone();
|
||||
try_clear_surface(&mut got, area, sel).unwrap();
|
||||
assert!(same_pixels(&got, &reference_fill_or_clear(&s, area, sel, None)), "clear {what}");
|
||||
if fmt.alpha {
|
||||
assert!(!same_pixels(&got, &s), "clear {what} changes the layer");
|
||||
if runs() {
|
||||
let mut got = s.clone();
|
||||
try_clear_surface(&mut got, area, sel).unwrap();
|
||||
assert!(same_pixels(&got, &reference_fill_or_clear(&s, area, sel, None)), "clear {what}");
|
||||
if fmt.alpha {
|
||||
assert!(!same_pixels(&got, &s), "clear {what} changes the layer");
|
||||
}
|
||||
}
|
||||
for color in [[1.0, 1.0, 1.0, 1.0], [0.3, 0.5, 0.9, 1.0], [0.3, 0.5, 0.9, 0.4]] {
|
||||
for lock in [true, false] {
|
||||
for lock in [true, false].into_iter().filter(|_| runs()) {
|
||||
let mut got = s.clone();
|
||||
try_fill_surface(&mut got, area, color, sel, lock).unwrap();
|
||||
assert!(same_pixels(&got, &reference_fill_or_clear(&s, area, sel, Some((color, lock)))), "fill {color:?} lock {lock} {what}");
|
||||
|
||||
@@ -7,28 +7,32 @@ use serde_json::{Value, json};
|
||||
|
||||
/// Documents in different states: a Background only, a pixel layer active, a group active, a
|
||||
/// selection, no document.
|
||||
fn states() -> Vec<(&'static str, Session)> {
|
||||
let mut out = Vec::new();
|
||||
out.push(("no document", Session::new()));
|
||||
const STATES: [&str; 5] = ["no document", "background only", "pixel layer", "group, no background", "selection"];
|
||||
|
||||
/// A fresh session in `state`.
|
||||
fn state(state: &str) -> Session {
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", json!({"width": 40, "height": 30, "background": "white"})).unwrap();
|
||||
out.push(("background only", s));
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", json!({"width": 40, "height": 30, "background": "white"})).unwrap();
|
||||
s.execute("layer.new.layer", json!({})).unwrap();
|
||||
s.execute("edit.fill", json!({"color": "#ff0000"})).unwrap();
|
||||
out.push(("pixel layer", s));
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", json!({"width": 40, "height": 30, "background": "transparent"})).unwrap();
|
||||
s.execute("layer.new.group", json!({})).unwrap();
|
||||
out.push(("group, no background", s));
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", json!({"width": 40, "height": 30, "background": "white"})).unwrap();
|
||||
s.execute("layer.new.layer", json!({})).unwrap();
|
||||
s.execute("edit.fill", json!({"color": "#00ff00"})).unwrap();
|
||||
s.execute("select.rect", json!({"x": 2, "y": 2, "width": 10, "height": 10})).unwrap();
|
||||
out.push(("selection", s));
|
||||
out
|
||||
if state == "no document" {
|
||||
return s;
|
||||
}
|
||||
let background = if state == "group, no background" { "transparent" } else { "white" };
|
||||
s.execute("file.new", json!({"width": 40, "height": 30, "background": background})).unwrap();
|
||||
match state {
|
||||
"pixel layer" => {
|
||||
s.execute("layer.new.layer", json!({})).unwrap();
|
||||
s.execute("edit.fill", json!({"color": "#ff0000"})).unwrap();
|
||||
}
|
||||
"group, no background" => {
|
||||
s.execute("layer.new.group", json!({})).unwrap();
|
||||
}
|
||||
"selection" => {
|
||||
s.execute("layer.new.layer", json!({})).unwrap();
|
||||
s.execute("edit.fill", json!({"color": "#00ff00"})).unwrap();
|
||||
s.execute("select.rect", json!({"x": 2, "y": 2, "width": 10, "height": 10})).unwrap();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
fn params() -> Vec<Value> {
|
||||
@@ -63,13 +67,13 @@ fn precheck_agrees_with_execute() {
|
||||
let mut disagreements = Vec::new();
|
||||
for id in PRECHECKED {
|
||||
for p in params() {
|
||||
for (state, _) in states() {
|
||||
// A fresh copy of the state for each call: execute changes it.
|
||||
let mut s = states().into_iter().find(|(n, _)| *n == state).map(|(_, s)| s).unwrap();
|
||||
for name in STATES {
|
||||
// A fresh session for each call: execute changes it.
|
||||
let mut s = state(name);
|
||||
let pre = s.precheck(id, &p).is_ok();
|
||||
let ran = s.execute(id, p.clone()).is_ok();
|
||||
if pre != ran {
|
||||
disagreements.push(format!("{id} {p} on {state}: precheck {pre}, execute {ran}"));
|
||||
disagreements.push(format!("{id} {p} on {name}: precheck {pre}, execute {ran}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user