add proptests to some layout ops

This commit is contained in:
🪞👃🪞 2025-01-27 15:58:28 +01:00
parent 1004c6a4d6
commit ad1abf6ec8
7 changed files with 206 additions and 57 deletions

View file

@ -8,3 +8,4 @@ tek_edn = { path = "../edn" }
[dev-dependencies]
tek_tui = { path = "../tui" }
proptest = "^1"

View file

@ -0,0 +1,10 @@
# Seeds for failure cases proptest has generated in the past. It is
# automatically read and these particular cases re-run before any
# novel cases are generated.
#
# It is recommended to check this file in to source control so that
# everyone who runs the test benefits from these saved cases.
cc b05b448ca4eb29304cae506927639494cae99a9e1ab40c58ac9dcb70d1ea1298 # shrinks to op_x = Some(0), op_y = None, content = "", x = 0, y = 46377, w = 0, h = 38318
cc efdb7136c68396fa7c632cc6d3b304545ada1ba134269278f890639559a17575 # shrinks to op_x = Some(0), op_y = Some(32768), content = "", x = 0, y = 0, w = 0, h = 0
cc f6d43c39db04f4c0112fe998ef68cff0a4454cd9791775a3014cc81997fbadf4 # shrinks to op_x = Some(10076), op_y = None, content = "", x = 60498, y = 0, w = 0, h = 0
cc 3cabc97f3fa3a83fd5f8cf2c619ed213c2be5e9b1cb13e5178bde87dd838e2f4 # shrinks to op_x = Some(3924), op_y = None, content = "", x = 63574, y = 0, w = 0, h = 0

View file

@ -38,29 +38,29 @@ pub trait Area<N: Coordinate>: From<[N;4]> + Debug + Copy {
[self.x(), self.y(), self.w(), h]
}
#[inline] fn x2 (&self) -> N {
self.x() + self.w()
self.x().plus(self.w())
}
#[inline] fn y2 (&self) -> N {
self.y() + self.h()
self.y().plus(self.h())
}
#[inline] fn lrtb (&self) -> [N;4] {
[self.x(), self.x2(), self.y(), self.y2()]
}
#[inline] fn center (&self) -> [N;2] {
[self.x() + self.w()/2.into(), self.y() + self.h()/2.into()]
[self.x().plus(self.w()/2.into()), self.y().plus(self.h()/2.into())]
}
#[inline] fn center_x (&self, n: N) -> [N;4] {
let [x, y, w, h] = self.xywh();
[(x + w / 2.into()).minus(n / 2.into()), y + h / 2.into(), n, 1.into()]
[(x.plus(w / 2.into())).minus(n / 2.into()), y.plus(h / 2.into()), n, 1.into()]
}
#[inline] fn center_y (&self, n: N) -> [N;4] {
let [x, y, w, h] = self.xywh();
[x + w / 2.into(), (y + h / 2.into()).minus(n / 2.into()), 1.into(), n]
[x.plus(w / 2.into()), (y + h / 2.into()).minus(n / 2.into()), 1.into(), n]
}
#[inline] fn center_xy (&self, [n, m]: [N;2]) -> [N;4] {
let [x, y, w, h] = self.xywh();
[(x + w / 2.into()).minus(n / 2.into()), (y + h / 2.into()).minus(m / 2.into()), n, m]
[(x.plus(w / 2.into())).minus(n / 2.into()), (y.plus(h / 2.into())).minus(m / 2.into()), n, m]
}
#[inline] fn centered (&self) -> [N;2] {

View file

@ -1,7 +1,11 @@
use std::fmt::{Debug, Display};
use std::ops::{Add, Sub, Mul, Div};
impl Coordinate for u16 {}
impl Coordinate for u16 {
#[inline] fn plus (self, other: Self) -> Self {
self.saturating_add(other)
}
}
/// A linear coordinate.
pub trait Coordinate: Send + Sync + Copy
@ -15,6 +19,7 @@ pub trait Coordinate: Send + Sync + Copy
+ Into<usize>
+ Into<f64>
{
#[inline] fn zero () -> Self { 0.into() }
#[inline] fn minus (self, other: Self) -> Self {
if self >= other {
self - other
@ -22,7 +27,5 @@ pub trait Coordinate: Send + Sync + Copy
0.into()
}
}
#[inline] fn zero () -> Self {
0.into()
}
fn plus (self, other: Self) -> Self;
}

View file

