No public description

PiperOrigin-RevId: 1002467443
diff --git a/rust/e2e_tests/gtest_registration_test.rs b/rust/e2e_tests/gtest_registration_test.rs
index fa6142a..a89af95 100644
--- a/rust/e2e_tests/gtest_registration_test.rs
+++ b/rust/e2e_tests/gtest_registration_test.rs
@@ -37,6 +37,7 @@
     // Verify that the expected fuzz tests are listed as regular tests.
     expect_that!(stdout, matchers::contains_substring("bool_fuzz_test: test"));
     expect_that!(stdout, matchers::contains_substring("multi_arg_fuzz_test: test"));
+    expect_that!(stdout, matchers::contains_substring("tuple_and_vec_fuzz_test: test"));
 }
 
 #[gtest]
diff --git a/rust/e2e_tests/testdata/fuzz_tests_as_gtests.rs b/rust/e2e_tests/testdata/fuzz_tests_as_gtests.rs
index d50cf14..aac25d6 100644
--- a/rust/e2e_tests/testdata/fuzz_tests_as_gtests.rs
+++ b/rust/e2e_tests/testdata/fuzz_tests_as_gtests.rs
@@ -13,6 +13,8 @@
 // limitations under the License.
 
 use fuzztest::domains::arbitrary::Arbitrary;
+use fuzztest::domains::range::InRange;
+use fuzztest::domains::tuple_of::TupleOf2;
 use fuzztest::fuzztest;
 use std::sync::Once;
 
@@ -30,3 +32,12 @@
     _c = Arbitrary::<bool>::default(),
 )]
 fn multi_arg_fuzz_test(_a: i32, _b: f32, _c: bool) {}
+
+#[fuzztest(
+    _a = TupleOf2::from((InRange::new(0i32, 10), Arbitrary::<bool>::default())),
+    _b = Arbitrary::<(i32, Vec<u8>)>::default(),
+    _c = Arbitrary::<Vec<i32>>::default(),
+)]
+fn tuple_and_vec_fuzz_test(_a: (i32, bool), _b: (i32, Vec<u8>), _c: Vec<i32>) {
+    assert!((0..=10).contains(&_a.0));
+}
diff --git a/rust/src/domains/arbitrary.rs b/rust/src/domains/arbitrary.rs
index df1023b..066255f 100644
--- a/rust/src/domains/arbitrary.rs
+++ b/rust/src/domains/arbitrary.rs
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+use super::containers::VecOf;
 use super::utility::choose_value;
 use super::utility::map_char_to_int;
 use super::utility::map_int_to_char;
@@ -319,6 +320,87 @@
     }
 }
 
