Skip to content

Commit 6d2aee8

Browse files
skip[fuzz]: allow generation of longer arrays (#7729)
Allow the fuzzer to create longer arrays to exercise more file_io logic (e.g. zone_map partitions). Adds a new trait `ArbitraryWith` and `ArbitraryArrayConfig` to express this. ```rust /// Trait for generating arbitrary values with a caller-provided configuration. pub trait ArbitraryWith<'a, C>: Sized { /// Generate an arbitrary value using the provided configuration. fn arbitrary_with_config(u: &mut Unstructured<'a>, config: &C) -> Result<Self>; } /// Configuration for arbitrary array generation. #[derive(Clone, Debug)] pub struct ArbitraryArrayConfig { /// Fixed dtype, or `None` to generate one from [`Unstructured`]. pub dtype: Option<DType>, /// Inclusive range for the total array length. pub len: RangeInclusive<usize>, } ``` --------- Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
1 parent 573c995 commit 6d2aee8

6 files changed

Lines changed: 83 additions & 13 deletions

File tree

encodings/runend/src/arbitrary.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use vortex_array::LEGACY_SESSION;
99
use vortex_array::VortexSessionExecute;
1010
use vortex_array::arrays::PrimitiveArray;
1111
use vortex_array::arrays::arbitrary::ArbitraryArray;
12+
use vortex_array::arrays::arbitrary::ArbitraryArrayConfig;
13+
use vortex_array::arrays::arbitrary::ArbitraryWith;
1214
use vortex_array::dtype::DType;
1315
use vortex_array::dtype::Nullability;
1416
use vortex_array::dtype::PType;
@@ -46,14 +48,28 @@ impl ArbitraryRunEndArray {
4648
if num_runs == 0 {
4749
// Empty RunEndArray
4850
let ends = PrimitiveArray::from_iter(Vec::<u64>::new()).into_array();
49-
let values = ArbitraryArray::arbitrary_with(u, Some(0), dtype)?.0;
51+
let values = ArbitraryArray::arbitrary_with_config(
52+
u,
53+
&ArbitraryArrayConfig {
54+
dtype: Some(dtype.clone()),
55+
len: 0..=0,
56+
},
57+
)?
58+
.0;
5059
let runend_array = RunEnd::try_new(ends, values, &mut ctx)
5160
.vortex_expect("Empty RunEndArray creation should succeed");
5261
return Ok(ArbitraryRunEndArray(runend_array));
5362
}
5463

5564
// Generate arbitrary values for each run
56-
let values = ArbitraryArray::arbitrary_with(u, Some(num_runs), dtype)?.0;
65+
let values = ArbitraryArray::arbitrary_with_config(
66+
u,
67+
&ArbitraryArrayConfig {
68+
dtype: Some(dtype.clone()),
69+
len: num_runs..=num_runs,
70+
},
71+
)?
72+
.0;
5773

5874
// Generate strictly increasing ends
5975
// Each end must be > previous end, and first end must be >= 1

fuzz/src/array/mod.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ use vortex_array::aggregate_fn::fns::sum::sum;
4949
use vortex_array::arrays::ConstantArray;
5050
use vortex_array::arrays::PrimitiveArray;
5151
use vortex_array::arrays::arbitrary::ArbitraryArray;
52+
use vortex_array::arrays::arbitrary::ArbitraryArrayConfig;
53+
use vortex_array::arrays::arbitrary::ArbitraryWith;
5254
use vortex_array::builtins::ArrayBuiltins;
5355
use vortex_array::dtype::DType;
5456
use vortex_array::dtype::Nullability;
@@ -67,6 +69,7 @@ use vortex_error::vortex_panic;
6769
use vortex_mask::Mask;
6870
use vortex_utils::aliases::hash_set::HashSet;
6971

72+
use crate::FUZZ_ARRAY_MAX_LEN;
7073
use crate::SESSION;
7174
use crate::error::Backtrace;
7275
use crate::error::VortexFuzzError;
@@ -170,7 +173,14 @@ impl ExpectedValue {
170173

171174
impl<'a> Arbitrary<'a> for FuzzArrayAction {
172175
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
173-
let array = ArbitraryArray::arbitrary(u)?.0;
176+
let array = ArbitraryArray::arbitrary_with_config(
177+
u,
178+
&ArbitraryArrayConfig {
179+
dtype: None,
180+
len: 0..=FUZZ_ARRAY_MAX_LEN,
181+
},
182+
)?
183+
.0;
174184
let mut current_array = array.clone();
175185

176186
let mut ctx = SESSION.create_execution_ctx();

fuzz/src/file/mod.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ use arbitrary::Arbitrary;
55
use arbitrary::Unstructured;
66
use vortex_array::ArrayRef;
77
use vortex_array::arrays::arbitrary::ArbitraryArray;
8+
use vortex_array::arrays::arbitrary::ArbitraryArrayConfig;
9+
use vortex_array::arrays::arbitrary::ArbitraryWith;
810
use vortex_array::expr::Expression;
911
use vortex_array::expr::arbitrary::filter_expr;
1012
use vortex_array::expr::arbitrary::projection_expr;
1113

14+
use crate::FUZZ_ARRAY_MAX_LEN;
1215
use crate::array::CompressorStrategy;
1316

1417
#[derive(Debug)]
@@ -21,7 +24,14 @@ pub struct FuzzFileAction {
2124

2225
impl<'a> Arbitrary<'a> for FuzzFileAction {
2326
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
24-
let array = ArbitraryArray::arbitrary(u)?.0;
27+
let array = ArbitraryArray::arbitrary_with_config(
28+
u,
29+
&ArbitraryArrayConfig {
30+
dtype: None,
31+
len: 0..=FUZZ_ARRAY_MAX_LEN,
32+
},
33+
)?
34+
.0;
2535
let dtype = array.dtype().clone();
2636
Ok(FuzzFileAction {
2737
array,

fuzz/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ pub use gpu::FuzzCompressGpu;
3232
#[cfg(feature = "cuda")]
3333
pub use gpu::run_compress_gpu;
3434

35+
pub const FUZZ_ARRAY_MAX_LEN: usize = 16_384;
36+
3537
// Runtime initialization - platform-specific
3638
#[cfg(not(target_arch = "wasm32"))]
3739
mod native_runtime {

vortex-array/src/arrays/arbitrary.rs

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

44
use std::iter;
5+
use std::ops::RangeInclusive;
56
use std::sync::Arc;
67

78
use arbitrary::Arbitrary;
9+
use arbitrary::Error::IncorrectFormat;
810
use arbitrary::Result;
911
use arbitrary::Unstructured;
1012
use vortex_buffer::BitBuffer;
@@ -41,16 +43,37 @@ use crate::validity::Validity;
4143
#[derive(Clone, Debug)]
4244
pub struct ArbitraryArray(pub ArrayRef);
4345

44-
impl<'a> Arbitrary<'a> for ArbitraryArray {
45-
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
46-
let dtype = u.arbitrary()?;
47-
Self::arbitrary_with(u, None, &dtype)
48-
}
46+
/// Trait for generating arbitrary values with a caller-provided configuration.
47+
pub trait ArbitraryWith<'a, C>: Sized {
48+
/// Generate an arbitrary value using the provided configuration.
49+
fn arbitrary_with_config(u: &mut Unstructured<'a>, config: &C) -> Result<Self>;
50+
}
51+
52+
/// Configuration for arbitrary array generation.
53+
#[derive(Clone, Debug)]
54+
pub struct ArbitraryArrayConfig {
55+
/// Fixed dtype, or `None` to generate one from [`Unstructured`].
56+
pub dtype: Option<DType>,
57+
/// Inclusive range for the total array length.
58+
pub len: RangeInclusive<usize>,
4959
}
5060

51-
impl ArbitraryArray {
52-
pub fn arbitrary_with(u: &mut Unstructured, len: Option<usize>, dtype: &DType) -> Result<Self> {
53-
random_array(u, dtype, len).map(ArbitraryArray)
61+
impl<'a> ArbitraryWith<'a, ArbitraryArrayConfig> for ArbitraryArray {
62+
fn arbitrary_with_config(
63+
u: &mut Unstructured<'a>,
64+
config: &ArbitraryArrayConfig,
65+
) -> Result<Self> {
66+
if config.len.is_empty() {
67+
return Err(IncorrectFormat);
68+
}
69+
70+
let dtype = match &config.dtype {
71+
Some(dtype) => dtype.clone(),
72+
None => u.arbitrary()?,
73+
};
74+
let len = u.int_in_range(config.len.clone())?;
75+
76+
random_array(u, &dtype, Some(len)).map(ArbitraryArray)
5477
}
5578
}
5679

vortex-array/src/arrays/dict/arbitrary.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ use crate::ArrayRef;
1313
use crate::IntoArray;
1414
use crate::arrays::PrimitiveArray;
1515
use crate::arrays::arbitrary::ArbitraryArray;
16+
use crate::arrays::arbitrary::ArbitraryArrayConfig;
17+
use crate::arrays::arbitrary::ArbitraryWith;
1618
use crate::arrays::arbitrary::random_validity;
1719
use crate::dtype::DType;
1820
use crate::dtype::NativePType;
@@ -36,7 +38,14 @@ impl ArbitraryDictArray {
3638
// Generate the number of unique values (dictionary size)
3739
let values_len = u.int_in_range(1..=20)?;
3840
// Generate values array with the given dtype
39-
let values = ArbitraryArray::arbitrary_with(u, Some(values_len), dtype)?.0;
41+
let values = ArbitraryArray::arbitrary_with_config(
42+
u,
43+
&ArbitraryArrayConfig {
44+
dtype: Some(dtype.clone()),
45+
len: values_len..=values_len,
46+
},
47+
)?
48+
.0;
4049

4150
// Generate codes that index into the values
4251
let codes_len = len.unwrap_or(u.int_in_range(0..=100)?);

0 commit comments

Comments
 (0)