disable Watch Mode until we can properly serialize interaction plan

This commit is contained in:
pedrocarlo
2025-10-18 12:10:52 -03:00
parent 4f143f385a
commit a4f0f2364d
3 changed files with 5 additions and 124 deletions

View File

@@ -1,8 +1,6 @@
#![allow(clippy::arc_with_non_send_sync)]
use anyhow::anyhow;
use clap::Parser;
use notify::event::{DataChange, ModifyKind};
use notify::{EventKind, RecursiveMode, Watcher};
use rand::prelude::*;
use runner::bugbase::BugBase;
use runner::cli::{SimulatorCLI, SimulatorCommand};
@@ -15,7 +13,7 @@ use std::fs::OpenOptions;
use std::io::{IsTerminal, Write};
use std::path::Path;
use std::rc::Rc;
use std::sync::{Arc, Mutex, mpsc};
use std::sync::{Arc, Mutex};
use tracing_subscriber::EnvFilter;
use tracing_subscriber::field::MakeExt;
use tracing_subscriber::fmt::format;
@@ -133,8 +131,7 @@ fn testing_main(cli_opts: &mut SimulatorCLI, profile: &Profile) -> anyhow::Resul
let (seed, mut env, plans) = setup_simulation(bugbase.as_mut(), cli_opts, profile);
if cli_opts.watch {
watch_mode(env).unwrap();
return Ok(());
anyhow::bail!("watch mode is disabled for now");
}
let paths = env.paths.clone();
@@ -158,58 +155,6 @@ fn testing_main(cli_opts: &mut SimulatorCLI, profile: &Profile) -> anyhow::Resul
result
}
fn watch_mode(env: SimulatorEnv) -> notify::Result<()> {
let (tx, rx) = mpsc::channel::<notify::Result<notify::Event>>();
println!("watching {:?}", env.get_plan_path());
// Use recommended_watcher() to automatically select the best implementation
// for your platform. The `EventHandler` passed to this constructor can be a
// closure, a `std::sync::mpsc::Sender`, a `crossbeam_channel::Sender`, or
// another type the trait is implemented for.
let mut watcher = notify::recommended_watcher(tx)?;
// Add a path to be watched. All files and directories at that path and
// below will be monitored for changes.
watcher.watch(&env.get_plan_path(), RecursiveMode::NonRecursive)?;
// Block forever, printing out events as they come in
let last_execution = Arc::new(Mutex::new(Execution::new(0, 0)));
for res in rx {
match res {
Ok(event) => {
if let EventKind::Modify(ModifyKind::Data(DataChange::Content)) = event.kind {
tracing::info!("plan file modified, rerunning simulation");
let env = env.clone_without_connections();
let last_execution_ = last_execution.clone();
let result = SandboxedResult::from(
std::panic::catch_unwind(move || {
let mut env = env;
let plan_path = env.get_plan_path();
let plan = InteractionPlan::compute_via_diff(&plan_path);
env.clear();
let env = Arc::new(Mutex::new(env.clone_without_connections()));
run_simulation_default(env, plan, last_execution_.clone())
}),
last_execution.clone(),
);
match result {
SandboxedResult::Correct => {
tracing::info!("simulation succeeded");
println!("simulation succeeded");
}
SandboxedResult::Panicked { error, .. }
| SandboxedResult::FoundBug { error, .. } => {
tracing::error!("simulation failed: '{}'", error);
}
}
}
}
Err(e) => println!("watch error: {e:?}"),
}
}
Ok(())
}
fn run_simulator(
mut bugbase: Option<&mut BugBase>,
cli_opts: &SimulatorCLI,

View File

@@ -1,7 +1,6 @@
use std::{
fmt::{Debug, Display},
ops::{Deref, DerefMut},
path::Path,
rc::Rc,
sync::Arc,
};
@@ -115,72 +114,6 @@ impl InteractionPlan {
self.len = self.new_len();
}
/// 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) -> impl InteractionPlanIterator {
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("json"))
.unwrap()
.as_str(),
)
.unwrap();
let mut plan = plan
.plan
.into_iter()
.map(|i| i.interactions())
.collect::<Vec<_>>();
let (mut i, mut j) = (0, 0);
while i < interactions.len() && j < plan.len() {
if interactions[i].starts_with("-- begin")
|| interactions[i].starts_with("-- end")
|| interactions[i].is_empty()
{
i += 1;
continue;
}
// interactions[i] is the i'th line in the human readable plan
// plan[j][k] is the k'th interaction in the j'th property
let mut k = 0;
while k < plan[j].len() {
if i >= interactions.len() {
let _ = plan.split_off(j + 1);
let _ = plan[j].split_off(k);
break;
}
tracing::error!("Comparing '{}' with '{}'", interactions[i], plan[j][k]);
if interactions[i].contains(plan[j][k].to_string().as_str()) {
i += 1;
k += 1;
} else {
plan[j].remove(k);
panic!("Comparing '{}' with '{}'", interactions[i], plan[j][k]);
}
}
if plan[j].is_empty() {
plan.remove(j);
} else {
j += 1;
}
}
let _ = plan.split_off(j);
PlanIterator {
iter: plan.into_iter().flatten(),
}
}
pub fn interactions_list(&self) -> Vec<Interaction> {
self.plan
.clone()

View File

@@ -200,6 +200,9 @@ pub enum SimulatorCommand {
impl SimulatorCLI {
pub fn validate(&mut self) -> anyhow::Result<()> {
if self.watch {
anyhow::bail!("watch mode is disabled for now");
}
if self.minimum_tests > self.maximum_tests {
tracing::warn!(
"minimum size '{}' is greater than '{}' maximum size, setting both to '{}'",