+impl<T> Domain for Arbitrary<Vec<T>>
+where
+    Arbitrary<T>: Domain,
+{
+    type UserValue<'user> = Vec<<Arbitrary<T> as Domain>::UserValue<'user>>;
+    type CorpusValue = Vec<<Arbitrary<T> as Domain>::CorpusValue>;
+
+    fn init(&mut self, rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> {
+        VecOf::new(Arbitrary::<T>::default()).init(rng)
+    }
+
+    fn mutate(
+        &mut self,
+        val: &mut Self::CorpusValue,
+        rng: &mut dyn rand::Rng,
+        only_shrink: bool,
+    ) -> anyhow::Result<()> {
+        VecOf::new(Arbitrary::<T>::default()).mutate(val, rng, only_shrink)
+    }
+
+    fn corpus_to_user_value<'a>(
+        &self,
+        corpus_value: &'a Self::CorpusValue,
+    ) -> anyhow::Result<Self::UserValue<'a>> {
+        VecOf::new(Arbitrary::<T>::default()).corpus_to_user_value(corpus_value)
+    }
+
+    fn validate_corpus_value(&self, corpus_value: &Self::CorpusValue) -> anyhow::Result<()> {
+        VecOf::new(Arbitrary::<T>::default()).validate_corpus_value(corpus_value)
+    }
+}
+
+macro_rules! impl_domain_for_arbitrary_tuple {
+    ($( $ty:ident ),+ $(,)?) => {
+        impl<$( $ty ),+> Domain for Arbitrary<( $( $ty, )+ )>
+        where
+            $( Arbitrary<$ty>: Domain, )+
+        {
+            type UserValue<'user> = ( $( <Arbitrary<$ty> as Domain>::UserValue<'user>, )+ );
+            type CorpusValue = ( $( <Arbitrary<$ty> as Domain>::CorpusValue, )+ );
+
+            fn init(&mut self, rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> {
+                ( $( Arbitrary::<$ty>::default(), )+ ).init(rng)
+            }
+
+            fn mutate(
+                &mut self,
+                val: &mut Self::CorpusValue,
+                rng: &mut dyn rand::Rng,
+                only_shrink: bool,
+            ) -> anyhow::Result<()> {
+                ( $( Arbitrary::<$ty>::default(), )+ ).mutate(val, rng, only_shrink)
+            }
+
+            fn corpus_to_user_value<'a>(
+                &self,
+                corpus_value: &'a Self::CorpusValue,
+            ) -> anyhow::Result<Self::UserValue<'a>> {
+                ( $( Arbitrary::<$ty>::default(), )+ ).corpus_to_user_value(corpus_value)
+            }
+
+            fn validate_corpus_value(&self, corpus_value: &Self::CorpusValue) -> anyhow::Result<()> {
+                ( $( Arbitrary::<$ty>::default(), )+ ).validate_corpus_value(corpus_value)
+            }
+        }
+    };
+}
+
+impl_domain_for_arbitrary_tuple!(T0);
+impl_domain_for_arbitrary_tuple!(T0, T1);
+impl_domain_for_arbitrary_tuple!(T0, T1, T2);
+impl_domain_for_arbitrary_tuple!(T0, T1, T2, T3);
+impl_domain_for_arbitrary_tuple!(T0, T1, T2, T3, T4);
+impl_domain_for_arbitrary_tuple!(T0, T1, T2, T3, T4, T5);
+impl_domain_for_arbitrary_tuple!(T0, T1, T2, T3, T4, T5, T6);
+impl_domain_for_arbitrary_tuple!(T0, T1, T2, T3, T4, T5, T6, T7);
+impl_domain_for_arbitrary_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8);
+impl_domain_for_arbitrary_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
+impl_domain_for_arbitrary_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
+impl_domain_for_arbitrary_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
+
 #[cfg(test)]
 mod tests {
     use std::collections::HashSet;
@@ -755,4 +837,90 @@
             );
         }
     }
