The numbers come straight from SQLite's own testing documentation. As of version 3.42.0, the SQLite library is about 155.8 KSLOC of C code. The project maintains 590 times as much test code and test scripts — 92,053.1 KSLOC. For every line that ships in the most widely deployed database engine on Earth, there are roughly 590 lines whose only job is to prove that line correct.
Here's the part that surprises people: the test harness that actually gates every release — the one that achieves 100% branch coverage — is proprietary. You can't download it. And that single fact explains SQLite's famously unusual policy of being "open-source, not open-contribution" better than any licensing philosophy does.
Four harnesses, one library
SQLite doesn't have a test suite. It has four independent ones, each attacking the library from a different direction.
The TCL tests are the original, public-domain suite that ships with the source tree: 1,390 script files totaling 23.2 MB, containing 51,445 distinct test cases. Most cases are parameterized, so a full run executes millions of individual tests. This is the suite you run when you build SQLite yourself — and there's a veryquick subset of about 304.7 thousand cases that runs in minutes instead of hours, which is what most development iterations use.
TH3 is the heavyweight. It's a proprietary test program generator, written in C, that emits self-contained C programs designed to link against the library under test and run on embedded platforms that lack the support infrastructure of a workstation. A full-coverage run executes about 2.4 million test instances; the soak test before each release runs about 248.5 million. TH3 exists because of aviation: when avionics manufacturers expressed interest in SQLite, the developers designed TH3 to support the rigorous testing standards of DO-178B, the safety certification standard for airborne software. Every SQLite release since 3.6.17 (2009) has been tested to that standard, on Linux, Windows, WinRT, Mac, and OpenBSD.
SQL Logic Test answers a different question: not "does the code do what we intended" but "does SQLite agree with everyone else?" It runs 7.2 million queries against 1.12 GB of test data and compares SQLite's answers with PostgreSQL, MySQL, Microsoft SQL Server, and Oracle 10g.
dbsqlfuzz is a proprietary fuzzer built on LLVM's libFuzzer with a custom mutator and 336 seed files. Unlike earlier fuzzers that mutated either the SQL text or the database file, dbsqlfuzz mutates both at once — and it runs about one billion test mutations per day.
What 100% MC/DC actually buys you
TH3's headline claim is 100% branch test coverage — and, stronger, 100% MC/DC (Modified Condition/Decision Coverage) — over the SQLite core, including the unix VFS, as measured by gcov. (Extensions like FTS3 and RTree are excluded.)
Branch coverage means every branch instruction has been taken in both directions. MC/DC goes further: every condition within a compound decision must be shown to independently affect the outcome. If you have if (a && b), MC/DC requires tests demonstrating that flipping a alone changes the result, and that flipping b alone changes the result. It's the coverage criterion DO-178B demands for the most safety-critical avionics software, and it's brutally expensive to achieve — which is why almost nobody outside aerospace does it.
Full coverage creates a dilemma most codebases never confront: what do you do with defensive code? A well-written C program contains conditionals that in practice are always true or always false — belt-and-suspenders checks that can never fire. Those branches are untestable by definition, so they'd break the 100% figure. SQLite's answer is a pair of macros, ALWAYS() and NEVER(), that wrap such conditions. In release builds they're pass-throughs — the defensive check still runs. In coverage builds they're excluded from measurement. The macros function as machine-checked comments: this branch is defensive, and if it ever fires in testing, that itself is a bug.
Fuzzing and MC/DC pull in opposite directions
The testing document contains one of the sharpest observations I've seen about test methodology, and it's worth quoting because it's counterintuitive:
Fuzz testing and 100% MC/DC testing are in tension with one another. That is to say, code tested to 100% MC/DC will tend to be more vulnerable to problems found by fuzzing and code that performs well during fuzz testing will tend to have (much) less than 100% MC/DC.
The mechanism: MC/DC discourages defensive code, because unreachable branches are uncoverable branches. But defensive code is exactly what saves you when a fuzzer wanders into a state no human anticipated. SQLite's conclusion is that MC/DC builds code that's robust during normal use, while fuzzing builds code that's robust against malicious use — so you need both, and you need the ALWAYS()/NEVER() machinery to keep them from fighting.
Beyond fuzzing, the anomaly tests attack the failure paths directly. OOM tests run each operation in a loop with an instrumented malloc() that fails on the Nth allocation, incrementing N until the operation completes — so every allocation site gets to fail. I/O error tests do the same for the filesystem, then run PRAGMA integrity_check to prove no corruption leaked through. Crash tests simulate power failure with an alternative VFS that reorders and corrupts unsynchronized writes, verifying that every transaction either commits completely or rolls back completely.
And because 100% branch coverage still doesn't prove the tests check anything, SQLite also does mutation testing: a script compiles the source to assembly, flips branch instructions one at a time, and verifies the test suite notices. A mutation that survives means either dead code that can be deleted or a feature the suite isn't really verifying.
There's a runtime layer too: 6,754 assert() statements verify preconditions, postconditions, and loop invariants. They're disabled by default in release builds — with asserts on, the engine runs about three times slower.
Why this makes SQLite closed to contributions
SQLite's copyright page is blunt: "SQLite is open-source, meaning that you can make as many copies of it as you want and do whatever you want with those copies, without limitation. But SQLite is not open-contribution." Patches are only accepted from people who have signed an affidavit dedicating their contribution to the public domain, and the docs warn: "please do not be offended if we rewrite your patch from scratch."
The usual explanation is legal — keeping the public domain dedication clean. That's true, but the testing story reveals a structural reason that would exist even if the licensing issue didn't. The bar for merging a change isn't "the TCL tests pass." It's 100% branch and MC/DC coverage under TH3, a couple hundred million soak-test executions, a billion fuzz mutations a day, and a release checklist of roughly 200 items (inspired, the developers note, by The Checklist Manifesto). An outside contributor can't run most of that pipeline, because TH3 and dbsqlfuzz are proprietary — TH3 licenses are part of how the project funds itself. A drive-by pull request can't demonstrate it meets the bar; only the core team can carry a change through the machinery that makes SQLite trustworthy enough to fly in avionics and ship in every phone.
That's the real lesson for the rest of us, and it scales down. The 590:1 ratio isn't the point — the point is that SQLite treats its test infrastructure as the product. The library is 155.8 KSLOC that anyone could fork tomorrow, public domain, no strings. Nobody does, because the fork would be worthless without the 92 million lines that prove it works. Your moat is rarely the code.
