Ignoring is for cost, not for status: a fuzzer earns it, a known defect does not. Hiding this one behind an attribute turns a loud failure into a quiet one nobody goes looking for. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
98 lines
3.1 KiB
Rust
98 lines
3.1 KiB
Rust
//! The smallest tree that lays out differently on a second frame, shrunk from
|
|
//! a 402-widget one `tests/shrink.rs` grew. Both of these fail: a cold frame
|
|
//! leaves a wrapping text shaped at a width it was measured in rather than the
|
|
//! one it was given, and a repaint is what puts it right. So the warm-against-
|
|
//! cold oracle in `generated.rs` has been comparing against a tree that had
|
|
//! not settled, and some of what it called a warm defect is the cold side
|
|
//! being wrong.
|
|
|
|
use iris::harness::Harness;
|
|
use iris::prelude::*;
|
|
|
|
/// Six widgets, shrunk from a 402-widget tree the fuzzer found. Nothing about
|
|
/// the tree changes -- every widget is marked for redraw and the frame is
|
|
/// taken again -- so no box may move, and a warm frame has to land where a
|
|
/// cold one does.
|
|
fn plant(h: &mut Harness) -> Vec<WidgetId> {
|
|
let plain = wtext("Wrapping").size(16).wrap(false).add(&mut h.rsc);
|
|
let wrapped = wtext("Wrapping shapes").size(16).wrap(true).add(&mut h.rsc);
|
|
let sized = SetSize {
|
|
inner: wrapped.add_strong(&mut h.rsc),
|
|
x: Some(Len::px(76.0)),
|
|
y: None,
|
|
}
|
|
.add(&mut h.rsc);
|
|
let aligned = Aligned {
|
|
inner: sized.add_strong(&mut h.rsc),
|
|
align: Align {
|
|
x: Some(AxisAlign::Pos),
|
|
y: Some(AxisAlign::Pos),
|
|
},
|
|
}
|
|
.add(&mut h.rsc);
|
|
let stack = Stack {
|
|
children: vec![plain.add_strong(&mut h.rsc), aligned.add_strong(&mut h.rsc)],
|
|
size: StackSize::Child(0),
|
|
}
|
|
.add(&mut h.rsc);
|
|
let root = (stack,).span(Dir::RIGHT).add(&mut h.rsc);
|
|
h.set_root(root);
|
|
vec![
|
|
plain.id(),
|
|
wrapped.id(),
|
|
sized.id(),
|
|
aligned.id(),
|
|
stack.id(),
|
|
root.id(),
|
|
]
|
|
}
|
|
|
|
/// The first frame does not reach the layout a second one does, so "cold" is
|
|
/// not a fixed point and comparing against it compares against a tree that
|
|
/// has not settled.
|
|
#[test]
|
|
fn one_frame_is_enough() {
|
|
let mut h = Harness::new((640, 900));
|
|
let ids = plant(&mut h);
|
|
let first = h.region(&ids[1]).unwrap();
|
|
for _ in 0..3 {
|
|
for &id in &ids {
|
|
h.rsc.widgets_mut().get_dyn_mut(id);
|
|
}
|
|
h.frame();
|
|
}
|
|
let settled = h.region(&ids[1]).unwrap();
|
|
println!(
|
|
"first frame {} tall, settled {} tall",
|
|
first.bot_right.y - first.top_left.y,
|
|
settled.bot_right.y - settled.top_left.y
|
|
);
|
|
assert_eq!(
|
|
first.bot_right.y - first.top_left.y,
|
|
settled.bot_right.y - settled.top_left.y,
|
|
"the first frame had not finished laying out"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn repainting_everything_moves_nothing() {
|
|
let mut warm = Harness::new((640, 900));
|
|
let ids = plant(&mut warm);
|
|
for &id in &ids {
|
|
warm.rsc.widgets_mut().get_dyn_mut(id);
|
|
}
|
|
warm.frame();
|
|
|
|
let mut cold = Harness::new((640, 900));
|
|
let cold_ids = plant(&mut cold);
|
|
|
|
let mut wrong = Vec::new();
|
|
for (i, (&w, &c)) in ids.iter().zip(&cold_ids).enumerate() {
|
|
let (got, want) = (warm.region(&w), cold.region(&c));
|
|
if got != want {
|
|
wrong.push(format!("widget {i}: warm {got:?} cold {want:?}"));
|
|
}
|
|
}
|
|
assert!(wrong.is_empty(), "{}", wrong.join("\n"));
|
|
}
|