- SQLite एक कड़े automated testing framework के जरिए उच्च विश्वसनीयता और मजबूती बनाए रखता है, और इसमें कोड से 590 गुना अधिक test code मौजूद है
- चार स्वतंत्र test harnesses (TCL, TH3, SQL Logic Test, dbsqlfuzz) मुख्य लाइब्रेरी को सत्यापित करते हैं, और सैकड़ों मिलियन टेस्ट चलाते हैं
- असामान्य स्थिति परीक्षण (OOM, I/O errors, crash simulation) और fuzz testing के जरिए यह पुष्टि की जाती है कि यह असामान्य input और system failure की स्थिति में भी स्थिर रूप से काम करता है
- 100% branch और MC/DC coverage, resource leak detection, Valgrind·static analysis·checklist जैसी बहु-स्तरीय सत्यापन प्रक्रियाएं बनाए रखी जाती हैं
- इस तरह की व्यवस्थित testing के कारण SQLite को commercial DB स्तर की reliability और quality वाले open source database के रूप में आंका जाता है
1. अवलोकन
- SQLite की विश्वसनीयता और मजबूती एक बेहद सूक्ष्म testing process से आती है
- version 3.42.0 के अनुसार, SQLite में लगभग 155.8 KSLOC का C code और 92053.1 KSLOC का test code शामिल है
- testing system में 4 independent harnesses, 100% branch coverage, और मिलियन-स्तर के test cases शामिल हैं
- इनमें OOM, I/O errors, crash, fuzz, boundary values, regression, abnormal DB files, optimization-disabled testing आदि जैसी कई श्रेणियां शामिल हैं
2. Test harnesses
- TCL Tests
- SQLite development के दौरान मुख्य रूप से उपयोग होने वाला public test set
- 27.2 KSLOC के C code और 1390 script files (23.2MB) से बना है
- लगभग 50 हजार test cases, और parameterization के कारण पूरे run में कई मिलियन tests चलाए जाते हैं
- TH3
- commercial C-based test set, जो 100% branch और MC/DC coverage हासिल करता है
- embedded environment में भी चलता है, और इसमें 1055.4 KSLOC तथा लगभग 50 हजार cases शामिल हैं
- full coverage test में लगभग 2.4 million tests, और release से पहले 248 million soak tests चलाए जाते हैं
- SQL Logic Test (SLT)
- SQLite के परिणामों की PostgreSQL, MySQL, SQL Server, Oracle 10g से तुलना करता है
- 7.2 million queries और 1.12GB data से बना है
- dbsqlfuzz
- SQL और database files दोनों को एक साथ mutate करने वाला libFuzzer-based fuzzer
- प्रतिदिन लगभग 1 billion mutation tests चलाता है, और malicious input के प्रति robustness को जांचता है
- अतिरिक्त tools
- speedtest1.c, mptester.c, threadtest3.c, fuzzershell.c, jfuzz आदि
- release तभी संभव है जब सभी tests multi-platform और compile settings में pass हों
3. असामान्य स्थिति परीक्षण
- OOM testing
- malloc() failure को simulate करके यह जांचा जाता है कि memory shortage पर recovery सही ढंग से होती है या नहीं
- failure point counter को बढ़ाते हुए इसे बार-बार चलाया जाता है
- I/O error testing
- virtual file system (VFS) का उपयोग करके disk errors simulate किए जाते हैं
- error के बाद
PRAGMA integrity_check से data corruption की जांच की जाती है
- Crash testing
- power loss और OS crash जैसी स्थितियों को simulate किया जाता है
- TCL harness child process आधारित है, जबकि TH3 memory-based VFS का उपयोग करता है
- यह सत्यापित किया जाता है कि transaction या तो पूरी तरह rollback हो या पूरी तरह complete
- Composite failure testing
- crash के बाद OOM या I/O errors लगातार होने वाली स्थिति तक की जांच की जाती है
4. Fuzz testing
- SQL Fuzz
- syntactically valid लेकिन असामान्य SQL बनाकर SQLite की प्रतिक्रिया को परखा जाता है
- American Fuzzy Lop (AFL)
- 2014 में अपनाया गया profile-based fuzzer, जो नए control paths खोजता है
- इसने SQLite में कई assert failures, crashes, और wrong results खोजे
- Google OSS Fuzz
- 2016 से Google infrastructure पर automated fuzzing कर रहा है
- नए commits में intermittent issues पकड़ता है
- dbsqlfuzz / jfuzz
- 2018 के बाद internal fuzzers के रूप में अपनाए गए, जो SQL और DB files दोनों को साथ mutate करते हैं
- प्रतिदिन 500 million से अधिक tests, और external fuzzers से आने वाली bug reports लगभग समाप्त हो गईं
- 2024 से jfuzz ने JSONB input validation भी जोड़ी
- Third-party fuzzers और fuzzcheck
- बाहरी researchers (जैसे Manuel Rigger) ने wrong result computation के कई उदाहरण खोजे
- fuzzcheck utility पुराने fuzz cases में से ‘interesting’ हजारों मामलों को फिर से validate करती है
- MC/DC और fuzz testing के बीच तनाव
- MC/DC defensive code को न्यूनतम रखने की ओर झुकता है, जबकि fuzzing में defensive code की जरूरत होती है
- SQLite दोनों approaches को साथ चलाकर normal और malicious input दोनों पर robust code बनाए रखता है
5. Regression testing
- रिपोर्ट किए गए bug को fix करने के बाद उसे हमेशा नए test case के रूप में जोड़ा जाता है
- उद्देश्य पुराने bug के दोबारा आने से रोकना है
6. स्वचालित resource leak detection
- TCL और TH3 harnesses memory, file, thread, और mutex leaks की स्वचालित निगरानी करते हैं
- OOM और I/O errors के बाद भी memory leak नहीं होना चाहिए
7. Test coverage
- SQLite core ने TH3 के आधार पर 100% branch coverage हासिल की है
- FTS3, RTree जैसी extensions इसमें शामिल नहीं हैं
- Statement vs Branch Coverage
- branch coverage, statement coverage से अधिक कठोर है और हर conditional branch को दोनों दिशाओं में validate करता है
- Defensive code coverage
- ALWAYS(), NEVER() macros से defensive conditions को स्पष्ट किया जाता है
- तीन अलग definitions के रूपों में tests दोहराकर consistency validate की जाती है
- Boundary value और boolean vector testing
- testcase() macro से condition के positive और negative दोनों परिणाम verify किए जाते हैं
- 1184 testcase() उपयोग में हैं
- MC/DC हासिल करना
- testcase() macro के जरिए हर condition के independent effect की जांच की जाती है
- gcov-based measurement
-fprofile-arcs -ftest-coverage options से coverage मापी जाती है
- results की तुलना करके compiler bugs या undefined behavior का पता लगाया जाता है
- Mutation Testing
- branch instructions को बदलकर देखा जाता है कि test system इसे detect करता है या नहीं
- optimization branches (
/*OPTIMIZATION-IF-TRUE*/) को exception के रूप में संभाला जाता है
- पूर्ण coverage का अनुभव
- सभी branches के test होने से code changes के side effects कम होते हैं
- maintenance cost अधिक है, लेकिन व्यापक रूप से वितरित infrastructure library होने के कारण यह उचित है
8. Dynamic analysis
- Assert()
- 6754 assert statements preconditions, postconditions, और loop invariants को validate करते हैं
- केवल
SQLITE_DEBUG build में सक्रिय
- Valgrind
- memory errors, stack overflow, और uninitialized memory access detect करता है
- release से पहले veryquick और TH3 tests को Valgrind के साथ चलाया जाता है
- Memsys2
SQLITE_MEMDEBUG build में memory error monitoring के लिए wrapper insert किया जाता है
- Valgrind की तुलना में यह तेज़ी से repeated validation कर सकता है
- Mutex Asserts
sqlite3_mutex_held() आदि से multithread synchronization validate किया जाता है
- Journal Tests
- यह जांचते हैं कि rollback journal DB से पहले लिखा गया है या नहीं, ताकि transaction atomicity सुनिश्चित हो
- Undefined Behavior Checks
-ftrapv, -fsanitize=undefined, /RTC1 आदि से undefined behavior detect किया जाता है
- 32/64-bit, endian, और विभिन्न CPU architectures पर इसे बार-बार चलाया जाता है
9. Optimization-disabled testing
sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS) से optimizations बंद किए जाते हैं
- optimization हो या न हो, result समान होना चाहिए
- कुछ performance measurement tests अपवाद हैं
10. Checklist
- release से पहले लगभग 200 items की manual checklist verify की जाती है
- कुछ items कुछ सेकंड लेते हैं, कुछ में कई घंटे लगते हैं
- issue मिलने पर तुरंत नया item जोड़ा जाता है, और system लगातार सुधरता है
11. Static analysis
- GCC, Clang, MSVC पर बिना warnings के compile होता है
- Clang Static Analyzer में भी कोई valid warning नहीं मिलती
- static analysis का वास्तविक bug detection प्रभाव सीमित है
12. सारांश
- open source होने के बावजूद SQLite commercial स्तर की quality और low defect rate बनाए रखता है
- इसकी मुख्य वजह कठोर testing और code design है
- हर release ऊपर बताए गए process से गुजरती है, इसलिए इसे mission-critical environments में भरोसेमंद DB engine के रूप में उपलब्ध कराया जाता है
4 टिप्पणियां
साथ में पढ़ने लायक लेख: SQLite की अनकही कहानी
यह SQLite के डेवलपर Richard Hipp के इंटरव्यू का सारांश है।
बताया गया है कि SQLite के डेवलपर्स ने Rockwell Collins में काम करने के दौरान Do-178 के बारे में जाना और फिर इस प्रक्रिया का पालन करना शुरू किया। उनमें से एक है 100% MC/DC हासिल करना।
Do-178 वास्तव में एक उपयोगी गाइडलाइन है, इसलिए मैं सिफारिश करता हूँ कि हर डेवलपर इसे पढ़े।
क्या यह है? https://alm.parasoft.com/hubfs/…
आपने जो लिंक दिया है, वह शायद Do-178 ट्रेनिंग मटेरियल लगता है.
मूल दस्तावेज़ इस लिंक पर देख सकते हैं.
https://studylib.net/doc/27132454/rtca-do-178b
Hacker News की राय
करीब 10 साल पहले SQLite के मेंटेनर ने OSCON में टेस्टिंग प्रैक्टिसेज़ पर बात की थी
सबसे प्रभावशाली बात checklist की ताकत लगी। वही टूल जो पायलट हर उड़ान से पहले इस्तेमाल करते हैं
उन्होंने Doctors Without Borders का एक उदाहरण भी बताया, जहाँ मेडिकल स्टाफ एक-दूसरे के नाम तक नहीं जानते थे और भाषा भी अलग थी, इसलिए सर्जरी के नतीजे खराब थे
समाधान सरल था — सर्जरी से पहले एक checklist बनाई गई, जिसमें हर व्यक्ति अपना नाम और भूमिका बताता था। इस छोटे-से ritual ने तकनीक नहीं बल्कि बेहतर communication के जरिए survival rate बढ़ा दिया
संबंधित सामग्री: SQLite checklist उदाहरण
अच्छी checklist और खराब checklist में फर्क पर और चर्चा होनी चाहिए। गणित के सुंदर सूत्र की तरह, यह सरल दिखता है लेकिन ढूंढना मुश्किल लगता है
खासकर मैंने अमेरिकी सेना का FM22-100 दस्तावेज़ कई बार पढ़ा है, और वह हैरान करने वाली हद तक आधुनिक और प्रेरक है
FM22-100 दस्तावेज़ देखें
किताब लिंक
मैं testing और CI के अलावा Markdown में बनी deployment checklist भी follow करता हूँ। मैं परिणाम सहेजता भी नहीं, बस चरण-दर-चरण उसे करता हूँ
इतना सरल काम दूसरे लोग क्यों नहीं करते, समझ नहीं आता
अगर MSF के इस मामले पर कोई आधिकारिक पेज हो, तो मैं ज़रूर देखना चाहूँगा। Google से मुझे नहीं मिला
SQLite की testing पर पुरानी चर्चाओं का एक संग्रह है
2009~2024 HN thread सूची
लगता है repost लगभग हर साल होता रहता है
SQLite जैसे software को इतनी बारीकी से तराशने की प्रक्रिया देखकर ईर्ष्या भी होती है और विस्मय भी
यह craftsmanship से भरा काम है
समय के साथ quality standard ऊँचे हो जाते हैं, और उसी मेहनत से बड़ा reward मिलता है
आपने जिस हिस्से को छुआ, उसे थोड़ा भी साफ़-सुथरा छोड़ने वाले व्यक्ति को कोई नापसंद नहीं करता
SQLite वाकई शानदार software है। इसकी आधिकारिक वेबसाइट भी marketing की जगह information-centric है, इसलिए अच्छी लगती है
बस हाल में HN पर उसकी साइट के पेज एक-एक करके आना दिलचस्प है
ऐसे लिंक इकट्ठा किए जाएँ तो मज़ेदार होगा
यह दिलचस्प है कि SQLite public software है लेकिन private tests इस्तेमाल करता है
अब जाकर समझ आया कि open source project के पास closed testing भी हो सकती है
यह मॉडल open-core जैसा कोई नया business model भी बन सकता है
उदाहरण: railgunlabs/unicorn license
SQLite की 100% branch coverage परियोजना जितनी ही प्रभावशाली है
इसे लगातार बनाए रखना खास तौर पर कमाल की बात है
tests का private होना दिलचस्प है। LLM-आधारित coding के आगे बढ़ने के साथ, हम ऐसे दौर में पहुँच रहे हैं जहाँ tests implementation से ज्यादा महत्वपूर्ण हो सकते हैं
हाल में simonw द्वारा justHTML engine को Python से JS में लगभग अपने-आप बदलने का उदाहरण देखकर SQLite की testing strategy याद आई
हाल में SQLite और DuckDB के बीच compatibility को लेकर मैंने LLM से चर्चा की, और concurrency handling के मामले में SQLite बेहतर है, इस निष्कर्ष पर पहुँचा
SQLite के testing दस्तावेज़ में performance regression के बारे में कम चर्चा देखकर हैरानी हुई
correctness महत्वपूर्ण है, लेकिन कुछ query paths पर performance में गिरावट भी घातक हो सकती है
सोचता हूँ क्या कोई ऐसा project है जो इसे अपनी मुख्य mission मानता हो
SQLite की स्थिरता देखकर मैं यह और जानना चाहता था कि anomaly testing कैसे की गई
लेकिन लेख में इसका लगभग कोई ज़िक्र नहीं था। फिर भी SQLite हर तरह के डिवाइस में इस्तेमाल होने वाले सबसे robust software में से एक है