From d52c7dfc81ba2e0e105d5d350af51626e8a07706 Mon Sep 17 00:00:00 2001 From: Ryan Roelke Date: Thu, 21 Mar 2024 10:48:27 -0400 Subject: [PATCH] Add proptest strategy for generating Schema for dense arrays --- tiledb/test/src/datatype.rs | 13 ++++++++-- tiledb/test/src/dimension.rs | 50 ++++++++++++++++++++++++------------ tiledb/test/src/domain.rs | 28 +++++++++++++------- tiledb/test/src/schema.rs | 3 +-- 4 files changed, 65 insertions(+), 29 deletions(-) diff --git a/tiledb/test/src/datatype.rs b/tiledb/test/src/datatype.rs index edfaaace..6f1023d3 100644 --- a/tiledb/test/src/datatype.rs +++ b/tiledb/test/src/datatype.rs @@ -49,9 +49,10 @@ pub fn arbitrary() -> impl Strategy { ] } -/// Choose an arbitrary datatype which satisifes the CAPIConverter trait +/// Choose an arbitrary datatype which is implemented +/// (satisfies CAPIConv, and has cases in fn_typed) // TODO: make sure to keep this list up to date as we add more types -pub fn arbitrary_conv() -> impl Strategy { +pub fn arbitrary_implemented() -> impl Strategy { prop_oneof![ Just(tiledb::Datatype::Int8), Just(tiledb::Datatype::Int16), @@ -65,3 +66,11 @@ pub fn arbitrary_conv() -> impl Strategy { Just(tiledb::Datatype::Float64), ] } + +pub fn arbitrary_for_dense_dimension() -> impl Strategy +{ + arbitrary_implemented().prop_filter( + "Type is not a valid dimension type for dense arrays", + |dt| dt.is_allowed_dimension_type_dense(), + ) +} diff --git a/tiledb/test/src/dimension.rs b/tiledb/test/src/dimension.rs index 0dbdb3bc..bff7f93a 100644 --- a/tiledb/test/src/dimension.rs +++ b/tiledb/test/src/dimension.rs @@ -1,10 +1,10 @@ use num_traits::{Bounded, Num}; use proptest::prelude::*; use std::fmt::Debug; -use tiledb::array::{Dimension, DimensionBuilder}; +use tiledb::array::{ArrayType, Dimension, DimensionBuilder}; use tiledb::context::Context; -use tiledb::fn_typed; use tiledb::Result as TileDBResult; +use tiledb::{fn_typed, Datatype}; use crate::strategy::LifetimeBoundStrategy; @@ -75,32 +75,50 @@ where }) } +pub fn arbitrary_for_type( + context: &Context, + datatype: Datatype, +) -> impl Strategy> { + fn_typed!(arbitrary_range_and_extent, datatype => + (crate::attribute::arbitrary_name(), arbitrary_range_and_extent).prop_map(move |(name, values)| { + DimensionBuilder::new(context, name.as_ref(), datatype, &values.0, &values.1) + .map(|b| b.build()) + }).bind()) +} + pub fn arbitrary( context: &Context, + array_type: ArrayType, ) -> impl Strategy> { - ( - crate::datatype::arbitrary_conv(), - crate::attribute::arbitrary_name(), - ) - .prop_flat_map(|(dt, name)| { - fn_typed!(arbitrary_range_and_extent, dt => - (Just(dt), Just(name), arbitrary_range_and_extent).prop_map(|(dt, name, values)| { - DimensionBuilder::new(context, name.as_ref(), dt, &values.0, &values.1) - .map(|b| b.build()) - }).bind()) - }) + match array_type { + ArrayType::Dense => { + crate::datatype::arbitrary_for_dense_dimension().boxed() + } + ArrayType::Sparse => crate::datatype::arbitrary_implemented().boxed(), + } + .prop_flat_map(|dt| arbitrary_for_type(context, dt)) } #[cfg(test)] mod tests { use super::*; - /// Test that the arbitrary dimension construction always succeeds + /// Test that the arbitrary dimension dense array construction always succeeds + #[test] + fn dimension_arbitrary_dense() { + let ctx = Context::new().expect("Error creating context"); + + proptest!(|(maybe_dimension in arbitrary(&ctx, ArrayType::Dense))| { + maybe_dimension.expect("Error constructing arbitrary dimension"); + }); + } + + /// Test that the arbitrary dimension sparse array construction always succeeds #[test] - fn dimension_arbitrary() { + fn dimension_arbitrary_sparse() { let ctx = Context::new().expect("Error creating context"); - proptest!(|(maybe_dimension in arbitrary(&ctx))| { + proptest!(|(maybe_dimension in arbitrary(&ctx, ArrayType::Sparse))| { maybe_dimension.expect("Error constructing arbitrary dimension"); }); } diff --git a/tiledb/test/src/domain.rs b/tiledb/test/src/domain.rs index ddd92ed4..9ee9f79a 100644 --- a/tiledb/test/src/domain.rs +++ b/tiledb/test/src/domain.rs @@ -13,20 +13,30 @@ pub fn arbitrary( const MAX_DIMENSIONS: usize = 8; match array_type { - ArrayType::Dense => unimplemented!(), + ArrayType::Dense => crate::datatype::arbitrary_for_dense_dimension() + .prop_flat_map(|dimension_type| { + proptest::collection::vec( + crate::dimension::arbitrary_for_type( + context, + dimension_type, + ), + MIN_DIMENSIONS..=MAX_DIMENSIONS, + ) + }) + .bind(), ArrayType::Sparse => proptest::collection::vec( - crate::dimension::arbitrary(context), + crate::dimension::arbitrary(context, array_type), MIN_DIMENSIONS..=MAX_DIMENSIONS, ) - .prop_map(|dimensions| { - let mut d = DomainBuilder::new(context)?; - for dim in dimensions { - d = d.add_dimension(dim?)?; - } - Ok(d.build()) - }) .bind(), } + .prop_map(|dimensions| { + let mut d = DomainBuilder::new(context)?; + for dim in dimensions { + d = d.add_dimension(dim?)?; + } + Ok(d.build()) + }) } #[cfg(test)] diff --git a/tiledb/test/src/schema.rs b/tiledb/test/src/schema.rs index b7d1f38e..90b7ca43 100644 --- a/tiledb/test/src/schema.rs +++ b/tiledb/test/src/schema.rs @@ -4,8 +4,7 @@ use tiledb::context::Context; use tiledb::Result as TileDBResult; pub fn arbitrary_array_type() -> impl Strategy { - // TODO: implement Domain scenario for Dense arrays - Just(ArrayType::Sparse) + prop_oneof![Just(ArrayType::Dense), Just(ArrayType::Sparse),] } pub fn arbitrary(