Вот здесь наткнулся на интересную статью How SQLite is Tested. Внушаить. Снимаю шляпу, есть чему поучиться и есть к чему стремиться.
Для тех, кто не в курсе: SQLite – это, пожалуй, самая распространенная встраиваемая в приложение легковесная реляционная СУБД, поддерживающая подмножество SQL.
Если коротко, то в тестировании SQLite используется три набора тестов (все цифры относятся к версии 3.7.8):
- TCL tests. Находящиеся в открытом доступе тесты, написанные с использованием языка TCL. В них реализовано 28278 тестов (test cases), но некоторые запускаются с разными параметрами, так что суммарно проверяется порядка 1.7 миллиона тестов.
- TH3. Это закрытый набор тестов, который нужно лицензировать отдельно. В нем реализовано 33595 различных теста. Этим тестовым набором обеспечивается 100% покрытие кода SQLite (для чего требуется прогон порядка 800 тысяч тестов). Всего же полный тестовый прогон перед релизом SQLite содержит порядка нескольких сотен миллионов тестов.
- SQL Logic Test. Прогоняет туеву хучу различных SQL-ных запросов как через SQLite, так и через другие БД для того, чтобы убедиться, что получаются одинаковые результаты обработки запросов. Всего при тестировании выполняется порядка 7.2 миллионов запросов.
Все это дело используется для проверки:
1. Аномальных режимов работы:
- нехватка памяти. Для симуляции чего SQLite подсовывается специальный менеджер памяти, который специально возвращает 0 при обращении к функции malloc (однократно или последовательно, в зависимости от сценария теста);
- наличие ошибок ввода-вывода. Для симуляции чего SQLite использует специальную реализацию интерфейса Virtual File System. Эта реализация поддерживает возможность имитации различных ошибок ввода-вывода по различным сценариям;
- крах приложения. Здесь посредством еще одной реализации Virtual File System проверяется корректность содержимого файлов БД при имитации краха приложений на разных стадиях работы с данными;
- сочетания различных видов сбоев – например, нехватка памяти при попытке восстановления после ошибки ввода-вывода.
2. Некорректных данные:
- синтаксически корректные, но семантически неправильные SQL-выражения (во время этого тестирования прогоняется порядка 102.1 тысяч разнообразных SQL выражений);
- запорченные файлы БД. Берутся нормальные файлы БД, в которых меняется часть байт и испорченные таким образом БД скармливаются SQLite;
- граничные условия. Проверяется поведение SQLite когда ей пытаются задавать значения, превышающие максимально допустимые. Например, создаются таблицы со слишком большим количеством столбцов и т.д.
3. Отсутствия регрессии при разработке SQLite. На каждый выявленный баг заводится тест, который включается затем в набор регрессионных тестов для проверки того, что он не всплывет в будущих версиях.
4. Отсутствия утечек ресурсов. Прогоны тестов построены таким образом, чтобы обнаруживать утечку памяти, файловых дескрипторов и пр.
Так же активно используются средства динамического анализа:
- assert-ы, которые можно включить посредством символа препроцессора SQLITE_DEBUG;
- valgrind, который ловит кучу проблем, связанных с памятью, но за счет серьезного снижения скорости работы. Поэтому под valgrind-ом прогоняется только ограниченный набор тестов;
- memsys2, который контролирует работу с памятью (хуже, чем valgrind, зато намного быстрее);
- специальные средства для контроля за тем, что мутексы при работе в многопоточной среде захватываются и освобождаются должным образом;
- journal test VFS, специальная реализация интерфейса Virtual File System, которая контролирует, что все данные, которые SQLite пишет в БД, сначала проходят через rollback journal (т.е. сначала попадают в журнал транзакции);
- отсутствия переполнения signed int-ов, для чего делаются прогоны кода, скомпилированного посредством GCC с опцией –ftrapv.
Так же SQLite проверяется на получение одинаковых результатов работы с данными в БД при включенной и выключенной оптимизацией запросов.
Еще раз повторюсь – внушаить. Такое впечатление, что в тестирование SQLite вложено в разы больше труда, чем в собственно ядро SQLite. Что подтверждается цифрами: объем кода SQLite – 77.6 KSLOC, объем тестов – 91392.4 KSLOC (в 1177 раз больше).
Если же кого-то информация заинтересовала, то настоятельно рекомендую обратиться к первоисточнику и приведенным там ссылкам.
2 комментария:
действительно внушает
а еще мне понравилась идея случайно возвращать из malloc-а 0
думаю, немеряно софта посыпется на таком тесте, и делать его очень легко
Отправить комментарий