mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-08-04 10:08:20 +00:00
fix arbitrary_from ergonomics by removing the implicit reference in the trait signature
This commit is contained in:
parent
13442808dd
commit
43f6c34408
7 changed files with 57 additions and 59 deletions
|
@ -13,7 +13,7 @@ pub trait Arbitrary {
|
|||
}
|
||||
|
||||
pub trait ArbitraryFrom<T> {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, t: &T) -> Self;
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, t: T) -> Self;
|
||||
}
|
||||
|
||||
pub(crate) fn frequency<
|
||||
|
|
|
@ -283,10 +283,8 @@ impl InteractionPlan {
|
|||
}
|
||||
}
|
||||
|
||||
impl InteractionPlan {
|
||||
// todo: This is a hack to get around the fact that `ArbitraryFrom<T>` can't take a mutable
|
||||
// reference of T, so instead write a bespoke function without using the trait system.
|
||||
pub(crate) fn arbitrary_from<R: rand::Rng>(rng: &mut R, env: &mut SimulatorEnv) -> Self {
|
||||
impl ArbitraryFrom<&mut SimulatorEnv> for InteractionPlan {
|
||||
fn arbitrary_from<R: rand::Rng>(rng: &mut R, env: &mut SimulatorEnv) -> Self {
|
||||
let mut plan = InteractionPlan::new();
|
||||
|
||||
let num_interactions = env.opts.max_interactions;
|
||||
|
@ -304,7 +302,7 @@ impl InteractionPlan {
|
|||
plan.plan.len(),
|
||||
num_interactions
|
||||
);
|
||||
let interactions = Interactions::arbitrary_from(rng, &(env, plan.stats()));
|
||||
let interactions = Interactions::arbitrary_from(rng, (env, plan.stats()));
|
||||
interactions.shadow(env);
|
||||
|
||||
plan.plan.push(interactions);
|
||||
|
@ -471,7 +469,7 @@ fn random_fault<R: rand::Rng>(_rng: &mut R, _env: &SimulatorEnv) -> Interactions
|
|||
impl ArbitraryFrom<(&SimulatorEnv, InteractionStats)> for Interactions {
|
||||
fn arbitrary_from<R: rand::Rng>(
|
||||
rng: &mut R,
|
||||
(env, stats): &(&SimulatorEnv, InteractionStats),
|
||||
(env, stats): (&SimulatorEnv, InteractionStats),
|
||||
) -> Self {
|
||||
let remaining_read = ((env.opts.max_interactions as f64 * env.opts.read_percent / 100.0)
|
||||
- (stats.read_count as f64))
|
||||
|
@ -489,7 +487,7 @@ impl ArbitraryFrom<(&SimulatorEnv, InteractionStats)> for Interactions {
|
|||
(
|
||||
f64::min(remaining_read, remaining_write) + remaining_create,
|
||||
Box::new(|rng: &mut R| {
|
||||
Interactions::Property(Property::arbitrary_from(rng, &(env, stats)))
|
||||
Interactions::Property(Property::arbitrary_from(rng, (env, &stats)))
|
||||
}),
|
||||
),
|
||||
(
|
||||
|
|
|
@ -115,10 +115,7 @@ impl Property {
|
|||
|
||||
interactions
|
||||
}
|
||||
Property::DoubleCreateFailure {
|
||||
create,
|
||||
queries,
|
||||
} => {
|
||||
Property::DoubleCreateFailure { create, queries } => {
|
||||
let table_name = create.table.name.clone();
|
||||
|
||||
let assumption = Interaction::Assumption(Assertion {
|
||||
|
@ -186,7 +183,11 @@ fn remaining(env: &SimulatorEnv, stats: &InteractionStats) -> Remaining {
|
|||
}
|
||||
}
|
||||
|
||||
fn property_insert_select<R: rand::Rng>(rng: &mut R, env: &SimulatorEnv, remaining: &Remaining) -> Property {
|
||||
fn property_insert_select<R: rand::Rng>(
|
||||
rng: &mut R,
|
||||
env: &SimulatorEnv,
|
||||
remaining: &Remaining,
|
||||
) -> Property {
|
||||
// Get a random table
|
||||
let table = pick(&env.tables, rng);
|
||||
// Pick a random column
|
||||
|
@ -218,7 +219,7 @@ fn property_insert_select<R: rand::Rng>(rng: &mut R, env: &SimulatorEnv, remaini
|
|||
// - [ ] The inserted row will not be updated. (todo: add this constraint once UPDATE is implemented)
|
||||
// - [ ] The table `t` will not be renamed, dropped, or altered. (todo: add this constraint once ALTER or DROP is implemented)
|
||||
for _ in 0..rng.gen_range(0..3) {
|
||||
let query = Query::arbitrary_from(rng, &(table, remaining));
|
||||
let query = Query::arbitrary_from(rng, (table, remaining));
|
||||
match &query {
|
||||
Query::Delete(Delete {
|
||||
table: t,
|
||||
|
@ -244,7 +245,7 @@ fn property_insert_select<R: rand::Rng>(rng: &mut R, env: &SimulatorEnv, remaini
|
|||
// Select the row
|
||||
let select_query = Select {
|
||||
table: table.name.clone(),
|
||||
predicate: Predicate::arbitrary_from(rng, &(table, &row)),
|
||||
predicate: Predicate::arbitrary_from(rng, (table, &row)),
|
||||
};
|
||||
|
||||
Property::InsertSelect {
|
||||
|
@ -254,7 +255,11 @@ fn property_insert_select<R: rand::Rng>(rng: &mut R, env: &SimulatorEnv, remaini
|
|||
}
|
||||
}
|
||||
|
||||
fn property_double_create_failure<R: rand::Rng>(rng: &mut R, env: &SimulatorEnv, remaining: &Remaining) -> Property {
|
||||
fn property_double_create_failure<R: rand::Rng>(
|
||||
rng: &mut R,
|
||||
env: &SimulatorEnv,
|
||||
remaining: &Remaining,
|
||||
) -> Property {
|
||||
// Get a random table
|
||||
let table = pick(&env.tables, rng);
|
||||
// Create the table
|
||||
|
@ -268,7 +273,7 @@ fn property_double_create_failure<R: rand::Rng>(rng: &mut R, env: &SimulatorEnv,
|
|||
// - [x] There will be no errors in the middle interactions.(best effort)
|
||||
// - [ ] Table `t` will not be renamed or dropped.(todo: add this constraint once ALTER or DROP is implemented)
|
||||
for _ in 0..rng.gen_range(0..3) {
|
||||
let query = Query::arbitrary_from(rng, &(table, remaining));
|
||||
let query = Query::arbitrary_from(rng, (table, remaining));
|
||||
match &query {
|
||||
Query::Create(Create { table: t }) => {
|
||||
// There will be no errors in the middle interactions.
|
||||
|
@ -288,12 +293,10 @@ fn property_double_create_failure<R: rand::Rng>(rng: &mut R, env: &SimulatorEnv,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl ArbitraryFrom<(&SimulatorEnv, &InteractionStats)> for Property {
|
||||
fn arbitrary_from<R: rand::Rng>(
|
||||
rng: &mut R,
|
||||
(env, stats): &(&SimulatorEnv, &InteractionStats),
|
||||
(env, stats): (&SimulatorEnv, &InteractionStats),
|
||||
) -> Self {
|
||||
let remaining_ = remaining(env, stats);
|
||||
frequency(
|
||||
|
|
|
@ -17,7 +17,7 @@ impl Arbitrary for Create {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<Vec<Table>> for Select {
|
||||
impl ArbitraryFrom<&Vec<Table>> for Select {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, tables: &Vec<Table>) -> Self {
|
||||
let table = pick(tables, rng);
|
||||
Self {
|
||||
|
@ -27,7 +27,7 @@ impl ArbitraryFrom<Vec<Table>> for Select {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<Vec<&Table>> for Select {
|
||||
impl ArbitraryFrom<&Vec<&Table>> for Select {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, tables: &Vec<&Table>) -> Self {
|
||||
let table = pick(tables, rng);
|
||||
Self {
|
||||
|
@ -37,7 +37,7 @@ impl ArbitraryFrom<Vec<&Table>> for Select {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<Table> for Insert {
|
||||
impl ArbitraryFrom<&Table> for Insert {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, table: &Table) -> Self {
|
||||
let num_rows = rng.gen_range(1..10);
|
||||
let values: Vec<Vec<Value>> = (0..num_rows)
|
||||
|
@ -56,7 +56,7 @@ impl ArbitraryFrom<Table> for Insert {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<Table> for Delete {
|
||||
impl ArbitraryFrom<&Table> for Delete {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, table: &Table) -> Self {
|
||||
Self {
|
||||
table: table.name.clone(),
|
||||
|
@ -65,7 +65,7 @@ impl ArbitraryFrom<Table> for Delete {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<Table> for Query {
|
||||
impl ArbitraryFrom<&Table> for Query {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, table: &Table) -> Self {
|
||||
frequency(
|
||||
vec![
|
||||
|
@ -89,7 +89,7 @@ impl ArbitraryFrom<Table> for Query {
|
|||
}
|
||||
|
||||
impl ArbitraryFrom<(&Table, &Remaining)> for Query {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, (table, remaining): &(&Table, &Remaining)) -> Self {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, (table, remaining): (&Table, &Remaining)) -> Self {
|
||||
frequency(
|
||||
vec![
|
||||
(
|
||||
|
@ -98,7 +98,7 @@ impl ArbitraryFrom<(&Table, &Remaining)> for Query {
|
|||
),
|
||||
(
|
||||
remaining.read,
|
||||
Box::new(|rng| Self::Select(Select::arbitrary_from(rng, &vec![*table]))),
|
||||
Box::new(|rng| Self::Select(Select::arbitrary_from(rng, &vec![table]))),
|
||||
),
|
||||
(
|
||||
remaining.write,
|
||||
|
@ -118,7 +118,7 @@ struct CompoundPredicate(Predicate);
|
|||
struct SimplePredicate(Predicate);
|
||||
|
||||
impl ArbitraryFrom<(&Table, bool)> for SimplePredicate {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, (table, predicate_value): &(&Table, bool)) -> Self {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, (table, predicate_value): (&Table, bool)) -> Self {
|
||||
// Pick a random column
|
||||
let column_index = rng.gen_range(0..table.columns.len());
|
||||
let column = &table.columns[column_index];
|
||||
|
@ -182,15 +182,15 @@ impl ArbitraryFrom<(&Table, bool)> for SimplePredicate {
|
|||
}
|
||||
|
||||
impl ArbitraryFrom<(&Table, bool)> for CompoundPredicate {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, (table, predicate_value): &(&Table, bool)) -> Self {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, (table, predicate_value): (&Table, bool)) -> Self {
|
||||
// Decide if you want to create an AND or an OR
|
||||
Self(if rng.gen_bool(0.7) {
|
||||
// An AND for true requires each of its children to be true
|
||||
// An AND for false requires at least one of its children to be false
|
||||
if *predicate_value {
|
||||
if predicate_value {
|
||||
Predicate::And(
|
||||
(0..rng.gen_range(0..=3))
|
||||
.map(|_| SimplePredicate::arbitrary_from(rng, &(*table, true)).0)
|
||||
.map(|_| SimplePredicate::arbitrary_from(rng, (table, true)).0)
|
||||
.collect(),
|
||||
)
|
||||
} else {
|
||||
|
@ -209,14 +209,14 @@ impl ArbitraryFrom<(&Table, bool)> for CompoundPredicate {
|
|||
Predicate::And(
|
||||
booleans
|
||||
.iter()
|
||||
.map(|b| SimplePredicate::arbitrary_from(rng, &(*table, *b)).0)
|
||||
.map(|b| SimplePredicate::arbitrary_from(rng, (table, *b)).0)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// An OR for true requires at least one of its children to be true
|
||||
// An OR for false requires each of its children to be false
|
||||
if *predicate_value {
|
||||
if predicate_value {
|
||||
// Create a vector of random booleans
|
||||
let mut booleans = (0..rng.gen_range(0..=3))
|
||||
.map(|_| rng.gen_bool(0.5))
|
||||
|
@ -230,13 +230,13 @@ impl ArbitraryFrom<(&Table, bool)> for CompoundPredicate {
|
|||
Predicate::Or(
|
||||
booleans
|
||||
.iter()
|
||||
.map(|b| SimplePredicate::arbitrary_from(rng, &(*table, *b)).0)
|
||||
.map(|b| SimplePredicate::arbitrary_from(rng, (table, *b)).0)
|
||||
.collect(),
|
||||
)
|
||||
} else {
|
||||
Predicate::Or(
|
||||
(0..rng.gen_range(0..=3))
|
||||
.map(|_| SimplePredicate::arbitrary_from(rng, &(*table, false)).0)
|
||||
.map(|_| SimplePredicate::arbitrary_from(rng, (table, false)).0)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
@ -244,28 +244,28 @@ impl ArbitraryFrom<(&Table, bool)> for CompoundPredicate {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<Table> for Predicate {
|
||||
impl ArbitraryFrom<&Table> for Predicate {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, table: &Table) -> Self {
|
||||
let predicate_value = rng.gen_bool(0.5);
|
||||
CompoundPredicate::arbitrary_from(rng, &(table, predicate_value)).0
|
||||
CompoundPredicate::arbitrary_from(rng, (table, predicate_value)).0
|
||||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<(&str, &Value)> for Predicate {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, (column_name, value): &(&str, &Value)) -> Self {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, (column_name, value): (&str, &Value)) -> Self {
|
||||
one_of(
|
||||
vec![
|
||||
Box::new(|_| Predicate::Eq(column_name.to_string(), (*value).clone())),
|
||||
Box::new(|rng| {
|
||||
Self::Gt(
|
||||
column_name.to_string(),
|
||||
GTValue::arbitrary_from(rng, *value).0,
|
||||
GTValue::arbitrary_from(rng, value).0,
|
||||
)
|
||||
}),
|
||||
Box::new(|rng| {
|
||||
Self::Lt(
|
||||
column_name.to_string(),
|
||||
LTValue::arbitrary_from(rng, *value).0,
|
||||
LTValue::arbitrary_from(rng, value).0,
|
||||
)
|
||||
}),
|
||||
],
|
||||
|
@ -275,7 +275,7 @@ impl ArbitraryFrom<(&str, &Value)> for Predicate {
|
|||
}
|
||||
|
||||
/// Produces a predicate that is true for the provided row in the given table
|
||||
fn produce_true_predicate<R: Rng>(rng: &mut R, (t, row): &(&Table, &Vec<Value>)) -> Predicate {
|
||||
fn produce_true_predicate<R: Rng>(rng: &mut R, (t, row): (&Table, &Vec<Value>)) -> Predicate {
|
||||
// Pick a column
|
||||
let column_index = rng.gen_range(0..t.columns.len());
|
||||
let column = &t.columns[column_index];
|
||||
|
@ -304,7 +304,7 @@ fn produce_true_predicate<R: Rng>(rng: &mut R, (t, row): &(&Table, &Vec<Value>))
|
|||
}
|
||||
|
||||
/// Produces a predicate that is false for the provided row in the given table
|
||||
fn produce_false_predicate<R: Rng>(rng: &mut R, (t, row): &(&Table, &Vec<Value>)) -> Predicate {
|
||||
fn produce_false_predicate<R: Rng>(rng: &mut R, (t, row): (&Table, &Vec<Value>)) -> Predicate {
|
||||
// Pick a column
|
||||
let column_index = rng.gen_range(0..t.columns.len());
|
||||
let column = &t.columns[column_index];
|
||||
|
@ -333,18 +333,18 @@ fn produce_false_predicate<R: Rng>(rng: &mut R, (t, row): &(&Table, &Vec<Value>)
|
|||
}
|
||||
|
||||
impl ArbitraryFrom<(&Table, &Vec<Value>)> for Predicate {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, (t, row): &(&Table, &Vec<Value>)) -> Self {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, (t, row): (&Table, &Vec<Value>)) -> Self {
|
||||
// We want to produce a predicate that is true for the row
|
||||
// We can do this by creating several predicates that
|
||||
// are true, some that are false, combiend them in ways that correspond to the creation of a true predicate
|
||||
|
||||
// Produce some true and false predicates
|
||||
let mut true_predicates = (1..=rng.gen_range(1..=4))
|
||||
.map(|_| produce_true_predicate(rng, &(*t, row)))
|
||||
.map(|_| produce_true_predicate(rng, (t, row)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let false_predicates = (0..=rng.gen_range(0..=3))
|
||||
.map(|_| produce_false_predicate(rng, &(*t, row)))
|
||||
.map(|_| produce_false_predicate(rng, (t, row)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Start building a top level predicate from a true predicate
|
||||
|
|
|
@ -45,7 +45,7 @@ impl Arbitrary for ColumnType {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<Vec<&Value>> for Value {
|
||||
impl ArbitraryFrom<&Vec<&Value>> for Value {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, values: &Vec<&Self>) -> Self {
|
||||
if values.is_empty() {
|
||||
return Self::Null;
|
||||
|
@ -55,7 +55,7 @@ impl ArbitraryFrom<Vec<&Value>> for Value {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<ColumnType> for Value {
|
||||
impl ArbitraryFrom<&ColumnType> for Value {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, column_type: &ColumnType) -> Self {
|
||||
match column_type {
|
||||
ColumnType::Integer => Self::Integer(rng.gen_range(i64::MIN..i64::MAX)),
|
||||
|
@ -68,7 +68,7 @@ impl ArbitraryFrom<ColumnType> for Value {
|
|||
|
||||
pub(crate) struct LTValue(pub(crate) Value);
|
||||
|
||||
impl ArbitraryFrom<Vec<&Value>> for LTValue {
|
||||
impl ArbitraryFrom<&Vec<&Value>> for LTValue {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, values: &Vec<&Value>) -> Self {
|
||||
if values.is_empty() {
|
||||
return Self(Value::Null);
|
||||
|
@ -79,7 +79,7 @@ impl ArbitraryFrom<Vec<&Value>> for LTValue {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<Value> for LTValue {
|
||||
impl ArbitraryFrom<&Value> for LTValue {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, value: &Value) -> Self {
|
||||
match value {
|
||||
Value::Integer(i) => Self(Value::Integer(rng.gen_range(i64::MIN..*i - 1))),
|
||||
|
@ -128,7 +128,7 @@ impl ArbitraryFrom<Value> for LTValue {
|
|||
|
||||
pub(crate) struct GTValue(pub(crate) Value);
|
||||
|
||||
impl ArbitraryFrom<Vec<&Value>> for GTValue {
|
||||
impl ArbitraryFrom<&Vec<&Value>> for GTValue {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, values: &Vec<&Value>) -> Self {
|
||||
if values.is_empty() {
|
||||
return Self(Value::Null);
|
||||
|
@ -139,7 +139,7 @@ impl ArbitraryFrom<Vec<&Value>> for GTValue {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<Value> for GTValue {
|
||||
impl ArbitraryFrom<&Value> for GTValue {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, value: &Value) -> Self {
|
||||
match value {
|
||||
Value::Integer(i) => Self(Value::Integer(rng.gen_range(*i..i64::MAX))),
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
use clap::Parser;
|
||||
use core::panic;
|
||||
use generation::plan::{InteractionPlan, InteractionPlanState};
|
||||
use generation::ArbitraryFrom;
|
||||
use limbo_core::Database;
|
||||
use rand::prelude::*;
|
||||
use rand_chacha::ChaCha8Rng;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
generation::plan::{Interaction, InteractionPlan, Interactions},
|
||||
generation::plan::{InteractionPlan, Interactions},
|
||||
runner::execution::Execution,
|
||||
};
|
||||
|
||||
|
@ -26,13 +26,9 @@ impl InteractionPlan {
|
|||
for interaction in plan.plan.iter_mut() {
|
||||
if let Interactions::Property(p) = interaction {
|
||||
match p {
|
||||
crate::generation::property::Property::InsertSelect {
|
||||
queries,
|
||||
..
|
||||
} |
|
||||
crate::generation::property::Property::DoubleCreateFailure {
|
||||
queries,
|
||||
..
|
||||
crate::generation::property::Property::InsertSelect { queries, .. }
|
||||
| crate::generation::property::Property::DoubleCreateFailure {
|
||||
queries, ..
|
||||
} => {
|
||||
queries.clear();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue