From faf38fe1960fe10ef2d40deccbf5781a12e0f9cc Mon Sep 17 00:00:00 2001 From: pedrocarlo Date: Mon, 15 Sep 2025 19:23:00 -0300 Subject: [PATCH] add connection Index to interaction struct --- simulator/generation/plan.rs | 170 +++++++++++++------------ simulator/generation/property.rs | 212 +++++++++++++++++++------------ simulator/runner/differential.rs | 22 ++-- simulator/runner/execution.rs | 21 +-- simulator/shrink/plan.rs | 12 +- 5 files changed, 252 insertions(+), 185 deletions(-) diff --git a/simulator/generation/plan.rs b/simulator/generation/plan.rs index d6ac09155..6079b4a84 100644 --- a/simulator/generation/plan.rs +++ b/simulator/generation/plan.rs @@ -143,37 +143,26 @@ pub enum InteractionsType { Fault(Fault), } -impl Shadow for InteractionsType { +impl Shadow for Interactions { type Result = (); fn shadow(&self, tables: &mut SimulatorTables) { - match self { - Self::Property(property) => { + match &self.interactions { + InteractionsType::Property(property) => { let initial_tables = tables.clone(); - let mut is_error = false; - for interaction in property.interactions() { - match interaction { - Interaction::Query(query) | Interaction::FsyncQuery(query) => { - if query.shadow(tables).is_err() { - is_error = true; - } - } - Interaction::FaultyQuery(..) => {} - Interaction::Assertion(_) => {} - Interaction::Assumption(_) => {} - Interaction::Fault(_) => {} - } - if is_error { + for interaction in property.interactions(self.connection_index) { + let res = interaction.shadow(tables); + if res.is_err() { // If any interaction fails, we reset the tables to the initial state *tables = initial_tables.clone(); break; } } } - Self::Query(query) => { + InteractionsType::Query(query) => { let _ = query.shadow(tables); } - Self::Fault(_) => {} + InteractionsType::Fault(_) => {} } } } @@ -189,26 +178,30 @@ impl Interactions { pub(crate) fn interactions(&self) -> Vec { match &self.interactions { - InteractionsType::Property(property) => property.interactions(), - InteractionsType::Query(query) => vec![Interaction::Query(query.clone())], - InteractionsType::Fault(fault) => vec![Interaction::Fault(fault.clone())], + InteractionsType::Property(property) => property.interactions(self.connection_index), + InteractionsType::Query(query) => vec![Interaction::new( + self.connection_index, + InteractionType::Query(query.clone()), + )], + InteractionsType::Fault(fault) => vec![Interaction::new( + self.connection_index, + InteractionType::Fault(fault.clone()), + )], } } pub(crate) fn dependencies(&self) -> IndexSet { match &self.interactions { - InteractionsType::Property(property) => { - property - .interactions() - .iter() - .fold(IndexSet::new(), |mut acc, i| match i { - Interaction::Query(q) => { - acc.extend(q.dependencies()); - acc - } - _ => acc, - }) - } + InteractionsType::Property(property) => property + .interactions(self.connection_index) + .iter() + .fold(IndexSet::new(), |mut acc, i| match &i.interaction { + InteractionType::Query(q) => { + acc.extend(q.dependencies()); + acc + } + _ => acc, + }), InteractionsType::Query(query) => query.dependencies(), InteractionsType::Fault(_) => IndexSet::new(), } @@ -216,18 +209,16 @@ impl Interactions { pub(crate) fn uses(&self) -> Vec { match &self.interactions { - InteractionsType::Property(property) => { - property - .interactions() - .iter() - .fold(vec![], |mut acc, i| match i { - Interaction::Query(q) => { - acc.extend(q.uses()); - acc - } - _ => acc, - }) - } + InteractionsType::Property(property) => property + .interactions(self.connection_index) + .iter() + .fold(vec![], |mut acc, i| match &i.interaction { + InteractionType::Query(q) => { + acc.extend(q.uses()); + acc + } + _ => acc, + }), InteractionsType::Query(query) => query.uses(), InteractionsType::Fault(_) => vec![], } @@ -242,27 +233,8 @@ impl Display for InteractionPlan { InteractionsType::Property(property) => { let name = property.name(); writeln!(f, "-- begin testing '{name}'")?; - for interaction in property.interactions() { - write!(f, "\t")?; - - match interaction { - Interaction::Query(query) => writeln!(f, "{query};")?, - Interaction::Assumption(assumption) => { - writeln!(f, "-- ASSUME {};", assumption.name)? - } - Interaction::Assertion(assertion) => { - writeln!(f, "-- ASSERT {};", assertion.name)? - } - Interaction::Fault(fault) => writeln!(f, "-- FAULT '{fault}';")?, - Interaction::FsyncQuery(query) => { - writeln!(f, "-- FSYNC QUERY;")?; - writeln!(f, "{query};")?; - writeln!(f, "{query};")? - } - Interaction::FaultyQuery(query) => { - writeln!(f, "{query}; -- FAULTY QUERY")? - } - } + for interaction in property.interactions(interactions.connection_index) { + writeln!(f, "\t{}", interaction)?; } writeln!(f, "-- end testing '{name}'")?; } @@ -355,7 +327,7 @@ impl Assertion { } } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] pub(crate) enum Fault { Disconnect, ReopenDatabase, @@ -406,8 +378,8 @@ impl InteractionPlan { for interactions in &self.plan { match &interactions.interactions { InteractionsType::Property(property) => { - for interaction in &property.interactions() { - if let Interaction::Query(query) = interaction { + for interaction in &property.interactions(interactions.connection_index) { + if let InteractionType::Query(query) = &interaction.interaction { query_stat(query, &mut stats); } } @@ -453,8 +425,37 @@ impl InteractionPlan { } } -#[derive(Debug)] -pub(crate) enum Interaction { +#[derive(Debug, Clone)] +pub struct Interaction { + pub connection_index: usize, + pub interaction: InteractionType, +} + +impl Deref for Interaction { + type Target = InteractionType; + + fn deref(&self) -> &Self::Target { + &self.interaction + } +} + +impl DerefMut for Interaction { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.interaction + } +} + +impl Interaction { + pub fn new(connection_index: usize, interaction: InteractionType) -> Self { + Self { + connection_index, + interaction, + } + } +} + +#[derive(Debug, Clone)] +pub enum InteractionType { Query(Query), Assumption(Assertion), Assertion(Assertion), @@ -465,20 +466,33 @@ pub(crate) enum Interaction { FaultyQuery(Query), } +// FIXME: add the connection index here later impl Display for Interaction { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.interaction) + } +} + +impl Display for InteractionType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Query(query) => write!(f, "{query}"), - Self::Assumption(assumption) => write!(f, "ASSUME {}", assumption.name), - Self::Assertion(assertion) => write!(f, "ASSERT {}", assertion.name), - Self::Fault(fault) => write!(f, "FAULT '{fault}'"), - Self::FsyncQuery(query) => write!(f, "{query}"), + Self::Assumption(assumption) => write!(f, "-- ASSUME {};", assumption.name), + Self::Assertion(assertion) => { + write!(f, "-- ASSERT {};", assertion.name) + } + Self::Fault(fault) => write!(f, "-- FAULT '{fault}';"), + Self::FsyncQuery(query) => { + writeln!(f, "-- FSYNC QUERY;")?; + writeln!(f, "{query};")?; + write!(f, "{query};") + } Self::FaultyQuery(query) => write!(f, "{query}; -- FAULTY QUERY"), } } } -impl Shadow for Interaction { +impl Shadow for InteractionType { type Result = anyhow::Result>>; fn shadow(&self, env: &mut SimulatorTables) -> Self::Result { match self { @@ -494,7 +508,7 @@ impl Shadow for Interaction { } } } -impl Interaction { +impl InteractionType { pub(crate) fn execute_query(&self, conn: &mut Arc) -> ResultSet { if let Self::Query(query) = self { let query_str = query.to_string(); diff --git a/simulator/generation/property.rs b/simulator/generation/property.rs index 1b07992d7..4dd877bb5 100644 --- a/simulator/generation/property.rs +++ b/simulator/generation/property.rs @@ -16,7 +16,10 @@ use turso_core::{LimboError, types}; use turso_parser::ast::{self, Distinctness}; use crate::{ - generation::Shadow as _, model::Query, profiles::query::QueryProfile, runner::env::SimulatorEnv, + generation::{Shadow as _, plan::InteractionType}, + model::Query, + profiles::query::QueryProfile, + runner::env::SimulatorEnv, }; use super::plan::{Assertion, Interaction, InteractionStats, ResultSet}; @@ -215,12 +218,12 @@ impl Property { /// interactions construct a list of interactions, which is an executable representation of the property. /// the requirement of property -> vec conversion emerges from the need to serialize the property, /// and `interaction` cannot be serialized directly. - pub(crate) fn interactions(&self) -> Vec { + pub(crate) fn interactions(&self, connection_index: usize) -> Vec { match self { Property::TableHasExpectedContent { table } => { let table = table.to_string(); let table_name = table.clone(); - let assumption = Interaction::Assumption(Assertion::new( + let assumption = InteractionType::Assumption(Assertion::new( format!("table {} exists", table.clone()), move |_: &Vec, env: &mut SimulatorEnv| { if env.tables.iter().any(|t| t.name == table_name) { @@ -231,12 +234,12 @@ impl Property { }, )); - let select_interaction = Interaction::Query(Query::Select(Select::simple( + let select_interaction = InteractionType::Query(Query::Select(Select::simple( table.clone(), Predicate::true_(), ))); - let assertion = Interaction::Assertion(Assertion::new( + let assertion = InteractionType::Assertion(Assertion::new( format!("table {} should have the expected content", table.clone()), move |stack: &Vec, env| { let rows = stack.last().unwrap(); @@ -269,11 +272,15 @@ impl Property { }, )); - vec![assumption, select_interaction, assertion] + vec![ + Interaction::new(connection_index, assumption), + Interaction::new(connection_index, select_interaction), + Interaction::new(connection_index, assertion), + ] } Property::ReadYourUpdatesBack { update, select } => { let table = update.table().to_string(); - let assumption = Interaction::Assumption(Assertion::new( + let assumption = InteractionType::Assumption(Assertion::new( format!("table {} exists", table.clone()), move |_: &Vec, env: &mut SimulatorEnv| { if env.tables.iter().any(|t| t.name == table.clone()) { @@ -284,14 +291,14 @@ impl Property { }, )); - let update_interaction = Interaction::Query(Query::Update(update.clone())); - let select_interaction = Interaction::Query(Query::Select(select.clone())); + let update_interaction = InteractionType::Query(Query::Update(update.clone())); + let select_interaction = InteractionType::Query(Query::Select(select.clone())); let update = update.clone(); let table = update.table().to_string(); - let assertion = Interaction::Assertion(Assertion::new( + let assertion = InteractionType::Assertion(Assertion::new( format!( "updated rows should be found and have the updated values for table {}", table.clone() @@ -318,10 +325,10 @@ impl Property { )); vec![ - assumption, - update_interaction, - select_interaction, - assertion, + Interaction::new(connection_index, assumption), + Interaction::new(connection_index, update_interaction), + Interaction::new(connection_index, select_interaction), + Interaction::new(connection_index, assertion), ] } Property::InsertValuesSelect { @@ -348,7 +355,7 @@ impl Property { let row = values[*row_index].clone(); // Assume that the table exists - let assumption = Interaction::Assumption(Assertion::new( + let assumption = InteractionType::Assumption(Assertion::new( format!("table {} exists", insert.table()), { let table_name = table.clone(); @@ -362,7 +369,7 @@ impl Property { }, )); - let assertion = Interaction::Assertion(Assertion::new( + let assertion = InteractionType::Assertion(Assertion::new( format!( "row [{:?}] should be found in table {}, interactive={} commit={}, rollback={}", row.iter().map(|v| v.to_string()).collect::>(), @@ -397,18 +404,29 @@ impl Property { )); let mut interactions = Vec::new(); - interactions.push(assumption); - interactions.push(Interaction::Query(Query::Insert(insert.clone()))); - interactions.extend(queries.clone().into_iter().map(Interaction::Query)); - interactions.push(Interaction::Query(Query::Select(select.clone()))); - interactions.push(assertion); + interactions.push(Interaction::new(connection_index, assumption)); + interactions.push(Interaction::new( + connection_index, + InteractionType::Query(Query::Insert(insert.clone())), + )); + interactions.extend( + queries + .clone() + .into_iter() + .map(|q| Interaction::new(connection_index, InteractionType::Query(q))), + ); + interactions.push(Interaction::new( + connection_index, + InteractionType::Query(Query::Select(select.clone())), + )); + interactions.push(Interaction::new(connection_index, assertion)); interactions } Property::DoubleCreateFailure { create, queries } => { let table_name = create.table.name.clone(); - let assumption = Interaction::Assumption(Assertion::new( + let assumption = InteractionType::Assumption(Assertion::new( "Double-Create-Failure should not be called on an existing table".to_string(), move |_: &Vec, env: &mut SimulatorEnv| { if !env.tables.iter().any(|t| t.name == table_name) { @@ -419,12 +437,12 @@ impl Property { }, )); - let cq1 = Interaction::Query(Query::Create(create.clone())); - let cq2 = Interaction::Query(Query::Create(create.clone())); + let cq1 = InteractionType::Query(Query::Create(create.clone())); + let cq2 = InteractionType::Query(Query::Create(create.clone())); let table_name = create.table.name.clone(); - let assertion = Interaction::Assertion(Assertion::new("creating two tables with the name should result in a failure for the second query" + let assertion = InteractionType::Assertion(Assertion::new("creating two tables with the name should result in a failure for the second query" .to_string(), move |stack: &Vec, _| { let last = stack.last().unwrap(); match last { @@ -440,16 +458,21 @@ impl Property { }) ); let mut interactions = Vec::new(); - interactions.push(assumption); - interactions.push(cq1); - interactions.extend(queries.clone().into_iter().map(Interaction::Query)); - interactions.push(cq2); - interactions.push(assertion); + interactions.push(Interaction::new(connection_index, assumption)); + interactions.push(Interaction::new(connection_index, cq1)); + interactions.extend( + queries + .clone() + .into_iter() + .map(|q| Interaction::new(connection_index, InteractionType::Query(q))), + ); + interactions.push(Interaction::new(connection_index, cq2)); + interactions.push(Interaction::new(connection_index, assertion)); interactions } Property::SelectLimit { select } => { - let assumption = Interaction::Assumption(Assertion::new( + let assumption = InteractionType::Assumption(Assertion::new( format!( "table ({}) exists", select @@ -481,7 +504,7 @@ impl Property { .limit .expect("Property::SelectLimit without a LIMIT clause"); - let assertion = Interaction::Assertion(Assertion::new( + let assertion = InteractionType::Assertion(Assertion::new( "select query should respect the limit clause".to_string(), move |stack: &Vec, _| { let last = stack.last().unwrap(); @@ -503,9 +526,12 @@ impl Property { )); vec![ - assumption, - Interaction::Query(Query::Select(select.clone())), - assertion, + Interaction::new(connection_index, assumption), + Interaction::new( + connection_index, + InteractionType::Query(Query::Select(select.clone())), + ), + Interaction::new(connection_index, assertion), ] } Property::DeleteSelect { @@ -513,7 +539,7 @@ impl Property { predicate, queries, } => { - let assumption = Interaction::Assumption(Assertion::new( + let assumption = InteractionType::Assumption(Assertion::new( format!("table {table} exists"), { let table = table.clone(); @@ -533,17 +559,17 @@ impl Property { }, )); - let delete = Interaction::Query(Query::Delete(Delete { + let delete = InteractionType::Query(Query::Delete(Delete { table: table.clone(), predicate: predicate.clone(), })); - let select = Interaction::Query(Query::Select(Select::simple( + let select = InteractionType::Query(Query::Select(Select::simple( table.clone(), predicate.clone(), ))); - let assertion = Interaction::Assertion(Assertion::new( + let assertion = InteractionType::Assertion(Assertion::new( format!("`{select}` should return no values for table `{table}`",), move |stack: &Vec, _| { let rows = stack.last().unwrap(); @@ -568,11 +594,16 @@ impl Property { )); let mut interactions = Vec::new(); - interactions.push(assumption); - interactions.push(delete); - interactions.extend(queries.clone().into_iter().map(Interaction::Query)); - interactions.push(select); - interactions.push(assertion); + interactions.push(Interaction::new(connection_index, assumption)); + interactions.push(Interaction::new(connection_index, delete)); + interactions.extend( + queries + .clone() + .into_iter() + .map(|q| Interaction::new(connection_index, InteractionType::Query(q))), + ); + interactions.push(Interaction::new(connection_index, select)); + interactions.push(Interaction::new(connection_index, assertion)); interactions } @@ -581,7 +612,7 @@ impl Property { queries, select, } => { - let assumption = Interaction::Assumption(Assertion::new( + let assumption = InteractionType::Assumption(Assertion::new( format!("table {table} exists"), { let table = table.clone(); @@ -603,7 +634,7 @@ impl Property { let table_name = table.clone(); - let assertion = Interaction::Assertion(Assertion::new( + let assertion = InteractionType::Assertion(Assertion::new( format!("select query should result in an error for table '{table}'"), move |stack: &Vec, _| { let last = stack.last().unwrap(); @@ -626,24 +657,29 @@ impl Property { }, )); - let drop = Interaction::Query(Query::Drop(Drop { + let drop = InteractionType::Query(Query::Drop(Drop { table: table.clone(), })); - let select = Interaction::Query(Query::Select(select.clone())); + let select = InteractionType::Query(Query::Select(select.clone())); let mut interactions = Vec::new(); - interactions.push(assumption); - interactions.push(drop); - interactions.extend(queries.clone().into_iter().map(Interaction::Query)); - interactions.push(select); - interactions.push(assertion); + interactions.push(Interaction::new(connection_index, assumption)); + interactions.push(Interaction::new(connection_index, drop)); + interactions.extend( + queries + .clone() + .into_iter() + .map(|q| Interaction::new(connection_index, InteractionType::Query(q))), + ); + interactions.push(Interaction::new(connection_index, select)); + interactions.push(Interaction::new(connection_index, assertion)); interactions } Property::SelectSelectOptimizer { table, predicate } => { - let assumption = Interaction::Assumption(Assertion::new( + let assumption = InteractionType::Assumption(Assertion::new( format!("table {table} exists"), { let table = table.clone(); @@ -663,7 +699,7 @@ impl Property { }, )); - let select1 = Interaction::Query(Query::Select(Select::single( + let select1 = InteractionType::Query(Query::Select(Select::single( table.clone(), vec![ResultColumn::Expr(predicate.clone())], Predicate::true_(), @@ -673,9 +709,9 @@ impl Property { let select2_query = Query::Select(Select::simple(table.clone(), predicate.clone())); - let select2 = Interaction::Query(select2_query); + let select2 = InteractionType::Query(select2_query); - let assertion = Interaction::Assertion(Assertion::new( + let assertion = InteractionType::Assertion(Assertion::new( "select queries should return the same amount of results".to_string(), move |stack: &Vec, _| { let select_star = stack.last().unwrap(); @@ -723,16 +759,25 @@ impl Property { }, )); - vec![assumption, select1, select2, assertion] + vec![ + Interaction::new(connection_index, assumption), + Interaction::new(connection_index, select1), + Interaction::new(connection_index, select2), + Interaction::new(connection_index, assertion), + ] } Property::FsyncNoWait { query, tables } => { - let checks = assert_all_table_values(tables); + let checks = assert_all_table_values(tables, connection_index); Vec::from_iter( - std::iter::once(Interaction::FsyncQuery(query.clone())).chain(checks), + std::iter::once(Interaction::new( + connection_index, + InteractionType::FsyncQuery(query.clone()), + )) + .chain(checks), ) } Property::FaultyQuery { query, tables } => { - let checks = assert_all_table_values(tables); + let checks = assert_all_table_values(tables, connection_index); let query_clone = query.clone(); // A fault may not occur as we first signal we want a fault injected, // then when IO is called the fault triggers. It may happen that a fault is injected @@ -756,14 +801,15 @@ impl Property { }, ); let first = [ - Interaction::FaultyQuery(query.clone()), - Interaction::Assertion(assert), + InteractionType::FaultyQuery(query.clone()), + InteractionType::Assertion(assert), ] - .into_iter(); + .into_iter() + .map(|i| Interaction::new(connection_index, i)); Vec::from_iter(first.chain(checks)) } Property::WhereTrueFalseNull { select, predicate } => { - let assumption = Interaction::Assumption(Assertion::new( + let assumption = InteractionType::Assumption(Assertion::new( format!( "tables ({}) exists", select @@ -838,11 +884,11 @@ impl Property { limit: None, }; - let select = Interaction::Query(Query::Select(select.clone())); - let select_tlp = Interaction::Query(Query::Select(select_tlp)); + let select = InteractionType::Query(Query::Select(select.clone())); + let select_tlp = InteractionType::Query(Query::Select(select_tlp)); // select and select_tlp should return the same rows - let assertion = Interaction::Assertion(Assertion::new( + let assertion = InteractionType::Assertion(Assertion::new( "select and select_tlp should return the same rows".to_string(), move |stack: &Vec, _: &mut SimulatorEnv| { if stack.len() < 2 { @@ -912,7 +958,12 @@ impl Property { }, )); - vec![assumption, select, select_tlp, assertion] + vec![ + Interaction::new(connection_index, assumption), + Interaction::new(connection_index, select), + Interaction::new(connection_index, select_tlp), + Interaction::new(connection_index, assertion), + ] } Property::UNIONAllPreservesCardinality { select, @@ -924,10 +975,10 @@ impl Property { let s3 = Select::compound(s1.clone(), s2.clone(), CompoundOperator::UnionAll); vec![ - Interaction::Query(Query::Select(s1.clone())), - Interaction::Query(Query::Select(s2.clone())), - Interaction::Query(Query::Select(s3.clone())), - Interaction::Assertion(Assertion::new( + InteractionType::Query(Query::Select(s1.clone())), + InteractionType::Query(Query::Select(s2.clone())), + InteractionType::Query(Query::Select(s3.clone())), + InteractionType::Assertion(Assertion::new( "UNION ALL should preserve cardinality".to_string(), move |stack: &Vec, _: &mut SimulatorEnv| { if stack.len() < 3 { @@ -960,20 +1011,23 @@ impl Property { } }, )), - ] + ].into_iter().map(|i| Interaction::new(connection_index, i)).collect() } } } } -fn assert_all_table_values(tables: &[String]) -> impl Iterator + use<'_> { - tables.iter().flat_map(|table| { - let select = Interaction::Query(Query::Select(Select::simple( +fn assert_all_table_values( + tables: &[String], + connection_index: usize, +) -> impl Iterator + use<'_> { + tables.iter().flat_map(move |table| { + let select = InteractionType::Query(Query::Select(Select::simple( table.clone(), Predicate::true_(), ))); - let assertion = Interaction::Assertion(Assertion::new(format!("table {table} should contain all of its expected values"), { + let assertion = InteractionType::Assertion(Assertion::new(format!("table {table} should contain all of its expected values"), { let table = table.clone(); move |stack: &Vec, env: &mut SimulatorEnv| { let table = env.tables.iter().find(|t| t.name == table).ok_or_else(|| { @@ -1017,7 +1071,7 @@ fn assert_all_table_values(tables: &[String]) -> impl Iterator { + match &interaction.interaction { + InteractionType::Query(query) => { let conn = match &mut env.connections[connection_index] { SimConnection::SQLiteConnection(conn) => conn, SimConnection::LimboConnection(_) => unreachable!(), @@ -409,14 +405,14 @@ fn execute_interaction_rusqlite( tracing::debug!("{:?}", results); stack.push(results); } - Interaction::FsyncQuery(..) => { + InteractionType::FsyncQuery(..) => { unimplemented!("cannot implement fsync query in rusqlite, as we do not control IO"); } - Interaction::Assertion(_) => { + InteractionType::Assertion(_) => { interaction.execute_assertion(stack, env)?; stack.clear(); } - Interaction::Assumption(_) => { + InteractionType::Assumption(_) => { let assumption_result = interaction.execute_assumption(stack, env); stack.clear(); @@ -425,10 +421,10 @@ fn execute_interaction_rusqlite( return Ok(ExecutionContinuation::NextProperty); } } - Interaction::Fault(_) => { + InteractionType::Fault(_) => { interaction.execute_fault(env, connection_index)?; } - Interaction::FaultyQuery(_) => { + InteractionType::FaultyQuery(_) => { unimplemented!("cannot implement faulty query in rusqlite, as we do not control IO"); } } diff --git a/simulator/runner/execution.rs b/simulator/runner/execution.rs index c7f31ed88..93b499fe6 100644 --- a/simulator/runner/execution.rs +++ b/simulator/runner/execution.rs @@ -6,7 +6,7 @@ use turso_core::{Connection, LimboError, Result, StepResult}; use crate::generation::{ Shadow as _, - plan::{Interaction, InteractionPlan, InteractionPlanState, ResultSet}, + plan::{Interaction, InteractionPlan, InteractionPlanState, InteractionType, ResultSet}, }; use super::env::{SimConnection, SimulatorEnv}; @@ -183,8 +183,8 @@ pub(crate) fn execute_interaction( ) -> Result { // Leave this empty info! here to print the span of the execution tracing::info!(""); - match interaction { - Interaction::Query(_) => { + match &interaction.interaction { + InteractionType::Query(_) => { let conn = match &mut env.connections[connection_index] { SimConnection::LimboConnection(conn) => conn, SimConnection::SQLiteConnection(_) => unreachable!(), @@ -198,7 +198,7 @@ pub(crate) fn execute_interaction( stack.push(results); limbo_integrity_check(conn)?; } - Interaction::FsyncQuery(query) => { + InteractionType::FsyncQuery(query) => { let conn = match &env.connections[connection_index] { SimConnection::LimboConnection(conn) => conn.clone(), SimConnection::SQLiteConnection(_) => unreachable!(), @@ -211,15 +211,18 @@ pub(crate) fn execute_interaction( } stack.push(results); - let query_interaction = Interaction::Query(query.clone()); + let query_interaction = Interaction::new( + interaction.connection_index, + InteractionType::Query(query.clone()), + ); execute_interaction(env, connection_index, &query_interaction, stack)?; } - Interaction::Assertion(_) => { + InteractionType::Assertion(_) => { interaction.execute_assertion(stack, env)?; stack.clear(); } - Interaction::Assumption(_) => { + InteractionType::Assumption(_) => { let assumption_result = interaction.execute_assumption(stack, env); stack.clear(); @@ -228,10 +231,10 @@ pub(crate) fn execute_interaction( return Ok(ExecutionContinuation::NextProperty); } } - Interaction::Fault(_) => { + InteractionType::Fault(_) => { interaction.execute_fault(env, connection_index)?; } - Interaction::FaultyQuery(_) => { + InteractionType::FaultyQuery(_) => { let conn = match &env.connections[connection_index] { SimConnection::LimboConnection(conn) => conn.clone(), SimConnection::SQLiteConnection(_) => unreachable!(), diff --git a/simulator/shrink/plan.rs b/simulator/shrink/plan.rs index 4413e7c0a..a6a759ccc 100644 --- a/simulator/shrink/plan.rs +++ b/simulator/shrink/plan.rs @@ -1,7 +1,7 @@ use crate::{ SandboxedResult, SimulatorEnv, generation::{ - plan::{Interaction, InteractionPlan, Interactions, InteractionsType}, + plan::{InteractionPlan, InteractionType, Interactions, InteractionsType}, property::Property, }, model::Query, @@ -25,13 +25,13 @@ impl InteractionPlan { { let mut idx = failing_execution.secondary_index; loop { - match &interactions[idx] { - Interaction::Query(query) => { + match &interactions[idx].interaction { + InteractionType::Query(query) => { depending_tables = query.dependencies(); break; } // Fault does not depend on - Interaction::Fault(..) => break, + InteractionType::Fault(..) => break, _ => { // In principle we should never fail this checked_sub. // But if there is a bug in how we count the secondary index @@ -156,9 +156,9 @@ impl InteractionPlan { { let mut idx = failing_execution.secondary_index; loop { - match &interactions[idx] { + match &interactions[idx].interaction { // Fault does not depend on - Interaction::Fault(..) => break, + InteractionType::Fault(..) => break, _ => { // In principle we should never fail this checked_sub. // But if there is a bug in how we count the secondary index