From aae8938c013149de94bd36d76cfa20e59fd4def6 Mon Sep 17 00:00:00 2001 From: Fintan Halpenny Date: Fri, 12 Jun 2026 10:40:22 +0100 Subject: [PATCH] radicle/test/arbitrary: Make BoundedVec shared A `BoundedVec` that implements `Arbitrary` is useful for all property testing. Move it from the `sigrefs` module so that it can be reused by other components. --- .../storage/refs/sigrefs/git/properties.rs | 19 ++----- crates/radicle/src/test/arbitrary.rs | 52 +++++++++++++++++++ 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/crates/radicle/src/storage/refs/sigrefs/git/properties.rs b/crates/radicle/src/storage/refs/sigrefs/git/properties.rs index 70db0700..5c3d636b 100644 --- a/crates/radicle/src/storage/refs/sigrefs/git/properties.rs +++ b/crates/radicle/src/storage/refs/sigrefs/git/properties.rs @@ -14,24 +14,11 @@ use crate::storage::refs::sigrefs::VerifiedCommit; use crate::storage::refs::sigrefs::read::{SignedRefsReader, Tip}; use crate::storage::refs::sigrefs::write::{SignedRefsWriter, Update}; use crate::storage::refs::{IDENTITY_ROOT, Refs}; +use crate::test::arbitrary; use super::Committer; -/// Newtype wrapper around [`Vec`] to keep the [`Arbitrary`] implementation -/// bounded to a smaller size. -#[derive(Clone, Debug)] -struct BoundedVec(Vec); - -impl qcheck::Arbitrary for BoundedVec { - fn arbitrary(g: &mut qcheck::Gen) -> Self { - let size = usize::arbitrary(g) % 24; - BoundedVec((0..size).map(|_| T::arbitrary(g)).collect()) - } - - fn shrink(&self) -> Box> { - Box::new(self.0.shrink().map(BoundedVec)) - } -} +type BoundedVec = arbitrary::BoundedVec; struct Verifier { key: PublicKey, @@ -176,7 +163,7 @@ fn initial_commit_roundtrip(mut refs: Refs) -> bool { #[quickcheck] fn chain_roundtrip(chain: BoundedVec) -> TestResult { - let chain = chain.0; + let chain = chain.to_vec(); if chain.is_empty() { return TestResult::discard(); } diff --git a/crates/radicle/src/test/arbitrary.rs b/crates/radicle/src/test/arbitrary.rs index a5c2fbe7..903e1d43 100644 --- a/crates/radicle/src/test/arbitrary.rs +++ b/crates/radicle/src/test/arbitrary.rs @@ -322,3 +322,55 @@ impl Arbitrary for UserAgent { .unwrap() } } + +/// Newtype wrapper around [`Vec`] to keep the [`Arbitrary`] implementation +/// bounded to a smaller size. +#[derive(Clone, Debug)] +pub struct BoundedVec { + inner: Vec, +} + +impl BoundedVec { + pub fn to_vec(self) -> Vec { + self.inner + } + + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } + + pub fn len(&self) -> usize { + self.inner.len() + } +} + +impl IntoIterator for BoundedVec { + type Item = T; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.inner.into_iter() + } +} + +impl<'a, T, const N: usize> IntoIterator for &'a BoundedVec { + type Item = &'a T; + type IntoIter = std::slice::Iter<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.inner.iter() + } +} + +impl qcheck::Arbitrary for BoundedVec { + fn arbitrary(g: &mut qcheck::Gen) -> Self { + let size = usize::arbitrary(g) % N; + Self { + inner: (0..size).map(|_| T::arbitrary(g)).collect(), + } + } + + fn shrink(&self) -> Box> { + Box::new(self.inner.shrink().map(|inner| Self { inner })) + } +}