
2025/12/18 3:15
How SQLite is tested
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
SQLiteのテストインフラは網羅的で、コードベース全体にわたって完全な分岐カバレッジを実現しています。
プロジェクトには約155.8 KSLOCのCソースがありますが、テストコードは92 M KSLOC以上――約590倍の量――で、すべての行が実行されることを保証しています。4つの独立したハーネスがカバレッジを提供します:
• TCL(27.2 KSLOC、1,390個のスクリプトファイル)で51,445件の異なるケースと数百万回の実行があります;
• TH3(1,055.4 KSLOC、約76.9 MBのバイナリ)で50,362件の異なるケース、完全カバレッジに必要な2.4 Mインスタンス、および約248.5 Mテストを実行するソークテストがあります;
• SQL Logic Test (SLT) はSQLiteとPostgreSQL、MySQL、MS SQL Server、Oracle 10gを比較し、7.2 Mクエリと1.12 GBのデータで検証します;
• dbsqlfuzz(libFuzzerベース)はSQLとデータベースファイルの両方を変異させ、約336個のシードファイルから16コアで1日あたり約500 Mテストを提供します。
追加の軽量ハーネスには、speedtest1.c、mptester.c、threadtest3.c、およびJSONBファズラfuzzershell.cが含まれます。jfuzz
異常テストではメモリ不足、I/O障害、クラッシュ/電源損失、およびカスタムmalloc/VFSフックを使用した複合故障をシミュレートし、各障害後に整合性チェックが実行されます。
ファズリングの歴史はAFL(2014‑2019)からOSS Fuzz(2016年以降)、その後dbsqlfuzz(2018年末)とjfuzz(2024年1月)へ進化しました。スクリプトは毎回ビルド時に興味深いケースを再実行し、新しいバグが自動的にリグレッションテストとして生成されることを保証します。fuzzcheck
リソースリーク検出はTCL/TH3ハーネスに組み込まれており、メモリリーク、ファイルディスクリプタ枯渇、および不要なスレッドが自動的に監視されます。
カバレッジはを使用して100 %の分岐カバレッジと変異テストで達成され、マクロ(gcov、ALWAYS、NEVER)がMC/DCを強制し、コメント(testcase)は偽陽性を防ぎます。/*OPTIMIZATION‑IF‑TRUE/FALSE*/
結果として、継続的に拡張される高い信頼性のテストスイートが実現し、ユーザーにSQLiteの安定性への確信を提供し、セキュリティ脆弱性から保護し、オープンソースデータベース品質保証のベンチマークとなります。
本文
SQLiteのテスト方法
1. はじめに
SQLite の信頼性と堅牢性は、徹底かつ慎重なテストによって実現されています。
- バージョン 3.42.0(2023‑05‑16)時点で、SQLite ライブラリは約 155.8 KSLOC の C コードから構成されています。
- プロジェクト全体では、テストコードとスクリプトが 590 倍に多く – 92,053.1 KSLOC あります。
1.1 エグゼクティブサマリー
| 機能 | 説明 |
|---|---|
| 独立したテストハーネスを4種類 | 配備済み構成で100 %の分岐テストカバレッジ |
| 数百万件のテストケース | メモリ不足テスト、I/O エラー テスト、クラッシュ・電源切断テスト、ファズテスト、境界値テスト、最適化無効テスト、回帰テスト、破損データベーステスト |
と実行時チェックを徹底的に利用 | |
| Valgrind 分析・未定義動作チェック・チェックリスト |
2. テストハーネス
SQLite コアライブラリのテストには、4つの独立したテストハーネスが使用されています。
2.1 TCL Tests
- 元々 Tcl で書かれたテストです。
- Tcl インタフェースに関する C コードは 27.2 KSLOC、スクリプトファイルは 1390 件(23.2 MB)。
- 51,445 のユニークなテストケースがあり、多くはパラメータ化されているため、完全実行時には数百万件の個別テストが生成されます。
2.2 TH3
- C ベースの独自テストで、100 % 分岐・MC/DC カバレッジを達成します。
- 約 76.9 MB / 1055.4 KSLOC;50,362 のユニークケース(≈ 2.4 M インスタンス)があります。
- リリース前のソークテストでは、約 248.5 M テスト が実行されます。
2.3 SQL Logic Test (SLT)
- SQLite と他エンジンに対して大量の SQL 文を実行し比較します。
- PostgreSQL、MySQL、MS SQL Server、Oracle 10g との比較を行います。
- 7.2 M クエリ、1.12 GB のテストデータがあります。
2.4 dbsqlfuzz
- SQL とデータベースファイルの両方を同時に変異させる独自ファズテスターです。
- LLVM libFuzzer をベースにカスタムミューテーターを使用しています。
- 336 のシードファイル、1 日あたり約 10億回 のミューテーションが行われます。
2.5 その他専門テスト
– パフォーマンス推定speedtest1.c
– マルチプロセス ストレステストmptester.c
– マルチスレッド ストレステストthreadtest3.c
– 一部ファズテストを実行fuzzershell.c
– libFuzzer JSONB ファザーjfuzz
すべてのテストは、複数プラットフォームとコンパイル時設定で成功しなければリリースできません。
チェックイン前に開発者は veryquick サブセット(約304.7 k 件)を数分で実行します。
3. 異常テスト
3.1 メモリ不足 (OOM)
をmalloc()
で置き換え、OOM をシミュレート。sqlite3_config(SQLITE_CONFIG_MALLOC, …)- インストゥルメンテーション付き malloc は一度だけ失敗させるか継続的に失敗させることが可能。
- 失敗ポイントを増やしながら操作が OOM シミュレーションなしで完了するまで繰り返します。
3.2 I/O エラー
- N 回の操作後に I/O エラーを発生させる VFS を挿入。
- 単一失敗または継続的失敗の二つのモードがあります。
- シミュレーション停止後、
を実行します。PRAGMA integrity_check
3.3 クラッシュテスト
- 特殊 VFS(Tcl の子プロセス、TH3 のインメモリスナップショット)でクラッシュをシミュレート。
- 書き込み中にランダムにクラッシュし、
でロールバックまたは完了を検証。PRAGMA integrity_check - スナップショットやランダム損傷を変えて繰り返します。
3.4 複合失敗テスト
- 前回のクラッシュからリカバリ中に I/O エラーなど複数失敗を重ねてテストします。
4. ファズテスト
| ファザー | 説明 |
|---|---|
| SQL Fuzz | 構文的には正しいが意味不明な SQL を生成し、エラーまたは妥当な結果を期待する。 |
| AFL | プロファイル指向ファザー(3.8.10–3.29.0 で使用)。 |
| OSS Fuzz | Google の AFL スタイルファザーでインフラ上自動実行。 |
| dbsqlfuzz & jfuzz | SQL、データベース、JSONB 入力を変異させる独自 libFuzzer ファザー。 |
| その他サードパーティファザー | Manuel Rigger などの独立ファザーが誤答を発見。 |
4.1 Fuzzcheck ハーネス
- 全ファザーから選ばれた「興味深い」ケースを再実行。
のたびに数千件のケースを実行します。make test
4.2 ファズと MC/DC の緊張関係
- 完全 MC/DC は防御的コードを抑制するが、ファズはそれを好む。
- SQLite は両方を維持:100 % MC/DC + 広範なファズサイクル。
5. 回帰テスト
新規バグは TCL または TH3 の回帰スイートに追加され、修正済みとして扱われる前に再導入が防止されます。
6. 自動リソースリーク検出
両ハーネスはシステムリソースを追跡し、メモリリークは即座に失敗します。SQLite は OOM や I/O エラー後でもメモリリークを起こさない。
7. テストカバレッジ
- 100 % 分岐カバレッジ(TH3、デフォルト設定で gcov による測定)。
- ステートメント vs. 分岐カバレッジを例とともに解説。
/ALWAYS()
マクロとNEVER()
で境界チェックを実装。testcase()- ミューテーションテスト:分岐を無条件ジャンプまたは NOP に置き換えて出力への影響を確認。最適化は
のコメントで除外。/*OPTIMIZATION‑IF‑TRUE*/
8. 動的解析
| ツール | 用途 |
|---|---|
| assert() | 6,754 個のアサーション(デフォルトでは により無効化)。 |
| Valgrind | メモリリーク、オーバーラン、未初期化読み取りなどを検出。veryquick と TH3 をリリース前に実行。 |
| memsys2 | 時の代替アロケータ(Valgrind より高速)。 |
| Mutex Asserts | / で正しいミューテックス使用を検証。 |
| Journal Tests | VFS がデータベースとロールバックジャーナル間の I/O を監視。 |
| Undefined Behavior Checks | 、、 でコンパイルし、複数アーキテクチャで実行。意図的な UB テスト(例:)も含む。 |
9. 最適化無効テスト
最適化を有効にした状態と
SQLITE_TESTCTRL_OPTIMIZATIONS で無効化した状態の両方でフルスイートを実行し、出力が同一であることを確認。
10. チェックリスト
- オンラインチェックリスト(約200項目)を手動でリリース前に検証。
- 人間の監視により自動テストでは捉えきれない微妙な問題も捕捉。
11. 静的解析
- GCC、Clang (
) と MSVC で警告なしでコンパイル。-Wall -Wextra
は有効な警告を出さず、稀にバグを検出。scan-build- 実際には警告抑制の過程でバグが導入されるケースが多い。
12. 要約
SQLite の信頼性は、綿密なコード設計と徹底したテスト によって支えられています:
- TCL、TH3、SLT、dbsqlfuzz といった複数の独立ハーネス
- 異常・ファズ・回帰・リソースリークテストを網羅
- 100 % 分岐カバレッジ、ミューテーションテスト、動的解析、静的チェック
- 継続的に人間が確認するチェックリスト
この厳格なプロセスにより、SQLite はミッション・クリティカルアプリケーションでの信頼性を維持しています。