Differential Fuzzer
Always load Debugging skill for reference
The differential fuzzer compares Turso results against SQLite for generated SQL statements to find correctness bugs.
Location
testing/differential-oracle/fuzzer/
Running the Fuzzer
Single Run
Continuous Fuzzing (Loop Mode)
Docker Runner (CI/Production)
Environment variables for docker-runner:
TIME_LIMIT_MINUTES- Total runtime (default: 1440 = 24h)PER_RUN_TIMEOUT_SECONDS- Per-run timeout (default: 1200 = 20min)NUM_STATEMENTS- Statements per run (default: 1000)LOG_TO_STDOUT- Print fuzzer output (default: false)GITHUB_TOKEN- For auto-filing issuesSLACK_WEBHOOK_URL- For notifications
Output Files
All output goes to simulator-output/ directory:
Reproducing Errors
Always follow these steps
-
Find the seed and profile in the error output:
-
Re-run with that seed and profile (a seed only replays under the same profile):
-
Read the minimized reproduction first. On an oracle failure the fuzzer writes these files to
simulator-output/:minimized.sql- a shrunken state script plus the shrunken failing statement, produced automatically. Start here.turso-state.sql/sqlite-state.sql- each engine's full state as a replayable script, when you need more than the minimized version kept.test.sql- every executed statement (the failing one is marked-- FAILED:). The minimizer falls back to replaying this history when the failure depends on how the state was built, not just its contents.schema.json- table structure at failure time.
-
Probe the reproduction with
differential_probe. It runs a statement-per-line script on Turso and SQLite side by side, prints both outcomes for every statement, marks divergences, and compares the final table contents. Exit code 1 means something diverged.Use it instead of piping SQL into the two shells: the tursodb shell cannot
ATTACH ':memory:' AS aux, so fuzzer reproductions with anauxschema only run correctly through the probe. Reading from stdin also works:echo "SELECT ~X'96';" | cargo run -q -p differential-fuzzer --bin differential_probe. -
Bisect by editing the script. Copy
minimized.sql, simplify one thing at a time (replace an expression with a constant, drop a column, drop a state line), and re-run the probe after each edit. The divergence marker tells you immediately whether the edit kept the bug. This loop usually ends at a one-line kernel you can hand toEXPLAINon both engines. -
Create a regression test in
.sqltest(preferred) or.rsfrom the kernel. Always load the Debugging skill for reference.
Understanding Failures
Oracle Failure Types
- Row set mismatch - Turso returned different rows than SQLite
- Turso errored but SQLite succeeded - Turso rejected valid SQL
- SQLite errored but Turso succeeded - Turso accepted invalid SQL
- Schema mismatch - Tables/columns differ after DDL
Warning (non-fatal)
- Unordered LIMIT mismatch - LIMIT without ORDER BY may return different valid rows
Key Source Files
Tracing
Set RUST_LOG for more detailed output:
