Идея тестирования грубой силой заключается в том, чтобы подвергать программу большой нагрузке и наблюдать за появлением ошибок. Обычно это означает, что код прогоняется многократно и, возможно, с большим количеством потоков. Если некоторая ошибка возникает только при определенном порядке планирования потоков, то чем дольше вы будете гонять код, тем больше будет вероятность ее проявления. Если тест прогоняется только один раз и при этом проходит, то появляется некоторая уверенность в его правильности. Если тест проходит десять раз подряд, то эта уверенность возрастает. Ну а если и после миллиарда прогонов ошибок не было, то доверие к коду становится еще сильнее.
Степень доверия к результатам, конечно, зависит от объема кода, проверяемого каждым тестом. Если тесты очень детальные, как, например, рассмотренные выше для потокобезопасной очереди, то такое тестирование грубой силой порождает высокую степень доверия к программе. С другой стороны, если тестированию подвергаются крупные участки кода, то количество возможных вариантов порядка планирования настолько велико, что и после миллиарда прогонов теста уверенность в правильности кода слабенькая.
Классический пример — тестирование многопоточного приложения на однопроцессорной машине. Поскольку все потоки исполняются единственным процессором, работа программы автоматически сериализуется, а разнообразные состояния гонки и проблемы перебрасывания кэша, которые могли бы наблюдаться в многопроцессорной системе, вообще невозможны. Но это еще не все — процессоры с разной архитектурой предоставляют различные средства синхронизации и упорядочения доступа к памяти. Например, в процессорах x86 и x86-64 атомарные операции загрузки одинаковы вне зависимости от того, помечены они признаком memory_order_relaxed
или memory_order_seq_cst
(см. раздел 5.3.3). Это означает, что код, написанный в предположении ослабленного упорядочения, может работать на машинах с архитектурой x86, но откажет на машине с системой команд, допускающей более точное управление порядком доступа к памяти, например, SPARC.
Если приложение должно быть переносимо на разные архитектуры, то и тестировать его следует на машинах, представляющих каждую возможную архитектуру. Поэтому я и включил архитектуру процессора в список факторов, которые нужно учитывать при тестировании (см. раздел 10.2.2).
Применяя тестирование грубой силой, важно всеми силами избегать условий, способных породить ложную уверенность. Для этого необходимо тщательно планировать тесты, уделяя внимание не только тому, какие участки кода подвергать тестированию, но также проектированию стенда (test harness) и выбору тестовой среды. Вы должны постараться протестировать как можно больше путей выполнения кода и взаимодействий между потоками. При этом еще необходимо знать,
Хотя метод грубой силы дает некоторую уверенность в правильности кода, гарантировать обнаружение всех ошибок он не может. Однако существует методика, которая
Название не вполне внятное, поэтому объясню, что я имею в виду. Идея в том, чтобы прогонять код под управлением специальной программы, которая