@ -139,8 +139,7 @@ transform_xy!("fill/x" "fill/y" "fill/xy" |self: Fill, to|{
X(_) => [x0, y, wmax, h],
Y(_) => [x, y0, w, hmax],
XY(_) => [x0, y0, wmax, hmax],
}.into()
});
}.into() });
transform_xy_unit!("fixed/x" "fixed/y" "fixed/xy"|self: Fixed, area|{
let [x, y, w, h] = area.xywh();
let fixed_area = match self {
@ -154,8 +153,7 @@ transform_xy_unit!("fixed/x" "fixed/y" "fixed/xy"|self: Fixed, area|{
Self::Y(fh, _) => [x, y, w, *fh],
Self::XY(fw, fh, _) => [x, y, *fw, *fh],
};
fixed_area
});
fixed_area });
transform_xy_unit!("min/x" "min/y" "min/xy"|self: Min, area|{
let area = Render::layout(&self.content(), area);
match self {
@ -175,24 +173,60 @@ transform_xy_unit!("shrink/x" "shrink/y" "shrink/xy"|self: Shrink, area|Render::
[area.x(), area.y(), area.w().minus(self.dx()), area.h().minus(self.dy())].into()));
transform_xy_unit!("expand/x" "expand/y" "expand/xy"|self: Expand, area|Render::layout(
&self.content(),
[area.x(), area.y(), area.w() + self.dx(), area.h() + self.dy()].into()));
[area.x(), area.y(), area.w().plus(self.dx()), area.h().plus(self.dy())].into()));
transform_xy_unit!("push/x" "push/y" "push/xy"|self: Push, area|{
let area = Render::layout(&self.content(), area);
[area.x() + self.dx(), area.y() + self.dy(), area.w(), area.h()]
});
[area.x().plus(self.dx()), area.y().plus(self.dy()), area.w(), area.h()] });
transform_xy_unit!("pull/x" "pull/y" "pull/xy"|self: Pull, area|{
let area = Render::layout(&self.content(), area);
[area.x().minus(self.dx()), area.y().minus(self.dy()), area.w(), area.h()]
});
[area.x().minus(self.dx()), area.y().minus(self.dy()), area.w(), area.h()] });
transform_xy_unit!("margin/x" "margin/y" "margin/xy"|self: Margin, area|{
let area = Render::layout(&self.content(), area);
let dx = self.dx();
let dy = self.dy();
[area.x().minus(dx), area.y().minus(dy), area.w() + dy + dy, area.h() + dy + dy]
});
[area.x().minus(dx), area.y().minus(dy), area.w().plus(dy.plus(dy)), area.h().plus(dy.plus(dy))] });
transform_xy_unit!("padding/x" "padding/y" "padding/xy"|self: Padding, area|{
let area = Render::layout(&self.content(), area);
let dx = self.dx();
let dy = self.dy();
[area.x() + dx, area.y() + dy, area.w().minus(dy + dy), area.h().minus(dy + dy), ]
});
[area.x().plus(dx), area.y().plus(dy), area.w().minus(dy.plus(dy)), area.h().minus(dy.plus(dy)), ] });
#[cfg(test)] mod test_op_transform {
use super::*;
use proptest::prelude::*;
use proptest::option::of;
macro_rules! test_op_transform {
($fn:ident, $Op:ident) => {
proptest! {
#[test] fn $fn (
op_x in of(u16::MIN..u16::MAX),
op_y in of(u16::MIN..u16::MAX),
content in "\\PC*",
x in u16::MIN..u16::MAX,
y in u16::MIN..u16::MAX,
w in u16::MIN..u16::MAX,
h in u16::MIN..u16::MAX,
) {
if let Some(op) = match (op_x, op_y) {
(Some(x), Some(y)) => Some($Op::xy(x, y, content)),
(Some(x), None) => Some($Op::x(x, content)),
(Some(y), None) => Some($Op::y(y, content)),
_ => None
} {
assert_eq!(Content::layout(&op, [x, y, w, h]),
Render::layout(&op, [x, y, w, h]));
}
}
}
}
}
test_op_transform!(test_op_fixed, Fixed);
test_op_transform!(test_op_min, Min);
test_op_transform!(test_op_max, Max);
test_op_transform!(test_op_push, Push);
test_op_transform!(test_op_pull, Pull);
test_op_transform!(test_op_shrink, Shrink);
test_op_transform!(test_op_expand, Expand);
test_op_transform!(test_op_margin, Margin);
test_op_transform!(test_op_padding, Padding);
}