diff --git a/.gitignore b/.gitignore index 6fd4b5c..458a18e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ flamegraph.svg perf.data* out +proptest-regressions diff --git a/Cargo.lock b/Cargo.lock index 57ecc36..3a07ba6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -186,6 +186,21 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bit_field" version = "0.10.2" @@ -481,6 +496,8 @@ dependencies = [ "flate2", "image", "miette", + "proptest", + "proptest-derive", "rand", "serde", "serde_json", @@ -488,6 +505,12 @@ dependencies = [ "termcolor", ] +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + [[package]] name = "fdeflate" version = "0.3.4" @@ -516,6 +539,12 @@ dependencies = [ "spin", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "getrandom" version = "0.2.15" @@ -610,7 +639,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f79afb8cbee2ef20f59ccd477a218c12a93943d075b492015ecb1bb81f8ee904" dependencies = [ "byteorder-lite", - "quick-error", + "quick-error 2.0.1", ] [[package]] @@ -729,6 +758,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -901,6 +936,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -1020,6 +1056,37 @@ dependencies = [ "syn", ] +[[package]] +name = "proptest" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags 2.6.0", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "proptest-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff7ff745a347b87471d859a377a9a404361e7efc2a971d73424a6d183c0fc77" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "qoi" version = "0.4.1" @@ -1029,6 +1096,12 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quick-error" version = "2.0.1" @@ -1074,6 +1147,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + [[package]] name = "rav1e" version = "0.7.1" @@ -1118,7 +1200,7 @@ dependencies = [ "avif-serialize", "imgref", "loop9", - "quick-error", + "quick-error 2.0.1", "rav1e", "rgb", ] @@ -1200,6 +1282,18 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error 1.2.3", + "tempfile", + "wait-timeout", +] + [[package]] name = "ryu" version = "1.0.18" @@ -1384,6 +1478,19 @@ version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -1498,6 +1605,12 @@ dependencies = [ "winnow", ] +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicode-ident" version = "1.0.13" @@ -1545,6 +1658,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "walkdir" version = "2.5.0" diff --git a/Cargo.toml b/Cargo.toml index 88b63fd..ea2dcc9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,8 @@ clap = { version = "4.4.8", features = ["derive"] } flate2 = "1.0.28" image = "0.25.2" miette = { version = "7.2.0", features = ["fancy"] } +proptest = "1.5.0" +proptest-derive = "0.5.0" rand = { version = "0.8.5", features = ["small_rng"] } serde = { version = "1.0.192", features = ["derive"] } serde_json = "1.0.108" diff --git a/src/common/block.rs b/src/common/block.rs index 74644fd..a3e893b 100644 --- a/src/common/block.rs +++ b/src/common/block.rs @@ -60,6 +60,7 @@ impl Transformable for Block { #[cfg(test)] mod test { use super::*; + use proptest::{prop_assert_eq, proptest}; #[test] fn transformations() { @@ -76,18 +77,18 @@ mod test { assert_eq!(m, Position::new(8, 8)); } - #[test] - fn identity_transformation() { - let b = Block::new(Position::new(10, 5), Direction::Right, Position::new(4, 3)); + proptest! { + #[test] + fn identity_transformation(dir: Direction, pos: Position, size: Position) { + let b = Block::new(pos, dir, size); - let t = b.world_to_block(); + let t = b.world_to_block(); - let n = b.transform(t); + let n = b.transform(t); - dbg!(t, n); - - assert_eq!(n.dir, Direction::Up); - assert_eq!(n.pos, Position::new(0, 0)); - assert_eq!(n.size, Position::new(4, 3)); + prop_assert_eq!(n.dir, Direction::Up); + prop_assert_eq!(n.pos, Position::new(0, 0)); + prop_assert_eq!(n.size, size); + } } } diff --git a/src/common/direction.rs b/src/common/direction.rs index 64bc546..bef4b06 100644 --- a/src/common/direction.rs +++ b/src/common/direction.rs @@ -2,6 +2,7 @@ use crate::prelude::*; use serde::{Deserialize, Serialize}; #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Deserialize, Serialize)] +#[cfg_attr(test, derive(proptest_derive::Arbitrary))] pub enum Direction { Up, Right, diff --git a/src/common/position.rs b/src/common/position.rs index 56014b4..dcdc5ca 100644 --- a/src/common/position.rs +++ b/src/common/position.rs @@ -4,6 +4,7 @@ use serde::{Deserialize, Serialize}; pub type PositionType = i32; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)] +#[cfg_attr(test, derive(proptest_derive::Arbitrary))] pub struct Position { pub x: PositionType, pub y: PositionType, diff --git a/src/common/transformation.rs b/src/common/transformation.rs index 63f3a4d..1e97ac8 100644 --- a/src/common/transformation.rs +++ b/src/common/transformation.rs @@ -75,6 +75,7 @@ impl Transformable for Direction { #[cfg(test)] mod test { use crate::prelude::*; + use proptest::{prop_assert_eq, proptest}; #[test] fn position() { @@ -87,21 +88,16 @@ mod test { assert_eq!(p.transform(t), Position::new(-6, -10)); } - #[test] - fn invert() { - let transformations = [ - Transformation::new(Direction::Up, Position::new(-3, -5)), - Transformation::new(Direction::Right, Position::new(-3, -5)), - Transformation::new(Direction::Down, Position::new(-3, -5)), - Transformation::new(Direction::Left, Position::new(-3, -5)), - ]; + proptest! { + #[test] + fn invert(dir: Direction, pos: Position) { + let o = Transformation::new(dir, pos); - for o in transformations { let i = o.invert(); let c = o.chain(i); - assert_eq!(c.rot, Direction::Up, "o: {:?}, i: {:?}, c: {:?}", o, i, c); - assert_eq!( + prop_assert_eq!(c.rot, Direction::Up, "o: {:?}, i: {:?}, c: {:?}", o, i, c); + prop_assert_eq!( c.pos, Position::new(0, 0), "o: {:?}, i: {:?}, c: {:?}", @@ -109,6 +105,7 @@ mod test { i, c ); + } } }