Модульное тестирование, взаимоблокировки и условия гонки

StackOverflow https://stackoverflow.com/questions/176636

Вопрос

Любые предложения о том, как написать повторяемые модульные тесты для кода, который может быть подвержен взаимоблокировкам и условиям гонки?

Прямо сейчас я склоняюсь к тому, чтобы пропустить модульные тесты и сосредоточиться на стресс-тестах.Проблема в том, что вы можете запустить стресс-тест 5 раз и увидеть пять разных результатов.

Редактировать:Я знаю, что это, вероятно, просто мечта, но если бы существовал способ управлять отдельными потоками и заставлять их выполнять по одной инструкции за раз, тогда я мог бы чего-то добиться.

Это было полезно?

Решение

Посмотрите на TypeMock Racer (он находится в бета-версии)

изменить: на самом деле Альфа

http://www.typemock.com/Typemock_software_development_tools.html

Другие советы

Обычно можно заставить предвиденный условия гонки и взаимоблокировки с помощью таких вещей, как ManualResetEvent, чтобы перевести каждый поток в ожидаемое состояние перед его выпуском, т. е.пусть поток A установит блокировку и будет ждать сигнала...получите поток B для запроса блокировки и т.д...

Однако обычно вы можете написать такой тест для расследования предполагаемой ошибки, чтобы доказать, когда она исправлена и что она не всплывает вновь.Как правило, вы разрабатываете с учетом условий гонки (но тестируете их настолько хорошо, насколько это прагматично).

Я не думаю, что поиск условий гонки действительно относится к области юнит-тестирования. Более или менее по определению, единственный способ проверить условия гонки - это псевдослучайно. Если вы не готовы формально доказать правильность своей стратегии блокировки, вам придется провести стресс-тестирование.

Вам все еще нужно написать модульные тесты, чтобы проверить правильность алгоритмов, а не стратегию блокировки.

При стресс-тестировании многопоточного кода вам нужно протестировать в условиях, когда у вас один ЦП на поток, где у вас несколько потоков, совместно использующих ЦП, и где у вас больше ЦП, чем потоков (если это возможно).

Вы можете написать класс блокировки, который обнаруживает потенциальные взаимоблокировки, рассматривая порядок операций блокировки. Мы делаем это, имея контекст потока, в котором регистрируются все блокировки, когда они получены (можно сделать опцию только DEBUG).

Идея состоит в том, чтобы создать граф, в котором узлы представляют блокировки, а направленный край между A и B означает «блокировка A удерживалась, когда блокировка B была получена». Дайте вашей программе работать с нормальной нагрузкой, затем проверьте циклы на графике. Цикл означает, что существует вероятность тупиковой ситуации, даже если ваш код не попал в нее.

Не могу придумать хороший автоматизированный способ, но ближе всего я подошел к написанию модульного теста, который бы «выставлял» тупик, используя точки останова в дополнение к модульному тесту. Я просто добавил несколько инструкций о том, где добавить точку останова. Прилагаются некоторые ручные усилия, но с их помощью вы всегда можете раскрыть свое расписание потоков в худшем случае.

Возможно, кто-то придумал хороший способ автоматизировать этот тип функциональности? Я мог бы представить себе автоматический запуск отладчика, разрыв одного потока в определенной строке, запуск другого потока до определенного состояния, а затем утверждение для модульного теста.

Ранее я использовал искусственные задержки в коде, которые запускаются некоторыми параметрами в запросе. Например, один запрос указывает серверу задержать запись между двумя записями, а другой - выполнять их без задержки между ними.

Марк Бесси пишет, что это полезно только для создания репро, а не для обнаружения проблемы.

Вы пробовали Corensic Jinx ?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top