+
+    #[test]
+    fn test_arbitrary_vec() {
+        let mut domain = Arbitrary::<Vec<i32>>::default();
+        let mut rng = get_rng();
+
+        for _ in 0..20 {
+            let val = domain.init(&mut rng).unwrap();
+            assert!(val.len() <= 1);
+            assert!(domain.validate_corpus_value(&val).is_ok());
+            assert_eq!(domain.corpus_to_user_value(&val).unwrap(), val);
+        }
+
+        let mut val = vec![10, 20, 30];
+        let mut changed = false;
+        for _ in 0..50 {
+            let prev = val.clone();
+            domain.mutate(&mut val, &mut rng, false).unwrap();
+            if val != prev {
+                changed = true;
+            }
+        }
+        assert!(changed);
+
+        // Shrinking should eventually reach the empty vector and zero elements.
+        let mut shrink_val = vec![100, 200, 300];
+        for _ in 0..500 {
+            if shrink_val.is_empty() {
+                break;
+            }
+            let prev_len = shrink_val.len();
+            domain.mutate(&mut shrink_val, &mut rng, true).unwrap();
+            assert!(shrink_val.len() <= prev_len);
+        }
+        assert!(shrink_val.is_empty());
+
+        let bytes = domain.serialize_corpus(&vec![1, -2, 3]).unwrap();
+        let parsed = domain.parse_corpus(&bytes).unwrap();
+        assert_eq!(parsed, vec![1, -2, 3]);
+    }
+
+    #[test]
+    fn test_arbitrary_tuples() {
+        let mut rng = get_rng();
+
+        // 1-tuple
+        let mut d1 = Arbitrary::<(i32,)>::default();
+        let mut v1 = d1.init(&mut rng).unwrap();
+        let orig_v1 = v1;
+        d1.mutate(&mut v1, &mut rng, false).unwrap();
+        assert_ne!(v1, orig_v1);
+        assert_eq!(d1.corpus_to_user_value(&v1).unwrap(), v1);
+        assert!(d1.validate_corpus_value(&v1).is_ok());
+
+        // 2-tuple shrinking to (0, false)
+        let mut d2 = Arbitrary::<(i32, bool)>::default();
+        let mut v2 = (1000i32, true);
+        for _ in 0..500 {
+            if v2 == (0, false) {
+                break;
+            }
+            d2.mutate(&mut v2, &mut rng, true).unwrap();
+        }
+        assert_eq!(v2, (0, false));
+
+        // 12-tuple
+        type Tuple12 = (u8, i8, u16, i16, u32, i32, u64, i64, usize, isize, bool, char);
+        let mut d12 = Arbitrary::<Tuple12>::default();
+        let mut v12 = d12.init(&mut rng).unwrap();
+        for _ in 0..20 {
+            d12.mutate(&mut v12, &mut rng, false).unwrap();
+            assert!(d12.validate_corpus_value(&v12).is_ok());
+        }
+        assert_eq!(d12.corpus_to_user_value(&v12).unwrap(), v12);
+        let bytes = d12.serialize_corpus(&v12).unwrap();
+        assert_eq!(d12.parse_corpus(&bytes).unwrap(), v12);
+
+        // Nested Arbitrary<Vec<(i32, bool)>>
+        let mut d_nested = Arbitrary::<Vec<(i32, bool)>>::default();
+        let mut v_nested = d_nested.init(&mut rng).unwrap();
+        for _ in 0..20 {
+            d_nested.mutate(&mut v_nested, &mut rng, false).unwrap();
+            assert!(d_nested.validate_corpus_value(&v_nested).is_ok());
+        }
+        assert_eq!(d_nested.corpus_to_user_value(&v_nested).unwrap(), v_nested);
+    }
 }
diff --git a/rust/src/domains/tuple_of.rs b/rust/src/domains/tuple_of.rs
index 4db94f8..34a5ab5 100644
--- a/rust/src/domains/tuple_of.rs
+++ b/rust/src/domains/tuple_of.rs
@@ -12,9 +12,456 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+use super::Domain;
+use anyhow::Result;
+use rand::{Rng, RngExt};
+
 // TODO(yamilmorales, tinmar, mathuxny-73): Replace generated wrapper domain (to deduplicate
-// implementations for tests with the same number of parameters) with these, meaning we should
-// `impl Domain` on these tuples.
+// implementations for tests with the same number of parameters) with these tuple domains.
 
 pub type TupleOf1<T0> = (T0,);
 pub type TupleOf2<T0, T1> = (T0, T1);
