Разумная стратегия для модульного тестирования ожидаемого и непредвиденного поведения тупика - PullRequest
6 голосов
/ 05 июня 2011

Мне хотелось бы получить несколько идей о том, как я должен тестировать некоторые объекты, которые могут блокироваться, ожидая другого участника. Конкретная единица, подлежащая проверке, - это канал между участниками. Сами участники являются пробными приспособлениями для целей испытаний.

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

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

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

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

РЕДАКТИРОВАТЬ: Я уверен, что тестирование было бы хорошо, но я не думаю, что мне нужно его иметь. Я имею в виду три уровня проверки достоверности.

  • «Фактическое поведение, как оказалось, соответствует ожидаемому поведению», тупик не может возникнуть
  • В N тестах тупиковая ситуация "фактическое поведение соответствует ожидаемому поведению" не возникла
  • «Фактическое поведение соответствует ожидаемому поведению» N тестов завершено в ожидаемый срок

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

Последний больше похож на то, что я имею в виду.

Ответы [ 4 ]

5 голосов
/ 19 июня 2011

Единственный способ надежного тестирования на наличие взаимоблокировок - это инструмент подсистемы блокировки для обнаружения и сообщения о них.В прошлый раз, когда мне пришлось это сделать, мы создали отладочную версию, в которой записывалось, какие потоки удерживались, какие блокировки и проверялось на наличие возможных взаимоблокировок при каждом вызове получения блокировки.Это может быть тяжеловесная операция в системе с продолжающейся блокировкой, но мы обнаружили, что это настолько ценно, что мы реорганизовали подсистему, чтобы мы могли включать и выключать ее переключателем во время выполнения, даже в производственных сборках.1001 *

2 голосов
/ 16 июня 2011

Академическое сообщество, вероятно, скажет вам (на самом деле это говорит вам прямо сейчас;), что вы должны сделать верную абстракцию в некоторую так называемую платформу проверки модели ( CSP, pi-calculus ) , Это затем имитирует абстрактные исполнения (исчерпывающий поиск по всем возможным чередованиям планировщика). Конечно, хитрость заключается в том, чтобы убедиться, что абстракция действительно верна. Вы больше не проверяете фактический источник вашей программы, но источник на каком-то другом языке.

В противном случае на ум приходит какой-то неуклюжий подход, такой как Java Path Finder / Explorer (который делает что-то очень похожее) для конкретного языка. Подобные исследовательские прототипы существуют для C, и Intel и других компаний также занимаются этим бизнесом со специализированными инструментами.

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

Ценный подход может заключаться в том, чтобы оборудовать ваш код так, чтобы он фактически обнаруживал тупик и потенциально пытался восстановить. Для обнаружения взаимоблокировок ядро ​​ FreeBSD использует набор C-макросов, которые отслеживают использование блокировки и сообщают потенциальные нарушения через witness(4) механизм. Но опять же, ошибки, которые встречаются редко, будут обнаруживаться только редко.

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

0 голосов
/ 17 июня 2011

Поскольку вы уже сделали достаточно абстракций, чтобы высмеивать участников, почему бы не пойти дальше и абстрагироваться от синхронизации потоков (мьютекс, семафор, еще много чего)?

Когда вы думаете о том, что представляет собой взаимоблокировку, вы можете использовать в своих тестах специализированный синхронизатор потоков с учетом взаимоблокировок. Под «пониманием взаимоблокировок» я не имею в виду, что он должен обнаруживать взаимные блокировки методом грубой силы с использованием тайм-аутов и т. Д., Но должен иметь представление о ситуациях, которые приводят к взаимоблокировкам, посредством флагов, счетчиков и т. Д. Он может обнаруживать взаимоблокировки при необходимости предоставляя ожидаемую функциональность синхронизации потоков. То, что я в основном говорю, это используйте инструментальную синхронизацию потоков для своих тестов ...

Это слишком абстрактно и легче сказать, чем сделать. И я не утверждаю, что успешно сделал это. Я мог бы просто быть глупым здесь. Но, возможно, если бы вы могли предоставить только один (неполный) тест, проблема может быть решена более конкретно.

0 голосов
/ 13 июня 2011

Для тестирования, если нет взаимоблокировки, вы можете использовать эквивалент TimeoutAttribute NUnit, который прерывает и не выполняет тест, если время выполнения превышает верхний предел. Вы можете придумать * хорошее значение времени ожидания, например, если тест не завершится в течение 30 секунд - что-то не так.

Я не уверен (или я не сталкивался с ситуацией) в том, чтобы утверждать, что возникла тупиковая ситуация. Тупики обычно нежелательны. Я озадачен тем, как написать модульный тест, который не пройдёт, если только тестовые блоки не будут - модульные тесты обычно должны быть быстрыми и неблокирующими.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...