From 38ed3fb6c26d5b1c954c4ab1b7d1ac96f5e71825 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 3 Jan 2026 13:15:18 -0700 Subject: [PATCH] ctutils: initial proptests Adds initial proptests for `CtEq::ct_eq` and `CtSelect::ct_select` for all core signed and unsigned integer types --- Cargo.lock | 1 + ctutils/Cargo.toml | 3 ++ ctutils/tests/proptests.rs | 56 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 ctutils/tests/proptests.rs diff --git a/Cargo.lock b/Cargo.lock index 3d75b464..031abdf8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -111,6 +111,7 @@ name = "ctutils" version = "0.3.1" dependencies = [ "cmov", + "proptest", "subtle", ] diff --git a/ctutils/Cargo.toml b/ctutils/Cargo.toml index c9cb17cb..fda861d3 100644 --- a/ctutils/Cargo.toml +++ b/ctutils/Cargo.toml @@ -22,5 +22,8 @@ cmov = "0.4.3" # optional dependencies subtle = { version = "2", optional = true, default-features = false } +[dev-dependencies] +proptest = "1.9" + [package.metadata.docs.rs] all-features = true diff --git a/ctutils/tests/proptests.rs b/ctutils/tests/proptests.rs new file mode 100644 index 00000000..52bee384 --- /dev/null +++ b/ctutils/tests/proptests.rs @@ -0,0 +1,56 @@ +/// Write the proptests for an integer type. +macro_rules! int_proptests { + ( $($int:ident),+ ) => { + $( + mod $int { + use ctutils::{CtSelect, CtEq, Choice}; + use proptest::prelude::*; + + proptest! { + #[test] + fn ct_assign(a in any::<$int>(), b in any::<$int>(), byte in any::()) { + let choice = Choice::from_u8_lsb(byte); + let mut actual = a; + actual.ct_assign(&b, choice); + + let expected = if byte & 1 == 1 { + b + } else { + a + }; + + prop_assert_eq!(expected, actual); + } + + #[test] + fn ct_eq(a in any::<$int>(), b in any::<$int>()) { + let actual = a.ct_eq(&b); + prop_assert_eq!(a == b, actual.to_bool()); + } + + #[test] + fn ct_ne(a in any::<$int>(), b in any::<$int>()) { + let actual = a.ct_ne(&b); + prop_assert_eq!(a != b, actual.to_bool()); + } + + #[test] + fn ct_select(a in any::<$int>(), b in any::<$int>(), byte in any::()) { + let choice = Choice::from_u8_lsb(byte); + let actual = a.ct_select(&b, choice); + + let expected = if byte & 1 == 1 { + b + } else { + a + }; + + prop_assert_eq!(expected, actual); + } + } + } + )+ + }; +} + +int_proptests!(i8, i16, i32, i64, i128, u8, u16, u32, u64, u128);