+pub type TupleOf3<T0, T1, T2> = (T0, T1, T2);
+pub type TupleOf4<T0, T1, T2, T3> = (T0, T1, T2, T3);
+pub type TupleOf5<T0, T1, T2, T3, T4> = (T0, T1, T2, T3, T4);
+pub type TupleOf6<T0, T1, T2, T3, T4, T5> = (T0, T1, T2, T3, T4, T5);
+pub type TupleOf7<T0, T1, T2, T3, T4, T5, T6> = (T0, T1, T2, T3, T4, T5, T6);
+pub type TupleOf8<T0, T1, T2, T3, T4, T5, T6, T7> = (T0, T1, T2, T3, T4, T5, T6, T7);
+pub type TupleOf9<T0, T1, T2, T3, T4, T5, T6, T7, T8> = (T0, T1, T2, T3, T4, T5, T6, T7, T8);
+pub type TupleOf10<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> =
+    (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
+pub type TupleOf11<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> =
+    (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
+pub type TupleOf12<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> =
+    (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
+
+impl<T0> Domain for (T0,)
+where
+    T0: Domain,
+{
+    type UserValue<'user> = (T0::UserValue<'user>,);
+    type CorpusValue = (T0::CorpusValue,);
+
+    fn init(&mut self, rng: &mut dyn Rng) -> Result<Self::CorpusValue> {
+        Ok((self.0.init(rng)?,))
+    }
+
+    fn mutate(
+        &mut self,
+        corpus_value: &mut Self::CorpusValue,
+        rng: &mut dyn Rng,
+        only_shrink: bool,
+    ) -> Result<()> {
+        self.0.mutate(&mut corpus_value.0, rng, only_shrink)
+    }
+
+    fn corpus_to_user_value<'a>(
+        &self,
+        corpus_value: &'a Self::CorpusValue,
+    ) -> Result<Self::UserValue<'a>> {
+        Ok((self.0.corpus_to_user_value(&corpus_value.0)?,))
+    }
+
+    fn validate_corpus_value(&self, corpus_value: &Self::CorpusValue) -> Result<()> {
+        self.0.validate_corpus_value(&corpus_value.0)
+    }
+}
+
+macro_rules! impl_domain_for_tuple {
+    ($count:expr, $( $idx:tt : $ty:ident ),+ $(,)?) => {
+        impl<$( $ty ),+> Domain for ( $( $ty, )+ )
+        where
+            $( $ty: Domain, )+
+        {
+            type UserValue<'user> = ( $( $ty::UserValue<'user>, )+ );
+            type CorpusValue = ( $( $ty::CorpusValue, )+ );
+
+            fn init(&mut self, rng: &mut dyn Rng) -> Result<Self::CorpusValue> {
+                Ok(( $( self.$idx.init(rng)?, )+ ))
+            }
+
+            fn mutate(
+                &mut self,
+                corpus_value: &mut Self::CorpusValue,
+                rng: &mut dyn Rng,
+                only_shrink: bool,
+            ) -> Result<()> {
+                match rng.random_range(0usize..$count) {
+                    $(
+                        $idx => self.$idx.mutate(&mut corpus_value.$idx, rng, only_shrink),
+                    )+
+                    _ => unreachable!(),
+                }
+            }
+
+            fn corpus_to_user_value<'a>(
+                &self,
+                corpus_value: &'a Self::CorpusValue,
+            ) -> Result<Self::UserValue<'a>> {
+                Ok(( $( self.$idx.corpus_to_user_value(&corpus_value.$idx)?, )+ ))
+            }
+
+            fn validate_corpus_value(&self, corpus_value: &Self::CorpusValue) -> Result<()> {
+                $( self.$idx.validate_corpus_value(&corpus_value.$idx)?; )+
+                Ok(())
+            }
+        }
+    };
+}
+
+impl_domain_for_tuple!(2, 0: T0, 1: T1);
+impl_domain_for_tuple!(3, 0: T0, 1: T1, 2: T2);
+impl_domain_for_tuple!(4, 0: T0, 1: T1, 2: T2, 3: T3);
+impl_domain_for_tuple!(5, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4);
+impl_domain_for_tuple!(6, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5);
+impl_domain_for_tuple!(7, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6);
+impl_domain_for_tuple!(8, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7);
+impl_domain_for_tuple!(9, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8);
+impl_domain_for_tuple!(
+    10,
+    0: T0,
+    1: T1,
+    2: T2,
+    3: T3,
+    4: T4,
+    5: T5,
+    6: T6,
+    7: T7,
+    8: T8,
+    9: T9
+);
+impl_domain_for_tuple!(
+    11,
+    0: T0,
+    1: T1,
+    2: T2,
+    3: T3,
+    4: T4,
+    5: T5,
+    6: T6,
+    7: T7,
+    8: T8,
+    9: T9,
+    10: T10
+);
+impl_domain_for_tuple!(
+    12,
+    0: T0,
+    1: T1,
+    2: T2,
+    3: T3,
+    4: T4,
+    5: T5,
+    6: T6,
+    7: T7,
+    8: T8,
+    9: T9,
+    10: T10,
+    11: T11
+);
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::domains::arbitrary::Arbitrary;
+    use crate::domains::containers::{ContainerDomain, VecOf};
+    use crate::domains::range::InRange;
+    use googletest::prelude::*;
+    use rand::rngs::{SmallRng, SysRng};
+    use rand::SeedableRng;
+
+    fn get_rng() -> SmallRng {
+        SmallRng::try_from_rng(&mut SysRng).expect("Failed to create RNG")
+    }
+
+    #[gtest]
+    fn test_tuple_of_1_domain() {
+        let mut domain: TupleOf1<_> = (InRange::new(10i32, 20),);
+        let mut rng = get_rng();
+
+        for _ in 0..50 {
+            let mut val = domain.init(&mut rng).unwrap();
+            expect_that!(val.0, all!(ge(10), le(20)));
+            expect_that!(domain.validate_corpus_value(&val).is_ok(), eq(true));
+            expect_that!(domain.corpus_to_user_value(&val).unwrap(), eq(val));
+
+            domain.mutate(&mut val, &mut rng, false).unwrap();
+            expect_that!(val.0, all!(ge(10), le(20)));
+        }
+
+        expect_that!(domain.validate_corpus_value(&(5,)).is_err(), eq(true));
+        expect_that!(domain.validate_corpus_value(&(25,)).is_err(), eq(true));
+    }
+
+    #[gtest]
+    fn test_tuple_of_2_init_and_corpus_to_user_value() {
+        let mut domain: TupleOf2<_, _> =
+            (InRange::new(-5i32, 5), VecOf::new(InRange::new(1u8, 3)).with_len(2));
+        let mut rng = get_rng();
+
+        for _ in 0..50 {
+            let corpus_val = domain.init(&mut rng).unwrap();
+            expect_that!(corpus_val.0, all!(ge(-5), le(5)));
+            expect_that!(corpus_val.1.len(), eq(2));
+            for &elem in &corpus_val.1 {
+                expect_that!(elem, all!(ge(1), le(3)));
+            }
+
+            let user_val = domain.corpus_to_user_value(&corpus_val).unwrap();
+            expect_that!(user_val, eq(&corpus_val));
+        }
+    }
+
+    #[gtest]
+    fn test_tuple_of_mutate_mutates_one_element_per_step_and_covers_all() {
+        let mut domain: TupleOf3<_, _, _> =
+            (Arbitrary::<i32>::default(), Arbitrary::<i32>::default(), Arbitrary::<i32>::default());
+        let mut rng = get_rng();
+        let mut val = (10, 20, 30);
+
+        let mut mutated_0 = false;
+        let mut mutated_1 = false;
+        let mut mutated_2 = false;
+
+        for _ in 0..100 {
+            let prev = val;
+            domain.mutate(&mut val, &mut rng, false).unwrap();
+            let changed_0 = val.0 != prev.0;
+            let changed_1 = val.1 != prev.1;
+            let changed_2 = val.2 != prev.2;
+
+            let changed_count =
+                usize::from(changed_0) + usize::from(changed_1) + usize::from(changed_2);
+            expect_that!(
+                changed_count,
+                eq(1),
+                "Each tuple mutation step should mutate exactly one element"
+            );
+
+            mutated_0 |= changed_0;
+            mutated_1 |= changed_1;
+            mutated_2 |= changed_2;
+        }
+
+        expect_that!(mutated_0, eq(true));
+        expect_that!(mutated_1, eq(true));
+        expect_that!(mutated_2, eq(true));
+    }
+
+    #[gtest]
+    fn test_tuple_of_shrink_converges_to_target() {
+        let mut domain =
+            (Arbitrary::<i32>::default(), Arbitrary::<u8>::default(), Arbitrary::<bool>::default());
+        let mut rng = get_rng();
+        let mut val = (1000i32, 200u8, true);
+
+        for _ in 0..1000 {
+            if val == (0, 0, false) {
+                break;
+            }
+            let prev = val;
+            domain.mutate(&mut val, &mut rng, true).unwrap();
+            expect_that!(val.0.abs(), le(prev.0.abs()));
+            expect_that!(val.1, le(prev.1));
+            if !prev.2 {
+                expect_that!(val.2, eq(false));
+            }
+        }
+
+        expect_that!(val, eq((0, 0, false)));
+    }
+
+    #[gtest]
+    fn test_tuple_of_validate_corpus_value() {
+        let constrained = (
+            InRange::new(10i32, 20),
+            VecOf::new(InRange::new(1u8, 5)).with_min_len(1).with_max_len(2),
+        );
+
+        let valid_val = (15i32, vec![2u8, 4u8]);
+        expect_that!(constrained.validate_corpus_value(&valid_val).is_ok(), eq(true));
+
+        let invalid_first = (5i32, vec![2u8, 4u8]);
+        expect_that!(constrained.validate_corpus_value(&invalid_first).is_err(), eq(true));
+
+        let invalid_second_elem = (15i32, vec![2u8, 9u8]);
+        expect_that!(constrained.validate_corpus_value(&invalid_second_elem).is_err(), eq(true));
+
+        let invalid_second_len = (15i32, Vec::<u8>::new());
+        expect_that!(constrained.validate_corpus_value(&invalid_second_len).is_err(), eq(true));
+    }
+
+    #[gtest]
+    fn test_tuple_of_serde_roundtrip() {
+        let domain = (
+            InRange::new(10i32, 20),
+            VecOf::new(InRange::new(1u8, 5)).with_min_len(1).with_max_len(2),
+        );
+
+        let val = (15i32, vec![2u8, 4u8]);
+        let bytes = domain.serialize_corpus(&val).unwrap();
+        expect_that!(domain.parse_corpus(&bytes).unwrap(), eq(&val));
+    }
+
+    #[gtest]
+    fn test_tuple_of_nested() {
+        let mut domain = (
+            (InRange::new(1i32, 5), Arbitrary::<bool>::default()),
+            VecOf::new(InRange::new(10u8, 20)).with_len(2),
+        );
+        let mut rng = get_rng();
+
+        let mut val = domain.init(&mut rng).unwrap();
+        expect_that!(domain.validate_corpus_value(&val).is_ok(), eq(true));
+
+        for _ in 0..50 {
+            domain.mutate(&mut val, &mut rng, false).unwrap();
+            expect_that!(domain.validate_corpus_value(&val).is_ok(), eq(true));
+        }
+
+        let bytes = domain.serialize_corpus(&val).unwrap();
+        let parsed = domain.parse_corpus(&bytes).unwrap();
+        expect_that!(parsed, eq(&val));
+    }
+
+    #[gtest]
+    fn test_tuple_of_arities_up_to_12() {
+        let mut rng = get_rng();
+
+        let mut d4: TupleOf4<_, _, _, _> = (
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+        );
+        let mut v4 = d4.init(&mut rng).unwrap();
+        d4.mutate(&mut v4, &mut rng, false).unwrap();
+        expect_that!(d4.validate_corpus_value(&v4).is_ok(), eq(true));
+
+        let mut d5: TupleOf5<_, _, _, _, _> = (
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+        );
+        let mut v5 = d5.init(&mut rng).unwrap();
+        d5.mutate(&mut v5, &mut rng, false).unwrap();
+        expect_that!(d5.validate_corpus_value(&v5).is_ok(), eq(true));
+
+        let mut d6: TupleOf6<_, _, _, _, _, _> = (
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+        );
+        let mut v6 = d6.init(&mut rng).unwrap();
+        d6.mutate(&mut v6, &mut rng, false).unwrap();
+        expect_that!(d6.validate_corpus_value(&v6).is_ok(), eq(true));
+
+        let mut d7: TupleOf7<_, _, _, _, _, _, _> = (
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+        );
+        let mut v7 = d7.init(&mut rng).unwrap();
+        d7.mutate(&mut v7, &mut rng, false).unwrap();
+        expect_that!(d7.validate_corpus_value(&v7).is_ok(), eq(true));
+
+        let mut d8: TupleOf8<_, _, _, _, _, _, _, _> = (
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+        );
+        let mut v8 = d8.init(&mut rng).unwrap();
+        d8.mutate(&mut v8, &mut rng, false).unwrap();
+        expect_that!(d8.validate_corpus_value(&v8).is_ok(), eq(true));
+
+        let mut d9: TupleOf9<_, _, _, _, _, _, _, _, _> = (
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+        );
+        let mut v9 = d9.init(&mut rng).unwrap();
+        d9.mutate(&mut v9, &mut rng, false).unwrap();
+        expect_that!(d9.validate_corpus_value(&v9).is_ok(), eq(true));
+
+        let mut d10: TupleOf10<_, _, _, _, _, _, _, _, _, _> = (
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+        );
+        let mut v10 = d10.init(&mut rng).unwrap();
+        d10.mutate(&mut v10, &mut rng, false).unwrap();
+        expect_that!(d10.validate_corpus_value(&v10).is_ok(), eq(true));
+
+        let mut d11: TupleOf11<_, _, _, _, _, _, _, _, _, _, _> = (
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+            InRange::new(0u8, 5),
+        );
+        let mut v11 = d11.init(&mut rng).unwrap();
+        d11.mutate(&mut v11, &mut rng, false).unwrap();
+        expect_that!(d11.validate_corpus_value(&v11).is_ok(), eq(true));
+
+        let mut d12: TupleOf12<_, _, _, _, _, _, _, _, _, _, _, _> = (
+            InRange::new(1u8, 5),
+            InRange::new(1u8, 5),
+            InRange::new(1u8, 5),
+            InRange::new(1u8, 5),
+            InRange::new(1u8, 5),
+            InRange::new(1u8, 5),
+            InRange::new(1u8, 5),
+            InRange::new(1u8, 5),
+            InRange::new(1u8, 5),
+            InRange::new(1u8, 5),
+            InRange::new(1u8, 5),
+            InRange::new(1u8, 5),
+        );
+        let mut v12 = d12.init(&mut rng).unwrap();
+        for _ in 0..50 {
+            d12.mutate(&mut v12, &mut rng, false).unwrap();
+            expect_that!(d12.validate_corpus_value(&v12).is_ok(), eq(true));
+        }
+        let user_v12 = d12.corpus_to_user_value(&v12).unwrap();
+        expect_that!(user_v12, eq(v12));
+        let bytes12 = d12.serialize_corpus(&v12).unwrap();
+        expect_that!(d12.parse_corpus(&bytes12).unwrap(), eq(v12));
+
+        let mut invalid_v12 = v12;
+        invalid_v12.11 = 99;
+        expect_that!(d12.validate_corpus_value(&invalid_v12).is_err(), eq(true));
+    }
+}
diff --git a/rust/tests/macro_compiles.rs b/rust/tests/macro_compiles.rs
index 04c245e..8ab7486 100644
--- a/rust/tests/macro_compiles.rs
+++ b/rust/tests/macro_compiles.rs
@@ -15,6 +15,8 @@
 use fuzztest::domains::arbitrary::Arbitrary;
 use fuzztest::domains::containers::ContainerDomain;
 use fuzztest::domains::containers::VecOf;
