mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-07 10:14:21 +01:00
all Arbitrary traits need to pass a GenerationContext
This commit is contained in:
@@ -7,7 +7,7 @@ use crate::{
|
||||
backtrack, one_of, pick,
|
||||
predicate::{CompoundPredicate, SimplePredicate},
|
||||
table::{GTValue, LTValue, LikeValue},
|
||||
ArbitraryFrom, ArbitraryFromMaybe as _,
|
||||
ArbitraryFrom, ArbitraryFromMaybe as _, GenerationContext,
|
||||
},
|
||||
model::{
|
||||
query::predicate::Predicate,
|
||||
@@ -17,8 +17,9 @@ use crate::{
|
||||
|
||||
impl Predicate {
|
||||
/// Generate an [ast::Expr::Binary] [Predicate] from a column and [SimValue]
|
||||
pub fn from_column_binary<R: rand::Rng>(
|
||||
pub fn from_column_binary<R: rand::Rng, C: GenerationContext>(
|
||||
rng: &mut R,
|
||||
context: &C,
|
||||
column_name: &str,
|
||||
value: &SimValue,
|
||||
) -> Predicate {
|
||||
@@ -32,7 +33,7 @@ impl Predicate {
|
||||
)
|
||||
}),
|
||||
Box::new(|rng| {
|
||||
let gt_value = GTValue::arbitrary_from(rng, value).0;
|
||||
let gt_value = GTValue::arbitrary_from(rng, context, value).0;
|
||||
Expr::Binary(
|
||||
Box::new(Expr::Id(ast::Name::Ident(column_name.to_string()))),
|
||||
ast::Operator::Greater,
|
||||
@@ -40,7 +41,7 @@ impl Predicate {
|
||||
)
|
||||
}),
|
||||
Box::new(|rng| {
|
||||
let lt_value = LTValue::arbitrary_from(rng, value).0;
|
||||
let lt_value = LTValue::arbitrary_from(rng, context, value).0;
|
||||
Expr::Binary(
|
||||
Box::new(Expr::Id(ast::Name::Ident(column_name.to_string()))),
|
||||
ast::Operator::Less,
|
||||
@@ -54,7 +55,12 @@ impl Predicate {
|
||||
}
|
||||
|
||||
/// Produces a true [ast::Expr::Binary] [Predicate] that is true for the provided row in the given table
|
||||
pub fn true_binary<R: rand::Rng>(rng: &mut R, t: &Table, row: &[SimValue]) -> Predicate {
|
||||
pub fn true_binary<R: rand::Rng, C: GenerationContext>(
|
||||
rng: &mut R,
|
||||
context: &C,
|
||||
t: &Table,
|
||||
row: &[SimValue],
|
||||
) -> Predicate {
|
||||
// Pick a column
|
||||
let column_index = rng.random_range(0..t.columns.len());
|
||||
let mut column = t.columns[column_index].clone();
|
||||
@@ -93,7 +99,7 @@ impl Predicate {
|
||||
(
|
||||
1,
|
||||
Box::new(|rng| {
|
||||
let v = SimValue::arbitrary_from(rng, &column.column_type);
|
||||
let v = SimValue::arbitrary_from(rng, context, &column.column_type);
|
||||
if &v == value {
|
||||
None
|
||||
} else {
|
||||
@@ -111,7 +117,7 @@ impl Predicate {
|
||||
(
|
||||
1,
|
||||
Box::new(|rng| {
|
||||
let lt_value = LTValue::arbitrary_from(rng, value).0;
|
||||
let lt_value = LTValue::arbitrary_from(rng, context, value).0;
|
||||
Some(Expr::Binary(
|
||||
Box::new(ast::Expr::Qualified(
|
||||
ast::Name::new(&table_name),
|
||||
@@ -125,7 +131,7 @@ impl Predicate {
|
||||
(
|
||||
1,
|
||||
Box::new(|rng| {
|
||||
let gt_value = GTValue::arbitrary_from(rng, value).0;
|
||||
let gt_value = GTValue::arbitrary_from(rng, context, value).0;
|
||||
Some(Expr::Binary(
|
||||
Box::new(ast::Expr::Qualified(
|
||||
ast::Name::new(&table_name),
|
||||
@@ -140,7 +146,7 @@ impl Predicate {
|
||||
1,
|
||||
Box::new(|rng| {
|
||||
// TODO: generation for Like and Glob expressions should be extracted to different module
|
||||
LikeValue::arbitrary_from_maybe(rng, value).map(|like| {
|
||||
LikeValue::arbitrary_from_maybe(rng, context, value).map(|like| {
|
||||
Expr::Like {
|
||||
lhs: Box::new(ast::Expr::Qualified(
|
||||
ast::Name::new(&table_name),
|
||||
@@ -162,7 +168,12 @@ impl Predicate {
|
||||
}
|
||||
|
||||
/// Produces an [ast::Expr::Binary] [Predicate] that is false for the provided row in the given table
|
||||
pub fn false_binary<R: rand::Rng>(rng: &mut R, t: &Table, row: &[SimValue]) -> Predicate {
|
||||
pub fn false_binary<R: rand::Rng, C: GenerationContext>(
|
||||
rng: &mut R,
|
||||
context: &C,
|
||||
t: &Table,
|
||||
row: &[SimValue],
|
||||
) -> Predicate {
|
||||
// Pick a column
|
||||
let column_index = rng.random_range(0..t.columns.len());
|
||||
let mut column = t.columns[column_index].clone();
|
||||
@@ -197,7 +208,7 @@ impl Predicate {
|
||||
}),
|
||||
Box::new(|rng| {
|
||||
let v = loop {
|
||||
let v = SimValue::arbitrary_from(rng, &column.column_type);
|
||||
let v = SimValue::arbitrary_from(rng, context, &column.column_type);
|
||||
if &v != value {
|
||||
break v;
|
||||
}
|
||||
@@ -212,7 +223,7 @@ impl Predicate {
|
||||
)
|
||||
}),
|
||||
Box::new(|rng| {
|
||||
let gt_value = GTValue::arbitrary_from(rng, value).0;
|
||||
let gt_value = GTValue::arbitrary_from(rng, context, value).0;
|
||||
Expr::Binary(
|
||||
Box::new(ast::Expr::Qualified(
|
||||
ast::Name::new(&table_name),
|
||||
@@ -223,7 +234,7 @@ impl Predicate {
|
||||
)
|
||||
}),
|
||||
Box::new(|rng| {
|
||||
let lt_value = LTValue::arbitrary_from(rng, value).0;
|
||||
let lt_value = LTValue::arbitrary_from(rng, context, value).0;
|
||||
Expr::Binary(
|
||||
Box::new(ast::Expr::Qualified(
|
||||
ast::Name::new(&table_name),
|
||||
@@ -242,8 +253,9 @@ impl Predicate {
|
||||
|
||||
impl SimplePredicate {
|
||||
/// Generates a true [ast::Expr::Binary] [SimplePredicate] from a [TableContext] for a row in the table
|
||||
pub fn true_binary<R: rand::Rng, T: TableContext>(
|
||||
pub fn true_binary<R: rand::Rng, C: GenerationContext, T: TableContext>(
|
||||
rng: &mut R,
|
||||
context: &C,
|
||||
table: &T,
|
||||
row: &[SimValue],
|
||||
) -> Self {
|
||||
@@ -271,7 +283,7 @@ impl SimplePredicate {
|
||||
)
|
||||
}),
|
||||
Box::new(|rng| {
|
||||
let lt_value = LTValue::arbitrary_from(rng, column_value).0;
|
||||
let lt_value = LTValue::arbitrary_from(rng, context, column_value).0;
|
||||
Expr::Binary(
|
||||
Box::new(Expr::Qualified(
|
||||
ast::Name::new(table_name),
|
||||
@@ -282,7 +294,7 @@ impl SimplePredicate {
|
||||
)
|
||||
}),
|
||||
Box::new(|rng| {
|
||||
let gt_value = GTValue::arbitrary_from(rng, column_value).0;
|
||||
let gt_value = GTValue::arbitrary_from(rng, context, column_value).0;
|
||||
Expr::Binary(
|
||||
Box::new(Expr::Qualified(
|
||||
ast::Name::new(table_name),
|
||||
@@ -299,8 +311,9 @@ impl SimplePredicate {
|
||||
}
|
||||
|
||||
/// Generates a false [ast::Expr::Binary] [SimplePredicate] from a [TableContext] for a row in the table
|
||||
pub fn false_binary<R: rand::Rng, T: TableContext>(
|
||||
pub fn false_binary<R: rand::Rng, C: GenerationContext, T: TableContext>(
|
||||
rng: &mut R,
|
||||
context: &C,
|
||||
table: &T,
|
||||
row: &[SimValue],
|
||||
) -> Self {
|
||||
@@ -328,7 +341,7 @@ impl SimplePredicate {
|
||||
)
|
||||
}),
|
||||
Box::new(|rng| {
|
||||
let gt_value = GTValue::arbitrary_from(rng, column_value).0;
|
||||
let gt_value = GTValue::arbitrary_from(rng, context, column_value).0;
|
||||
Expr::Binary(
|
||||
Box::new(ast::Expr::Qualified(
|
||||
ast::Name::new(table_name),
|
||||
@@ -339,7 +352,7 @@ impl SimplePredicate {
|
||||
)
|
||||
}),
|
||||
Box::new(|rng| {
|
||||
let lt_value = LTValue::arbitrary_from(rng, column_value).0;
|
||||
let lt_value = LTValue::arbitrary_from(rng, context, column_value).0;
|
||||
Expr::Binary(
|
||||
Box::new(ast::Expr::Qualified(
|
||||
ast::Name::new(table_name),
|
||||
@@ -360,8 +373,9 @@ impl CompoundPredicate {
|
||||
/// Decide if you want to create an AND or an OR
|
||||
///
|
||||
/// Creates a Compound Predicate that is TRUE or FALSE for at least a single row
|
||||
pub fn from_table_binary<R: rand::Rng, T: TableContext>(
|
||||
pub fn from_table_binary<R: rand::Rng, C: GenerationContext, T: TableContext>(
|
||||
rng: &mut R,
|
||||
context: &C,
|
||||
table: &T,
|
||||
predicate_value: bool,
|
||||
) -> Self {
|
||||
@@ -381,7 +395,7 @@ impl CompoundPredicate {
|
||||
// An AND for false requires at least one of its children to be false
|
||||
if predicate_value {
|
||||
(0..rng.random_range(1..=3))
|
||||
.map(|_| SimplePredicate::arbitrary_from(rng, (table, row, true)).0)
|
||||
.map(|_| SimplePredicate::arbitrary_from(rng, context, (table, row, true)).0)
|
||||
.reduce(|accum, curr| {
|
||||
Predicate(Expr::Binary(
|
||||
Box::new(accum.0),
|
||||
@@ -405,7 +419,7 @@ impl CompoundPredicate {
|
||||
|
||||
booleans
|
||||
.iter()
|
||||
.map(|b| SimplePredicate::arbitrary_from(rng, (table, row, *b)).0)
|
||||
.map(|b| SimplePredicate::arbitrary_from(rng, context, (table, row, *b)).0)
|
||||
.reduce(|accum, curr| {
|
||||
Predicate(Expr::Binary(
|
||||
Box::new(accum.0),
|
||||
@@ -431,7 +445,7 @@ impl CompoundPredicate {
|
||||
|
||||
booleans
|
||||
.iter()
|
||||
.map(|b| SimplePredicate::arbitrary_from(rng, (table, row, *b)).0)
|
||||
.map(|b| SimplePredicate::arbitrary_from(rng, context, (table, row, *b)).0)
|
||||
.reduce(|accum, curr| {
|
||||
Predicate(Expr::Binary(
|
||||
Box::new(accum.0),
|
||||
@@ -442,7 +456,7 @@ impl CompoundPredicate {
|
||||
.unwrap_or(Predicate::true_())
|
||||
} else {
|
||||
(0..rng.random_range(1..=3))
|
||||
.map(|_| SimplePredicate::arbitrary_from(rng, (table, row, false)).0)
|
||||
.map(|_| SimplePredicate::arbitrary_from(rng, context, (table, row, false)).0)
|
||||
.reduce(|accum, curr| {
|
||||
Predicate(Expr::Binary(
|
||||
Box::new(accum.0),
|
||||
@@ -463,7 +477,9 @@ mod tests {
|
||||
use rand_chacha::ChaCha8Rng;
|
||||
|
||||
use crate::{
|
||||
generation::{pick, predicate::SimplePredicate, Arbitrary, ArbitraryFrom as _},
|
||||
generation::{
|
||||
pick, predicate::SimplePredicate, tests::TestContext, Arbitrary, ArbitraryFrom as _,
|
||||
},
|
||||
model::{
|
||||
query::predicate::{expr_to_value, Predicate},
|
||||
table::{SimValue, Table},
|
||||
@@ -481,20 +497,22 @@ mod tests {
|
||||
fn fuzz_true_binary_predicate() {
|
||||
let seed = get_seed();
|
||||
let mut rng = ChaCha8Rng::seed_from_u64(seed);
|
||||
let context = &TestContext::default();
|
||||
|
||||
for _ in 0..10000 {
|
||||
let table = Table::arbitrary(&mut rng);
|
||||
let table = Table::arbitrary(&mut rng, context);
|
||||
let num_rows = rng.random_range(1..10);
|
||||
let values: Vec<Vec<SimValue>> = (0..num_rows)
|
||||
.map(|_| {
|
||||
table
|
||||
.columns
|
||||
.iter()
|
||||
.map(|c| SimValue::arbitrary_from(&mut rng, &c.column_type))
|
||||
.map(|c| SimValue::arbitrary_from(&mut rng, context, &c.column_type))
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
let row = pick(&values, &mut rng);
|
||||
let predicate = Predicate::true_binary(&mut rng, &table, row);
|
||||
let predicate = Predicate::true_binary(&mut rng, context, &table, row);
|
||||
let value = expr_to_value(&predicate.0, row, &table);
|
||||
assert!(
|
||||
value.as_ref().is_some_and(|value| value.as_bool()),
|
||||
@@ -507,20 +525,22 @@ mod tests {
|
||||
fn fuzz_false_binary_predicate() {
|
||||
let seed = get_seed();
|
||||
let mut rng = ChaCha8Rng::seed_from_u64(seed);
|
||||
let context = &TestContext::default();
|
||||
|
||||
for _ in 0..10000 {
|
||||
let table = Table::arbitrary(&mut rng);
|
||||
let table = Table::arbitrary(&mut rng, context);
|
||||
let num_rows = rng.random_range(1..10);
|
||||
let values: Vec<Vec<SimValue>> = (0..num_rows)
|
||||
.map(|_| {
|
||||
table
|
||||
.columns
|
||||
.iter()
|
||||
.map(|c| SimValue::arbitrary_from(&mut rng, &c.column_type))
|
||||
.map(|c| SimValue::arbitrary_from(&mut rng, context, &c.column_type))
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
let row = pick(&values, &mut rng);
|
||||
let predicate = Predicate::false_binary(&mut rng, &table, row);
|
||||
let predicate = Predicate::false_binary(&mut rng, context, &table, row);
|
||||
let value = expr_to_value(&predicate.0, row, &table);
|
||||
assert!(
|
||||
!value.as_ref().is_some_and(|value| value.as_bool()),
|
||||
@@ -533,21 +553,23 @@ mod tests {
|
||||
fn fuzz_true_binary_simple_predicate() {
|
||||
let seed = get_seed();
|
||||
let mut rng = ChaCha8Rng::seed_from_u64(seed);
|
||||
let context = &TestContext::default();
|
||||
|
||||
for _ in 0..10000 {
|
||||
let mut table = Table::arbitrary(&mut rng);
|
||||
let mut table = Table::arbitrary(&mut rng, context);
|
||||
let num_rows = rng.random_range(1..10);
|
||||
let values: Vec<Vec<SimValue>> = (0..num_rows)
|
||||
.map(|_| {
|
||||
table
|
||||
.columns
|
||||
.iter()
|
||||
.map(|c| SimValue::arbitrary_from(&mut rng, &c.column_type))
|
||||
.map(|c| SimValue::arbitrary_from(&mut rng, context, &c.column_type))
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
table.rows.extend(values.clone());
|
||||
let row = pick(&table.rows, &mut rng);
|
||||
let predicate = SimplePredicate::true_binary(&mut rng, &table, row);
|
||||
let predicate = SimplePredicate::true_binary(&mut rng, context, &table, row);
|
||||
let result = values
|
||||
.iter()
|
||||
.map(|row| predicate.0.test(row, &table))
|
||||
@@ -561,21 +583,23 @@ mod tests {
|
||||
fn fuzz_false_binary_simple_predicate() {
|
||||
let seed = get_seed();
|
||||
let mut rng = ChaCha8Rng::seed_from_u64(seed);
|
||||
let context = &TestContext::default();
|
||||
|
||||
for _ in 0..10000 {
|
||||
let mut table = Table::arbitrary(&mut rng);
|
||||
let mut table = Table::arbitrary(&mut rng, context);
|
||||
let num_rows = rng.random_range(1..10);
|
||||
let values: Vec<Vec<SimValue>> = (0..num_rows)
|
||||
.map(|_| {
|
||||
table
|
||||
.columns
|
||||
.iter()
|
||||
.map(|c| SimValue::arbitrary_from(&mut rng, &c.column_type))
|
||||
.map(|c| SimValue::arbitrary_from(&mut rng, context, &c.column_type))
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
table.rows.extend(values.clone());
|
||||
let row = pick(&table.rows, &mut rng);
|
||||
let predicate = SimplePredicate::false_binary(&mut rng, &table, row);
|
||||
let predicate = SimplePredicate::false_binary(&mut rng, context, &table, row);
|
||||
let result = values
|
||||
.iter()
|
||||
.map(|row| predicate.0.test(row, &table))
|
||||
|
||||
Reference in New Issue
Block a user