Skip to content

Commit

Permalink
implement watch mode
Browse files Browse the repository at this point in the history
- add `--watch` flag
- start saving seeds in persistent storage
- make a separate version of execution functions that use `vector of interaction` instead of `InteractionPlan`
  • Loading branch information
alpaylan committed Jan 18, 2025
1 parent c30e275 commit e476b9f
Show file tree
Hide file tree
Showing 12 changed files with 521 additions and 91 deletions.
107 changes: 98 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions simulator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ anarchist-readable-name-generator-lib = "0.1.2"
clap = { version = "4.5", features = ["derive"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0" }
notify = "8.0.0"
85 changes: 78 additions & 7 deletions simulator/generation/plan.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{fmt::Display, rc::Rc, vec};
use std::{fmt::Display, path::Path, rc::Rc, vec};

use limbo_core::{Connection, Result, StepResult};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -26,6 +26,69 @@ pub(crate) struct InteractionPlan {
pub(crate) plan: Vec<Interactions>,
}

impl InteractionPlan {
/// Compute via diff computes a a plan from a given `.plan` file without the need to parse
/// sql. This is possible because there are two versions of the plan file, one that is human
/// readable and one that is serialized as JSON. Under watch mode, the users will be able to
/// delete interactions from the human readable file, and this function uses the JSON file as
/// a baseline to detect with interactions were deleted and constructs the plan from the
/// remaining interactions.
pub(crate) fn compute_via_diff(plan_path: &Path) -> Vec<Vec<Interaction>> {
let interactions = std::fs::read_to_string(plan_path).unwrap();
let interactions = interactions.lines().collect::<Vec<_>>();

let plan: InteractionPlan = serde_json::from_str(
std::fs::read_to_string(plan_path.with_extension("plan.json"))
.unwrap()
.as_str(),
)
.unwrap();

let mut plan = plan
.plan
.into_iter()
.map(|i| i.interactions())
.collect::<Vec<_>>();

let (mut i, mut j1, mut j2) = (0, 0, 0);

while i < interactions.len() && j1 < plan.len() {
if interactions[i].starts_with("-- begin")
|| interactions[i].starts_with("-- end")
|| interactions[i].is_empty()
{
i += 1;
continue;
}

if interactions[i].contains(plan[j1][j2].to_string().as_str()) {
i += 1;
if j2 + 1 < plan[j1].len() {
j2 += 1;
} else {
j1 += 1;
j2 = 0;
}
} else {
plan[j1].remove(j2);

if plan[j1].is_empty() {
plan.remove(j1);
j2 = 0;
}
}
}
if j1 < plan.len() {
if j2 < plan[j1].len() {
let _ = plan[j1].split_off(j2);
}
let _ = plan.split_off(j1);
}

plan
}
}

pub(crate) struct InteractionPlanState {
pub(crate) stack: Vec<ResultSet>,
pub(crate) interaction_pointer: usize,
Expand Down Expand Up @@ -110,12 +173,12 @@ impl Display for InteractionPlan {
match interaction {
Interaction::Query(query) => writeln!(f, "{};", query)?,
Interaction::Assumption(assumption) => {
writeln!(f, "-- ASSUME: {};", assumption.message)?
writeln!(f, "-- ASSUME {};", assumption.message)?
}
Interaction::Assertion(assertion) => {
writeln!(f, "-- ASSERT: {};", assertion.message)?
writeln!(f, "-- ASSERT {};", assertion.message)?
}
Interaction::Fault(fault) => writeln!(f, "-- FAULT: {};", fault)?,
Interaction::Fault(fault) => writeln!(f, "-- FAULT '{}';", fault)?,
}
}
writeln!(f, "-- end testing '{}'", name)?;
Expand Down Expand Up @@ -162,9 +225,9 @@ impl Display for Interaction {
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.message),
Self::Assertion(assertion) => write!(f, "ASSERT: {}", assertion.message),
Self::Fault(fault) => write!(f, "FAULT: {}", fault),
Self::Assumption(assumption) => write!(f, "ASSUME {}", assumption.message),
Self::Assertion(assertion) => write!(f, "ASSERT {}", assertion.message),
Self::Fault(fault) => write!(f, "FAULT '{}'", fault),
}
}
}
Expand Down Expand Up @@ -326,6 +389,14 @@ impl ArbitraryFrom<&mut SimulatorEnv> for InteractionPlan {
}

impl Interaction {
pub(crate) fn shadow(&self, env: &mut SimulatorEnv) {
match self {
Self::Query(query) => query.shadow(env),
Self::Assumption(_) => {}
Self::Assertion(_) => {}
Self::Fault(_) => {}
}
}
pub(crate) fn execute_query(&self, conn: &mut Rc<Connection>) -> ResultSet {
if let Self::Query(query) = self {
let query_str = query.to_string();
Expand Down
1 change: 0 additions & 1 deletion simulator/generation/property.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ impl Property {

let assertion = Interaction::Assertion(Assertion {
message: format!(
// todo: add the part inserting ({} = {})",
"row [{:?}] not found in table {}",
row.iter().map(|v| v.to_string()).collect::<Vec<String>>(),
insert.table,
Expand Down
Loading

0 comments on commit e476b9f

Please sign in to comment.