|
RRD является средством динамической верификации без запоминания состояний. Он предназначен, прежде всего, для тестирования многопоточных алгоритмов (алгоритмов синхронизации, многопоточных структур данных и так далее). Для пользователя работа с RRD выглядит примерно следующим образом. Вначале реализуется тестируемый алгоритм. Реализация может быть выражена через примитивы синхронизации C++09, POSIX threads (pthread), Win32 API, C#/.NET, Java. Однако необходимо использовать указанные API не напрямую, а через "обёртки", предоставляемые RRD; синтаксис практически идентичен, однако имеются некоторые отличия. Когда тестируемый алгоритм реализован, необходимо реализовать один или несколько юнит-тестов (unit test) для алгоритма. Далее можно запускать их на исполнение, при этом RRD позаботится об эффективном исполнении тестов, то есть будет проверено как можно больше различных чередований (interleaving) потоков. Во время исполнения каждого чередования RRD будет делать множество различных проверок корректности алгоритма, включая как пользовательские утверждения (asserts) и инварианты (invariants), так и базовые встроенные проверки - гонки (data races), обращения к освобожденной памяти, двойные освобождения памяти, утечки памяти, взаимные блокировки (deadlocks), активные блокировки (livelocks), некорректные использования API (например, рекурсивный захват нерекурсивного мьютекса), и другие. При обнаружении ошибки RRD выведет подробную историю исполнения, которая привела к ошибке. Имея на руках такую историю, локализация ошибки становится делом техники (история содержит такие детали как отклонения от последовательно согласованного (sequentially consistent) порядка, инстансы ABA проблемы, ложные пробуждения на условных переменных (condition variable) и т.д.).
|