+use fuzztest::domains::range::InRange;
+use fuzztest::domains::tuple_of::TupleOf2;
 use fuzztest::fuzztest;
 
 #[fuzztest(_a = Arbitrary::<i32>::default())]
@@ -26,8 +28,24 @@
 #[fuzztest(_a = VecOf::new(Arbitrary::<i32>::default()).with_max_len(10))]
 fn fuzztest_macro_compiles_with_vec(_a: Vec<i32>) {}
 
+#[fuzztest(_a = Arbitrary::<Vec<i32>>::default())]
+fn fuzztest_macro_compiles_with_arbitrary_vec(_a: Vec<i32>) {}
+
+#[fuzztest(_a = (InRange::new(0i32, 10), Arbitrary::<bool>::default()))]
+fn fuzztest_macro_compiles_with_tuple_of(_a: (i32, bool)) {}
+
+#[fuzztest(_a = TupleOf2::from((InRange::new(0i32, 10), Arbitrary::<u8>::default())))]
+fn fuzztest_macro_compiles_with_tuple_of_alias(_a: (i32, u8)) {}
+
+#[fuzztest(_a = Arbitrary::<(i32, Vec<u8>)>::default())]
+fn fuzztest_macro_compiles_with_arbitrary_tuple(_a: (i32, Vec<u8>)) {}
+
 fn main() {
     // The property function is defined in the scope where the macro is
     // invoked, so it can be called directly, e.g. from a regression test.
     fuzztest_macro_compiles(0);
+    fuzztest_macro_compiles_with_arbitrary_vec(vec![1, 2]);
+    fuzztest_macro_compiles_with_tuple_of((5, true));
+    fuzztest_macro_compiles_with_tuple_of_alias((3, 7));
+    fuzztest_macro_compiles_with_arbitrary_tuple((42, vec![1]));
 }