# HG changeset patch # User alfadur # Date 1553628588 -10800 # Node ID c97faf0aef7877422819438bba7920a57d33f73b # Parent f9f71cccb5c3d19c37ab1b5ebbb5c24a09b8dfe1 proptest atlas, find 🐛🐜🦋 diff -r f9f71cccb5c3 -r c97faf0aef78 rust/lib-hedgewars-engine/Cargo.toml --- a/rust/lib-hedgewars-engine/Cargo.toml Tue Mar 26 09:59:53 2019 -0400 +++ b/rust/lib-hedgewars-engine/Cargo.toml Tue Mar 26 22:29:48 2019 +0300 @@ -18,6 +18,9 @@ mapgen = { path = "../mapgen" } vec2d = { path = "../vec2d" } +[dev-dependencies] +proptest = "0.9.2" + [lib] name = "hedgewars_engine" crate-type = ["dylib"] diff -r f9f71cccb5c3 -r c97faf0aef78 rust/lib-hedgewars-engine/src/render/atlas.rs --- a/rust/lib-hedgewars-engine/src/render/atlas.rs Tue Mar 26 09:59:53 2019 -0400 +++ b/rust/lib-hedgewars-engine/src/render/atlas.rs Tue Mar 26 22:29:48 2019 +0300 @@ -174,11 +174,7 @@ if !self.texture_size.contains(size) { false } else { - if let Some(rect) = self - .atlases - .iter_mut() - .find_map(|a| a.insert(size)) - { + if let Some(rect) = self.atlases.iter_mut().find_map(|a| a.insert(size)) { } else if !self.repack(size) { let mut atlas = Atlas::new(self.texture_size); @@ -217,6 +213,7 @@ mod tests { use super::Atlas; use integral_geometry::{Rect, Size}; + use proptest::prelude::*; #[test] fn insert() { @@ -227,7 +224,61 @@ let rect_size = Size::new(11, 3); let rect = atlas.insert(rect_size).unwrap(); + assert_eq!(rect, Rect::at_origin(rect_size)); assert_eq!(2, atlas.free_rects.len()); } + + #[derive(Debug, Clone)] + struct TestRect(Size); + struct TestRectParameters(Size); + + impl Default for TestRectParameters { + fn default() -> Self { + Self(Size::square(64)) + } + } + + impl Arbitrary for TestRect { + type Parameters = TestRectParameters; + + fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { + (1..=args.0.width, 1..=args.0.height) + .prop_map(|(w, h)| TestRect(Size::new(w, h))) + .boxed() + } + + type Strategy = BoxedStrategy; + } + + trait HasSize { + fn size(&self) -> Size; + } + + impl HasSize for TestRect { + fn size(&self) -> Size { + self.0 + } + } + + impl HasSize for Rect { + fn size(&self) -> Size { + self.size() + } + } + + fn sum_area(items: &[S]) -> usize { + items.iter().map(|s| s.size().area()).sum() + } + + proptest! { + #[test] + fn prop_insert(rects in Vec::::arbitrary()) { + let mut atlas = Atlas::new(Size::square(2048)); + let inserted: Vec<_> = rects.iter().take_while(|TestRect(size)| atlas.insert(*size).is_some()).cloned().collect(); + + assert_eq!(inserted.len(), atlas.used_rects.len()); + assert_eq!(sum_area(&inserted), sum_area(&atlas.used_rects)); + } + } }