В макросе ERROR_BEGIN в первую очередь проверяется, что если функция завершилась с ошибкой, то код ошибки не равен EOK (коду, обозначающему отсутствие ошибки). Обычно признаком ошибки является сам факт отличия кода от EOK, и эта проверка превращается в тавтологию. Но бывают и другие случаи, когда, например, признаком ошибки является возвращаемое значение функции, равное -1, и тогда эта проверка необходима.
Проверка кодов ошибок не ограничивается случаем, когда функция завершилась с ошибкой. Условие типа SHALL должно обеспечивать также проверку в обратную сторону: если условия вызова функции ошибочны, то функция обязана вернуть ошибку, и если этого не произошло, поведение считается некорректным.
Заметим, что независимо от того, успешно ли отработала функция, необходимо проверять все требования к кодам возврата, поскольку выполнение одного требования ещё не означает, что другие требования не нарушены. Таким образом, решение о правильной работе функции должно приниматься только в макросе ERROR_END, не раньше. На первый взгляд, это соображение очевидно, но именно поэтому его так легко упустить из виду.
Для каждого требования имеется четыре базовых случая:
В каждом из этих случаев есть свои тонкости, которые легко упустить из виду. Возьмём, например, первый случай, когда ошибка ожидалась и произошла. Первым побуждением будет выдать вердикт, что проверка завершилась успешно, и выйти из блока проверки ошибок. Однако этого делать ни в коем случае нельзя, т. к. должны быть проверены абсолютно все требования - то самое «очевидное» соображение, высказанное выше! Ведь даже в случае возврата ожидаемого кода ошибки есть вероятность, что другое требование окажется нарушенным. То же самое относится к последнему случаю, когда ошибка не ожидалась и не произошла.
Случай второй, когда ошибка не ожидалась, но произошла. Если это требование типа NEVER, или если это MAY/SHALL, и соответствующая константа XX_HAS_EXTRA_CONDITION_ON_YY равна нулю, то можно констатировать неправильную работу функции.