Skip to content

Commit

Permalink
fix arbitrary_from ergonomics by removing the implicit reference in t…
Browse files Browse the repository at this point in the history
…he trait signature
  • Loading branch information
alpaylan committed Jan 13, 2025
1 parent 1344280 commit 3c14f77
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 44 deletions.
2 changes: 1 addition & 1 deletion simulator/generation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<
Expand Down
12 changes: 5 additions & 7 deletions simulator/generation/plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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))
Expand All @@ -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)))
}),
),
(
Expand Down
8 changes: 4 additions & 4 deletions simulator/generation/property.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,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,
Expand All @@ -244,7 +244,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 {
Expand All @@ -268,7 +268,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.
Expand All @@ -293,7 +293,7 @@ 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(
Expand Down
50 changes: 25 additions & 25 deletions simulator/generation/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand All @@ -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)
Expand All @@ -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(),
Expand All @@ -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![
Expand All @@ -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![
(
Expand All @@ -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,
Expand All @@ -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];
Expand Down Expand Up @@ -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 {
Expand All @@ -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))
Expand All @@ -230,42 +230,42 @@ 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(),
)
}
})
}
}

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,
)
}),
],
Expand All @@ -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];
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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
Expand Down
12 changes: 6 additions & 6 deletions simulator/generation/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)),
Expand All @@ -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);
Expand All @@ -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))),
Expand Down Expand Up @@ -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);
Expand All @@ -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))),
Expand Down
1 change: 1 addition & 0 deletions simulator/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![allow(clippy::arc_with_non_send_sync, dead_code)]
use clap::Parser;
use generation::ArbitraryFrom;
use core::panic;
use generation::plan::{InteractionPlan, InteractionPlanState};
use limbo_core::Database;
Expand Down
2 changes: 1 addition & 1 deletion simulator/shrink/plan.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
generation::plan::{Interaction, InteractionPlan, Interactions},
generation::plan::{InteractionPlan, Interactions},
runner::execution::Execution,
};

Expand Down

0 comments on commit 3c14f77

Please sign in to comment.