use std::fmt::Write as _;
use std::io::Write as _;
use ddx_core::sqlparser::ast::Expr;
use ddx_core::sqlparser::dialect::GenericDialect;
use ddx_core::test_utils::{
central_diff, eval, gen_adversarial_sql, gen_expr, gen_expr_and_wrt, gen_marker_free_stmt,
gen_marker_statement, has_residual_marker, max_intermediate_mag, metamorphic_mismatch,
min_domain_margin, parse_expr, run_bounded, seeded, try_parse, try_parse_stmt, Rng, Var,
};
use ddx_core::{ColRef, Ddx, DiffError};
fn fd_failure(rng: &mut Rng, expr_text: &str, d: &Expr, wrt: Var) -> Option<String> {
const H: f64 = 1e-4;
const RTOL: f64 = 2e-3;
const ATOL: f64 = 1e-5;
const COND_CAP: f64 = 1e5; const RICHARDSON_TOL: f64 = 1e-4;
const MAG_CAP: f64 = 1e8;
const DOMAIN_EPS: f64 = 1e-3;
let f = parse_expr(expr_text);
let mut comparable = 0u32;
let mut disagree = 0u32;
let mut first_bad = String::new();
for _ in 0..80 {
if comparable >= 8 {
break;
}
let x0 = rng.range(0.2, 1.8);
let y0 = rng.range(0.2, 1.8);
let near_edge = [
(x0, y0),
(x0 + H, y0),
(x0 - H, y0),
(x0, y0 + H),
(x0, y0 - H),
]
.iter()
.any(|&(px, py)| matches!(min_domain_margin(&f, px, py), Some(m) if m < DOMAIN_EPS));
if near_edge {
continue;
}
let fmag = max_intermediate_mag(&f, x0, y0);
let dmag = max_intermediate_mag(d, x0, y0);
match (fmag, dmag) {
(Some(fm), Some(dm)) if fm <= MAG_CAP && dm <= MAG_CAP => {}
_ => continue,
}
let (Some(fd_h), Some(fd_h2), Some(dv)) = (
central_diff(&f, x0, y0, wrt, H),
central_diff(&f, x0, y0, wrt, H / 2.0),
eval(d, x0, y0),
) else {
continue;
};
if !fd_h.is_finite() || !fd_h2.is_finite() || !dv.is_finite() {
continue;
}
if fd_h.abs() > COND_CAP || fd_h2.abs() > COND_CAP || dv.abs() > COND_CAP {
continue;
}
if (fd_h - fd_h2).abs() > RICHARDSON_TOL * fd_h2.abs().max(1.0) {
continue;
}
comparable += 1;
let fd = fd_h2;
if (fd - dv).abs() > ATOL + RTOL * dv.abs().max(fd.abs()) {
disagree += 1;
if first_bad.is_empty() {
first_bad = format!(
"x={x0:.6} y={y0:.6}: symbolic d/d{} = {dv:.8}, finite-diff = {fd:.8}",
wrt.name()
);
}
}
}
if comparable >= 4 && disagree >= 2 && disagree * 2 > comparable {
return Some(format!(
"[finite-diff] d/d{} {expr_text}\n => {d}\n {disagree}/{comparable} points disagree; e.g. {first_bad}",
wrt.name()
));
}
None
}
fn fidelity_failure(rng: &mut Rng, expr_text: &str, d: &Expr, wrt: Var) -> Option<String> {
const RTOL: f64 = 1e-9;
const ATOL: f64 = 1e-11;
let rendered = d.to_string();
if rendered.contains("--") {
return Some(format!(
"[render] emitted a `--` comment: d/d{} {expr_text} => {rendered}",
wrt.name()
));
}
let reparsed = match try_parse(&rendered) {
Ok(rp) => rp,
Err(e) => {
return Some(format!(
"[render] engine emitted unparseable SQL: d/d{} {expr_text} => {rendered} ({e})",
wrt.name()
))
}
};
let mut compared = 0u32;
for _ in 0..40 {
if compared >= 6 {
break;
}
let x0 = rng.range(0.2, 1.8);
let y0 = rng.range(0.2, 1.8);
let scale = match (
max_intermediate_mag(d, x0, y0),
max_intermediate_mag(&reparsed, x0, y0),
) {
(Some(a), Some(b)) if a.is_finite() && b.is_finite() && a.max(b) < 1e300 => a.max(b),
_ => continue,
};
let (Some(va), Some(vb)) = (eval(d, x0, y0), eval(&reparsed, x0, y0)) else {
continue;
};
if !va.is_finite() || !vb.is_finite() {
continue;
}
compared += 1;
if (va - vb).abs() > ATOL + RTOL * scale {
return Some(format!(
"[render] render changed the value: d/d{} {expr_text}\n rendered = {rendered}\n at x={x0:.4} y={y0:.4}: AST = {va:.10}, reparsed = {vb:.10}",
wrt.name()
));
}
}
None
}
fn self_consumption_failure(ddx: &Ddx, wrt: &ColRef, original: &str) -> Option<String> {
let mut current = original.to_string();
for round in 0..4 {
let parsed = match try_parse(¤t) {
Ok(p) => p,
Err(e) if e.contains("recursion limit exceeded") => break,
Err(e) => {
return Some(format!(
"[self-consumption] round {round}: engine's own output did not reparse: `{current}` ({e}) [from {original}]"
))
}
};
match ddx.differentiate(&parsed, wrt) {
Ok(d) => {
let rendered = d.to_string();
if rendered.contains("--") {
return Some(format!(
"[self-consumption] round {round}: emitted `--` comment: `{rendered}` [from {original}]"
));
}
current = rendered;
}
Err(DiffError::NotImplemented(_)) => break,
Err(e) => {
return Some(format!(
"[self-consumption] round {round}: unexpected error re-differentiating `{current}`: {e} [from {original}]"
))
}
}
}
None
}
fn splice_failure(rng: &mut Rng, ddx: &Ddx) -> Option<String> {
let (input, expected) = gen_marker_statement(rng, ddx);
let got = ddx.rewrite_sql(&input, &GenericDialect {});
let Some(expected) = expected else {
return match got {
Err(_) => None,
Ok(o) => Some(format!(
"[splice] expected an error (a marker derivative is undefined) but got Ok:\n input = {input}\n output = {o}"
)),
};
};
match got {
Ok(o) if o == expected => None,
Ok(o) => Some(format!(
"[splice] rewrite_sql splice mismatch:\n input = {input}\n expected = {expected}\n actual = {o}"
)),
Err(e) => Some(format!(
"[splice] rewrite_sql errored on a valid marker statement:\n input = {input}\n error = {e}"
)),
}
}
fn marker_free_failure(rng: &mut Rng, ddx: &Ddx) -> Option<String> {
let s = gen_marker_free_stmt(rng);
match ddx.rewrite_sql(&s, &GenericDialect {}) {
Ok(o) if o == s => None,
Ok(o) => Some(format!(
"[identity] marker-free statement was modified:\n input = {s}\n output = {o}"
)),
Err(e) => Some(format!(
"[identity] marker-free statement errored:\n input = {s}\n error = {e}"
)),
}
}
fn rewrite_validity_failure(rng: &mut Rng, ddx: &Ddx) -> Option<String> {
let (input, expected) = gen_marker_statement(rng, ddx);
let out = match ddx.rewrite_sql(&input, &GenericDialect {}) {
Ok(o) => o,
Err(_) if expected.is_none() => return None,
Err(e) => {
return Some(format!(
"[validity] rewrite_sql errored on a valid marker statement:\n input = {input}\n error = {e}"
))
}
};
match try_parse_stmt(&out) {
Err(e) => Some(format!(
"[validity] rewrite_sql emitted unparseable SQL:\n input = {input}\n output = {out}\n parse error = {e}"
)),
Ok(stmts) if has_residual_marker(&stmts) => Some(format!(
"[validity] rewrite_sql left a residual grad/jvp marker:\n input = {input}\n output = {out}"
)),
Ok(_) => None,
}
}
fn idempotence_failure(rng: &mut Rng, ddx: &Ddx) -> Option<String> {
let (input, _) = gen_marker_statement(rng, ddx);
let once = match ddx.rewrite_sql(&input, &GenericDialect {}) {
Ok(o) => o,
Err(_) => return None, };
match ddx.rewrite_sql(&once, &GenericDialect {}) {
Ok(twice) if twice == once => None,
Ok(twice) => Some(format!(
"[idempotence] rewrite_sql is not idempotent:\n input = {input}\n once = {once}\n twice = {twice}"
)),
Err(e) => Some(format!(
"[idempotence] rewrite_sql errored on its own output:\n input = {input}\n once = {once}\n error = {e}"
)),
}
}
fn panic_failure(rng: &mut Rng, ddx: &Ddx) -> Option<String> {
let input = gen_adversarial_sql(rng);
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
ddx.rewrite_sql(&input, &GenericDialect {}).is_ok()
}));
match result {
Ok(_) => None,
Err(payload) => {
let msg = payload
.downcast_ref::<&str>()
.map(|s| s.to_string())
.or_else(|| payload.downcast_ref::<String>().cloned())
.unwrap_or_else(|| "<non-string panic>".to_string());
Some(format!(
"[panic] rewrite_sql PANICKED (must return a typed error instead):\n input = {input:?}\n panic = {msg}"
))
}
}
}
fn zero_derivative_failure(rng: &mut Rng, ddx: &Ddx, text: &str) -> Option<String> {
let f = parse_expr(text);
let d = match ddx.differentiate(&f, &ColRef::bare("w")) {
Ok(d) => d,
Err(_) => return None,
};
for _ in 0..12 {
let x0 = rng.range(0.2, 1.8);
let y0 = rng.range(0.2, 1.8);
if let Some(v) = eval(&d, x0, y0) {
if v.is_finite() && v.abs() > 1e-12 {
return Some(format!(
"[zero-deriv] d/dw {text} is not zero (w is absent):\n => {d}\n at x={x0:.4} y={y0:.4}: value = {v}"
));
}
}
}
None
}
fn no_inf_nan_failure(text: &str, d: &Expr) -> Option<String> {
let rendered = d.to_string();
let low = rendered.to_ascii_lowercase();
if low.contains("inf") || low.contains("nan") {
return Some(format!(
"[inf-nan] derivative text contains an inf/nan token:\n d/d? {text}\n => {rendered}"
));
}
None
}
fn jvp_consistency_failure(rng: &mut Rng, ddx: &Ddx, text: &str, wrt: Var) -> Option<String> {
let f = parse_expr(text);
let wrt_col = ColRef::bare(wrt.name());
let tan_depth = 1 + rng.below(2) as u32;
let t_text = gen_expr(rng, tan_depth);
let t = parse_expr(&t_text);
let grad_e = ddx.differentiate(&f, &wrt_col).ok()?;
let jvp_e = ddx.jvp(&f, &[(wrt_col, t.clone())]).ok()?;
let gate = [&f, &t, &grad_e];
if let Some((x0, y0, a, b)) = metamorphic_mismatch(rng, &gate, &jvp_e, |x, y| {
Some(eval(&t, x, y)? * eval(&grad_e, x, y)?)
}) {
return Some(format!(
"[jvp≠t·grad] jvp({text}, {w}, {t_text}) ≠ tangent·grad:\n jvp => {jvp_e}\n grad => {grad_e}\n at x={x0:.4} y={y0:.4}: jvp = {a}, t·grad = {b}",
w = wrt.name()
));
}
None
}
fn linearity_failure(rng: &mut Rng, ddx: &Ddx, f_text: &str, wrt: Var) -> Option<String> {
let wrt_col = ColRef::bare(wrt.name());
let f = parse_expr(f_text);
let g_depth = 2 + rng.below(2) as u32;
let g_text = gen_expr(rng, g_depth);
let g = parse_expr(&g_text);
let df = ddx.differentiate(&f, &wrt_col).ok()?;
let dg = ddx.differentiate(&g, &wrt_col).ok()?;
let sum = parse_expr(&format!("({f_text}) + ({g_text})"));
let dsum = ddx.differentiate(&sum, &wrt_col).ok()?;
let gate_sum = [&f, &g, &df, &dg];
if let Some((x0, y0, a, b)) = metamorphic_mismatch(rng, &gate_sum, &dsum, |x, y| {
Some(eval(&df, x, y)? + eval(&dg, x, y)?)
}) {
return Some(format!(
"[linearity] d(f+g) ≠ d(f)+d(g):\n f = {f_text}\n g = {g_text}\n d(f+g) => {dsum}\n at x={x0:.4} y={y0:.4}: lhs = {a}, rhs = {b}"
));
}
let prod = parse_expr(&format!("({f_text}) * ({g_text})"));
let dprod = ddx.differentiate(&prod, &wrt_col).ok()?;
let gate_prod = [&f, &g, &df, &dg];
if let Some((x0, y0, a, b)) = metamorphic_mismatch(rng, &gate_prod, &dprod, |x, y| {
Some(eval(&df, x, y)? * eval(&g, x, y)? + eval(&f, x, y)? * eval(&dg, x, y)?)
}) {
return Some(format!(
"[product-rule] d(f*g) ≠ d(f)*g + f*d(g):\n f = {f_text}\n g = {g_text}\n d(f*g) => {dprod}\n at x={x0:.4} y={y0:.4}: lhs = {a}, rhs = {b}"
));
}
None
}
fn run_all_checks(rng: &mut Rng, ddx: &Ddx, text: &str, wrt: Var) -> Vec<String> {
let mut out = Vec::new();
let parsed = match try_parse(text) {
Ok(p) => p,
Err(e) => {
out.push(format!(
"[generator] produced unparseable text `{text}` ({e})"
));
return out;
}
};
let wrt_col = ColRef::bare(wrt.name());
let d = match ddx.differentiate(&parsed, &wrt_col) {
Ok(d) => d,
Err(DiffError::NotImplemented(_)) => return out, Err(e) => {
out.push(format!("[differentiate] unexpected error on `{text}`: {e}"));
return out;
}
};
if let Some(f) = fd_failure(rng, text, &d, wrt) {
out.push(f);
}
if let Some(f) = fidelity_failure(rng, text, &d, wrt) {
out.push(f);
}
if let Some(f) = self_consumption_failure(ddx, &wrt_col, text) {
out.push(f);
}
if let Some(f) = no_inf_nan_failure(text, &d) {
out.push(f);
}
if let Some(f) = zero_derivative_failure(rng, ddx, text) {
out.push(f);
}
if let Some(f) = jvp_consistency_failure(rng, ddx, text, wrt) {
out.push(f);
}
if let Some(f) = linearity_failure(rng, ddx, text, wrt) {
out.push(f);
}
if let Some(f) = splice_failure(rng, ddx) {
out.push(f);
}
if let Some(f) = marker_free_failure(rng, ddx) {
out.push(f);
}
if let Some(f) = rewrite_validity_failure(rng, ddx) {
out.push(f);
}
if let Some(f) = idempotence_failure(rng, ddx) {
out.push(f);
}
if let Some(f) = panic_failure(rng, ddx) {
out.push(f);
}
out
}
#[test]
fn finite_difference_agreement_over_random_expressions() {
let ddx = Ddx::new();
let wrt = ColRef::bare("x");
let mut failures: Vec<String> = Vec::new();
let mut tested = 0u32;
for seed in 0..4000u64 {
let mut rng = seeded(seed, 0);
let depth = 2 + (seed % 3) as u32;
let text = gen_expr(&mut rng, depth);
let parsed = parse_expr(&text);
let d = match ddx.differentiate(&parsed, &wrt) {
Ok(d) => d,
Err(DiffError::NotImplemented(_)) => continue,
Err(e) => {
failures.push(format!("UNEXPECTED ERROR on `{text}`: {e}"));
continue;
}
};
tested += 1;
if let Some(report) = fd_failure(&mut rng, &text, &d, Var::X) {
failures.push(report);
}
}
assert!(
tested > 500,
"generator produced too few derivable cases: {tested}"
);
assert!(
failures.is_empty(),
"finite-difference oracle found {} disagreement(s) out of {} tested:\n\n{}",
failures.len(),
tested,
failures
.iter()
.take(15)
.cloned()
.collect::<Vec<_>>()
.join("\n\n")
);
}
#[test]
fn render_reparse_is_value_preserving() {
let ddx = Ddx::new();
let wrt = ColRef::bare("x");
let mut failures: Vec<String> = Vec::new();
for seed in 0..5000u64 {
let mut rng = seeded(seed, 0xDEAD_BEEF);
let depth = 2 + (seed % 4) as u32;
let text = gen_expr(&mut rng, depth);
let parsed = parse_expr(&text);
let d = match ddx.differentiate(&parsed, &wrt) {
Ok(d) => d,
Err(_) => continue,
};
if let Some(report) = fidelity_failure(&mut rng, &text, &d, Var::X) {
failures.push(report);
}
}
assert!(
failures.is_empty(),
"render-fidelity fuzz found {} failure(s):\n\n{}",
failures.len(),
failures
.iter()
.take(15)
.cloned()
.collect::<Vec<_>>()
.join("\n\n")
);
}
#[test]
fn higher_order_self_consumption_is_stable() {
let ddx = Ddx::new();
let wrt = ColRef::bare("x");
let mut failures: Vec<String> = Vec::new();
for seed in 0..2000u64 {
let mut rng = seeded(seed, 0x1234_5678);
let depth = 2 + (seed % 3) as u32;
let original = gen_expr(&mut rng, depth);
if let Some(report) = self_consumption_failure(&ddx, &wrt, &original) {
failures.push(report);
}
}
assert!(
failures.is_empty(),
"self-consumption fuzz found {} failure(s):\n\n{}",
failures.len(),
failures
.iter()
.take(15)
.cloned()
.collect::<Vec<_>>()
.join("\n\n")
);
}
#[test]
fn rewrite_sql_splice_is_byte_faithful() {
let ddx = Ddx::new();
let mut failures: Vec<String> = Vec::new();
for seed in 0..4000u64 {
let mut rng = seeded(seed, 0x5719_C0DE);
if let Some(report) = splice_failure(&mut rng, &ddx) {
failures.push(report);
}
}
assert!(
failures.is_empty(),
"splice-fidelity fuzz found {} failure(s):\n\n{}",
failures.len(),
failures
.iter()
.take(15)
.cloned()
.collect::<Vec<_>>()
.join("\n\n")
);
}
#[test]
fn splice_handles_marker_with_cast_or_nested_tail() {
let ddx = Ddx::new();
assert_eq!(
ddx.rewrite_sql(
"SELECT jvp(sin(x), x, CAST(y AS DOUBLE)) FROM t",
&GenericDialect {}
)
.unwrap(),
"SELECT (cos(x) * CAST(y AS DOUBLE)) FROM t"
);
assert_eq!(
ddx.rewrite_sql("SELECT jvp(x, x, (y + z)) FROM t", &GenericDialect {})
.unwrap(),
"SELECT ((y + z)) FROM t"
);
}
#[test]
fn marker_free_statements_are_byte_identical() {
let ddx = Ddx::new();
let mut failures: Vec<String> = Vec::new();
for seed in 0..2000u64 {
let mut rng = seeded(seed, 0x1DE0_7175);
if let Some(report) = marker_free_failure(&mut rng, &ddx) {
failures.push(report);
}
}
assert!(
failures.is_empty(),
"marker-free identity fuzz found {} failure(s):\n\n{}",
failures.len(),
failures
.iter()
.take(15)
.cloned()
.collect::<Vec<_>>()
.join("\n\n")
);
}
#[test]
fn rewrite_sql_output_is_valid_and_marker_free() {
let ddx = Ddx::new();
run_bounded("rewrite validity fuzz", 4000, 0x5A11_D000, |rng| {
rewrite_validity_failure(rng, &ddx)
});
}
#[test]
fn rewrite_sql_never_panics_on_adversarial_input() {
let ddx = Ddx::new();
run_bounded("never-panic fuzz", 5000, 0x9A11_C000, |rng| {
panic_failure(rng, &ddx)
});
}
#[test]
fn jvp_equals_tangent_times_grad() {
let ddx = Ddx::new();
run_bounded("jvp↔grad consistency fuzz", 4000, 0x0F5E_ED00, |rng| {
let (text, wrt) = gen_expr_and_wrt(rng);
jvp_consistency_failure(rng, &ddx, &text, wrt)
});
}
#[test]
fn derivative_of_absent_variable_is_zero() {
let ddx = Ddx::new();
run_bounded("zero-derivative fuzz", 4000, 0x2E50_1000, |rng| {
let depth = 2 + rng.below(4) as u32;
let text = gen_expr(rng, depth);
zero_derivative_failure(rng, &ddx, &text)
});
}
#[test]
fn rewrite_sql_is_idempotent() {
let ddx = Ddx::new();
run_bounded("idempotence fuzz", 4000, 0x1DE1_1000, |rng| {
idempotence_failure(rng, &ddx)
});
}
#[test]
fn no_inf_or_nan_token_is_ever_emitted() {
let ddx = Ddx::new();
run_bounded("inf/nan-token fuzz", 4000, 0x1FFF_F000, |rng| {
let (text, wrt) = gen_expr_and_wrt(rng);
let d = ddx
.differentiate(&parse_expr(&text), &ColRef::bare(wrt.name()))
.ok()?;
no_inf_nan_failure(&text, &d)
});
}
#[test]
fn differentiation_is_linear_and_obeys_the_product_rule() {
let ddx = Ddx::new();
run_bounded("linearity/product-rule fuzz", 4000, 0x114E_A200, |rng| {
let (text, wrt) = gen_expr_and_wrt(rng);
linearity_failure(rng, &ddx, &text, wrt)
});
}
fn env_u64(key: &str, default: u64) -> u64 {
std::env::var(key)
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(default)
}
#[test]
#[ignore = "soak: long-running continuous fuzz; run explicitly with DDX_SOAK_SECS set"]
fn soak_continuous_property_fuzz() {
use std::time::Instant;
let budget_secs = env_u64("DDX_SOAK_SECS", 15);
let base = env_u64("DDX_SOAK_BASE", 0);
let log_path = std::env::var("DDX_SOAK_LOG").ok();
let mut log = log_path.as_ref().map(|p| {
std::fs::OpenOptions::new()
.create(true)
.append(true)
.open(p)
.unwrap_or_else(|e| panic!("cannot open DDX_SOAK_LOG `{p}`: {e}"))
});
let mut logline = |s: &str| {
eprintln!("{s}");
if let Some(f) = log.as_mut() {
let _ = writeln!(f, "{s}");
let _ = f.flush();
}
};
let ddx = Ddx::new();
let start = Instant::now();
let deadline = budget_secs;
let mut iters: u64 = 0;
let mut failures: u64 = 0;
let mut last_beat = 0u64;
logline(&format!(
"SOAK start: budget={budget_secs}s base={base} log={:?}",
log_path
));
loop {
let elapsed = start.elapsed().as_secs();
if elapsed >= deadline {
break;
}
let seed = base.wrapping_add(iters);
let mut rng = seeded(seed, 0xA5A5_5A5A);
let depth = 2 + (rng.below(5) as u32); let wrt = if rng.below(2) == 0 { Var::X } else { Var::Y };
let text = gen_expr(&mut rng, depth);
let reports = run_all_checks(&mut rng, &ddx, &text, wrt);
if reports.is_empty() {
} else {
for r in &reports {
failures += 1;
logline(&format!(
"\nFAILURE (seed={seed}, base={base}, depth={depth}, wrt={}):\n{r}",
wrt.name()
));
}
}
iters += 1;
if elapsed != last_beat {
last_beat = elapsed;
logline(&format!(
"HEARTBEAT elapsed={elapsed}s iters={iters} failures={failures} rate={}/s",
iters / elapsed.max(1)
));
}
}
let mut summary = String::new();
let _ = write!(
summary,
"SOAK done: elapsed={}s iters={iters} failures={failures} base={base} next_base={}",
start.elapsed().as_secs(),
base.wrapping_add(iters)
);
logline(&summary);
assert_eq!(
failures, 0,
"soak found {failures} property failure(s) — see the FAILURE lines above (each has a reproducing seed)"
);
}