среда, 28 декабря 2011 г.

[prog.testing] Ознакомился с описанием тестирования SQLite

Вот здесь наткнулся на интересную статью How SQLite is Tested. Внушаить. Снимаю шляпу, есть чему поучиться и есть к чему стремиться.

Для тех, кто не в курсе: SQLite – это, пожалуй, самая распространенная встраиваемая в приложение легковесная реляционная СУБД, поддерживающая подмножество SQL.

Если коротко, то в тестировании SQLite используется три набора тестов (все цифры относятся к версии 3.7.8):

  1. TCL tests. Находящиеся в открытом доступе тесты, написанные с использованием языка TCL. В них реализовано 28278 тестов (test cases), но некоторые запускаются с разными параметрами, так что суммарно проверяется порядка 1.7 миллиона тестов.
  2. TH3. Это закрытый набор тестов, который нужно лицензировать отдельно. В нем реализовано 33595 различных теста. Этим тестовым набором обеспечивается 100% покрытие кода SQLite (для чего требуется прогон порядка 800 тысяч тестов). Всего же полный тестовый прогон перед релизом SQLite содержит порядка нескольких сотен миллионов тестов.
  3. 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

имя комментирует...

думаю, немеряно софта посыпется на таком тесте, и делать его очень легко