Тестирование на соответствие контрактам C ++ 20 (утверждения) - PullRequest
2 голосов
/ 03 мая 2019

Херб Саттер выступил с докладом на конференции ACUU относительно будущего исключений в C ++ и предстоящих контрактов по замене или расширению существующих утверждений .

Он постулирует следующие правила для обработки ошибок:

  1. Повреждение системы (например, переполнение стека): прекратить

  2. Ошибка программирования (например, нарушение предусловия): утверждения, контракты

  3. Исправимая ошибка (например, отключение сети): исключение, код ошибки

Хотя я склонен согласиться, я не использую этот подход и по сути объединяю 2 и 3 в один. Причина, по которой я это делаю, заключается в том, что я не знаю, как проверить утверждения или предстоящие контракты. Оба используют схожий механизм, так как их нарушение приводит к завершению программы и до этого вызывает дополнительный обработчик.

Из документации (выделено мое):

Программа может быть переведена с одним из двух режимов продолжения нарушения:

  • off (по умолчанию, если не выбран режим продолжения): после выполнения если обработчик нарушения завершается, вызывается std :: terminate;
  • on: после завершения выполнения обработчика нарушения выполнение продолжается нормально.

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

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

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

Или есть какой-то другой способ проверки на предмет утверждений и контрактов, который мне не хватает?

1 Ответ

2 голосов
/ 03 мая 2019

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

Прототип для обработчика определяется спецификацией. Единственная разница реализации в отношении обработчика нарушений - это то, как вы его установили. Обратите внимание, что «определенный реализацией» не означает «не позволяет этому случиться». То есть, стандарт говорит, что будет механизмом для установки обработчика , и что этот механизм будет документирован с реализацией (вот что "реализация «определено» означает, в отличие от просто «не указано»). Именно то, чем является этот механизм, будет зависеть от реализации, но не предоставляя его, не вариант.

Единственная реальная проблема, которая может возникнуть, - это если несколько реализаций решают разрешить пользователям указывать обработчик, благословляя определенное глобальное имя, и если эти реализации используют другое глобальное имя. Однако, учитывая, что выбор глобального имени является плохой идеей по многим причинам (конфликт с существующим кодом, макросами и т. Д.), Маловероятно, что это станет проблемой в реальности. Поэтому, скорее всего, они выберут очевидный механизм: переключатель компилятора, который задает имя функции для использования в качестве обработчика.

Обратите внимание, что одна из причин сделать определение обработчика статическим, а не определенным во время выполнения, состоит в том, чтобы убедиться, что этот переключатель является компилятором , а не компоновщиком. В конце концов, это тот компилятор, который генерирует любой код проверки концепции. Таким образом, компилятор может просто использовать имя рассматриваемой функции в упомянутом проверочном коде.

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

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