From 7d1f23dd3aab7cddf0d69d77e4cdd24e7def6d39 Mon Sep 17 00:00:00 2001 From: pedrocarlo Date: Mon, 22 Sep 2025 13:11:44 -0300 Subject: [PATCH] better diffing with similar crate --- Cargo.lock | 40 ++++++++++++++++++ Cargo.toml | 5 +++ simulator/Cargo.toml | 2 + simulator/runner/differential.rs | 69 ++++++++++++++++---------------- 4 files changed, 82 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dfdb48cf3..c3c1c280e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -621,6 +621,18 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "windows-sys 0.59.0", +] + [[package]] name = "console_error_panic_hook" version = "0.1.7" @@ -1100,6 +1112,12 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "encryption-throughput" version = "0.1.0" @@ -2171,6 +2189,8 @@ dependencies = [ "schemars 1.0.4", "serde", "serde_json", + "similar", + "similar-asserts", "sql_generation", "strum", "tracing", @@ -3540,6 +3560,26 @@ dependencies = [ "libc", ] +[[package]] +name = "similar" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" +dependencies = [ + "bstr", + "unicode-segmentation", +] + +[[package]] +name = "similar-asserts" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b441962c817e33508847a22bd82f03a30cff43642dc2fae8b050566121eb9a" +dependencies = [ + "console", + "similar", +] + [[package]] name = "slab" version = "0.4.9" diff --git a/Cargo.toml b/Cargo.toml index 96d3af1a2..4ca15dd35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -96,6 +96,11 @@ tracing-appender = "0.2.3" env_logger = { version = "0.11.6", default-features = false } regex = "1.11.1" regex-syntax = { version = "0.8.5", default-features = false } +similar = { version = "2.7.0" } +similar-asserts = { version = "1.7.0" } + +[profile.dev.package.similar] +opt-level = 3 [profile.release] debug = "line-tables-only" diff --git a/simulator/Cargo.toml b/simulator/Cargo.toml index 8c37dd8f0..84d67304e 100644 --- a/simulator/Cargo.toml +++ b/simulator/Cargo.toml @@ -45,3 +45,5 @@ strum = { workspace = true } parking_lot = { workspace = true } indexmap = { workspace = true } either = "1.15.0" +similar = { workspace = true } +similar-asserts = { workspace = true } diff --git a/simulator/runner/differential.rs b/simulator/runner/differential.rs index a64585085..1a519228c 100644 --- a/simulator/runner/differential.rs +++ b/simulator/runner/differential.rs @@ -1,5 +1,8 @@ use std::sync::{Arc, Mutex}; +use similar_asserts::SimpleDiff; +use sql_generation::model::table::SimValue; + use crate::generation::plan::{ConnectionState, Interaction, InteractionPlanState}; use super::{ @@ -147,43 +150,41 @@ fn compare_results( tracing::error!( "returned values from limbo and rusqlite results do not match" ); - let diff = limbo_values - .iter() - .zip(rusqlite_values.iter()) - .enumerate() - .filter(|(_, (l, r))| l != r) - .collect::>(); - let diff = diff - .iter() - .flat_map(|(i, (l, r))| { - let mut diffs = vec![]; - for (j, (l, r)) in l.iter().zip(r.iter()).enumerate() { - if l != r { - tracing::debug!( - "difference at index {}, {}: {} != {}", - i, - j, - l.to_string(), - r.to_string() - ); - diffs.push(((i, j), (l.clone(), r.clone()))); - } + fn val_to_string(sim_val: &SimValue) -> String { + match &sim_val.0 { + turso_core::Value::Blob(blob) => { + let convert_blob = || -> anyhow::Result { + let val = String::from_utf8(blob.clone())?; + Ok(val) + }; + + convert_blob().unwrap_or_else(|_| sim_val.to_string()) } - diffs - }) - .collect::>(); - tracing::debug!("limbo values {:?}", limbo_values); - tracing::debug!("rusqlite values {:?}", rusqlite_values); - tracing::debug!( - "differences: {}", - diff.iter() - .map(|((i, j), (l, r))| format!( - "\t({i}, {j}): ({l}) != ({r})" - )) - .collect::>() - .join("\n") + _ => sim_val.to_string(), + } + } + + let limbo_string_values: Vec> = limbo_values + .iter() + .map(|rows| rows.iter().map(|row| val_to_string(row)).collect()) + .collect(); + + let rusqlite_string_values: Vec> = rusqlite_values + .iter() + .map(|rows| rows.iter().map(|row| val_to_string(row)).collect()) + .collect(); + + let turso_string = format!("{limbo_string_values:#?}"); + let rusqlite_string = format!("{rusqlite_string_values:#?}"); + let diff = SimpleDiff::from_str( + &turso_string, + &rusqlite_string, + "turso", + "rusqlite", ); + tracing::error!(%diff); + return Err(turso_core::LimboError::InternalError( "returned values from limbo and rusqlite results do not match" .into(),