Skip to content

Commit

Permalink
iox-eclipse-iceoryx#1032 Add stringified condition to the error output
Browse files Browse the repository at this point in the history
  • Loading branch information
elBoberido committed Feb 18, 2024
1 parent a21603a commit 079afd6
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 56 deletions.
20 changes: 11 additions & 9 deletions iceoryx_hoofs/reporting/include/iox/assertions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,31 +48,33 @@
//* Instead a special internal error type is used.
//************************************************************************************************

/// @brief only for debug builds: report fatal assert violation if expr evaluates to false
/// @brief only for debug builds: report fatal assert violation if expression evaluates to false
/// @note for conditions that should not happen with correct use
/// @param expr boolean expression that must hold
/// @param condition boolean expression that must hold
/// @param message message to be forwarded in case of violation
#define IOX_ASSERT(expr, message) \
if (iox::er::Configuration::CHECK_ASSERT && !(expr)) \
#define IOX_ASSERT(condition, message) \
if (iox::er::Configuration::CHECK_ASSERT && !(condition)) \
{ \
iox::er::forwardFatalError(iox::er::Violation::createAssertViolation(), \
iox::er::ASSERT_VIOLATION, \
IOX_CURRENT_SOURCE_LOCATION, \
#condition, \
message); \
} \
[] {}() // the empty lambda forces a semicolon on the caller side

/// @brief report fatal enforce violation if expr evaluates to false
/// @brief report fatal enforce violation if expression evaluates to false
/// @note for conditions that may actually happen during correct use
/// @param expr boolean expression that must hold
/// @param condition boolean expression that must hold
/// @param message message to be forwarded in case of violation
#define IOX_ENFORCE(expr, message) \
if (!(expr)) \
#define IOX_ENFORCE(condition, message) \
if (!(condition)) \
{ \
iox::er::forwardFatalError(iox::er::Violation::createEnforceViolation(), \
iox::er::ENFORCE_VIOLATION, \
IOX_CURRENT_SOURCE_LOCATION, \
message); /* @todo iox-#1032 add strigified 'expr' as '#expr' */ \
#condition, \
message); \
} \
[] {}() // the empty lambda forces a semicolon on the caller side

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,20 +68,33 @@ template <class Message>
panic();
}

/// @todo iox-#1032 add a 'StringifiedCondition' template parameter
namespace detail
{
inline log::LogStream& logStringifiedCondition(log::LogStream& stream, const char* stringifiedCondition)
{
if (stringifiedCondition != nullptr && strnlen(stringifiedCondition, 1) != 0)
{
stream << "Conditiopn: \"" << stringifiedCondition << "\" ";
}
return stream;
}
} // namespace detail

// Report any error, general version.
template <class Kind, class Error>
inline void report(const SourceLocation& location, Kind, const Error& error)
inline void report(const SourceLocation& location, Kind, const Error& error, const char* stringifiedCondition)
{
auto code = toCode(error);
auto module = toModule(error);
auto moduleName = toModuleName(error);
auto errorName = toErrorName(error);

IOX_ERROR_INTERNAL_LOG(location,
"[" << errorName << " (code = " << code.value << ")] in module [" << moduleName
<< " (id = " << module.value << ")]");
[stringifiedCondition](auto& stream) -> auto& {
return detail::logStringifiedCondition(stream, stringifiedCondition);
} << "["
<< errorName << " (code = " << code.value << ")] in module [" << moduleName
<< " (id = " << module.value << ")]");
auto& h = ErrorHandler::get();
h.onReportError(ErrorDescriptor(location, code, module));
}
Expand All @@ -92,16 +105,20 @@ inline void report(const SourceLocation& location, Kind, const Error& error)
// Here the logging is subtly different and does not easily allow to factor out common parts.

template <class Error>
inline void report(const SourceLocation& location, iox::er::FatalKind kind, const Error& error)
inline void
report(const SourceLocation& location, iox::er::FatalKind kind, const Error& error, const char* stringifiedCondition)
{
auto code = toCode(error);
auto module = toModule(error);
auto moduleName = toModuleName(error);
auto errorName = toErrorName(error);

IOX_ERROR_INTERNAL_LOG_FATAL(location,
"[" << kind.name << "] [" << errorName << " (code = " << code.value << ")] in module ["
<< moduleName << " (id = " << module.value << ")]");
[stringifiedCondition](auto& stream) -> auto& {
return detail::logStringifiedCondition(stream, stringifiedCondition);
} << "["
<< kind.name << "] [" << errorName << " (code = " << code.value << ")] in module ["
<< moduleName << " (id = " << module.value << ")]");
auto& h = ErrorHandler::get();
h.onReportError(ErrorDescriptor(location, code, module));
}
Expand All @@ -113,46 +130,71 @@ enum class NoMessage
};

template <class Kind, class Error, class Message>
inline void report(const SourceLocation& location, Kind kind, const Error& error, Message&& msg)
inline void
// NOLINTNEXTLINE(readability-function-size) Not used directly but via a macro which hides the number of parameter away
report(const SourceLocation& location, Kind kind, const Error& error, const char* stringifiedCondition, Message&& msg)
{
auto code = toCode(error);
auto module = toModule(error);
if constexpr (std::is_same<NoMessage, Message>::value)
{
IOX_ERROR_INTERNAL_LOG_FATAL(location, "[" << kind.name << "]");
IOX_ERROR_INTERNAL_LOG_FATAL(location,
[stringifiedCondition](auto& stream) -> auto& {
return detail::logStringifiedCondition(stream, stringifiedCondition);
} << "["
<< kind.name << "]");
}
else
{
IOX_ERROR_INTERNAL_LOG_FATAL(location, "[" << kind.name << "] " << std::forward<Message>(msg));
IOX_ERROR_INTERNAL_LOG_FATAL(location,
[stringifiedCondition](auto& stream) -> auto& {
return detail::logStringifiedCondition(stream, stringifiedCondition);
} << "["
<< kind.name << "] " << std::forward<Message>(msg));
}
auto& h = ErrorHandler::get();
h.onReportViolation(ErrorDescriptor(location, code, module));
}
} // namespace detail

template <class Error>
inline void report(const SourceLocation& location, iox::er::AssertViolationKind kind, const Error& error)
inline void report(const SourceLocation& location,
iox::er::AssertViolationKind kind,
const Error& error,
const char* stringifiedCondition)
{
detail::report(location, kind, error, detail::NoMessage{});
detail::report(location, kind, error, stringifiedCondition, detail::NoMessage{});
}

template <class Error>
inline void report(const SourceLocation& location, iox::er::EnforceViolationKind kind, const Error& error)
inline void report(const SourceLocation& location,
iox::er::EnforceViolationKind kind,
const Error& error,
const char* stringifiedCondition)
{
detail::report(location, kind, error, detail::NoMessage{});
detail::report(location, kind, error, stringifiedCondition, detail::NoMessage{});
}

template <class Error, class Message>
inline void report(const SourceLocation& location, iox::er::AssertViolationKind kind, const Error& error, Message&& msg)
// NOLINTNEXTLINE(readability-function-size) Not used directly but via a macro which hides the number of parameter away
inline void report(const SourceLocation& location,
iox::er::AssertViolationKind kind,
const Error& error,
const char* stringifiedCondition,
Message&& msg)
{
detail::report(location, kind, error, std::forward<Message>(msg));
detail::report(location, kind, error, stringifiedCondition, std::forward<Message>(msg));
}

template <class Error, class Message>
inline void
report(const SourceLocation& location, iox::er::EnforceViolationKind kind, const Error& error, Message&& msg)
// NOLINTNEXTLINE(readability-function-size) Not used directly but via a macro which hides the number of parameter away
inline void report(const SourceLocation& location,
iox::er::EnforceViolationKind kind,
const Error& error,
const char* stringifiedCondition,
Message&& msg)
{
detail::report(location, kind, error, std::forward<Message>(msg));
detail::report(location, kind, error, stringifiedCondition, std::forward<Message>(msg));
}

} // namespace er
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,45 +45,56 @@ template <typename Message>
}

/// @brief Forwards a fatal error and does not return.
/// @param location the location of the error
/// @param error the error
/// @param kind the kind of error (category)
/// @param location the location of the error
/// @param stringifiedCondition the condition as string if a macro with a condition was used; an empty string otherwise
template <typename Error, typename Kind>
[[noreturn]] inline void forwardFatalError(Error&& error, Kind&& kind, const SourceLocation& location)
[[noreturn]] inline void
forwardFatalError(Error&& error, Kind&& kind, const SourceLocation& location, const char* stringifiedCondition)
{
using K = typename std::remove_const<typename std::remove_reference<Kind>::type>::type;
static_assert(IsFatal<K>::value, "Must forward a fatal error!");

report(location, std::forward<Kind>(kind), std::forward<Error>(error));
report(location, std::forward<Kind>(kind), std::forward<Error>(error), stringifiedCondition);
panic(location);
abort();
}

/// @brief Forwards a non-fatal error.
/// @param location the location of the error
/// @param error the error
/// @param kind the kind of error (category)
/// @param location the location of the error
/// @param stringifiedCondition the condition as string if a macro with a condition was used; an empty string otherwise
template <typename Error, typename Kind>
inline void forwardNonFatalError(Error&& error, Kind&& kind, const SourceLocation& location)
inline void
forwardNonFatalError(Error&& error, Kind&& kind, const SourceLocation& location, const char* stringifiedCondition)
{
using K = typename std::remove_const<typename std::remove_reference<Kind>::type>::type;
static_assert(!IsFatal<K>::value, "Must forward a non-fatal error!");

report(location, std::forward<Kind>(kind), std::forward<Error>(error));
report(location, std::forward<Kind>(kind), std::forward<Error>(error), stringifiedCondition);
}

/// @brief Forwards a fatal error and a message and does not return.
/// @param location the location of the error
/// @param error the error
/// @param kind the kind of error (category)
/// @param location the location of the error
/// @param stringifiedCondition the condition as string if a macro with a condition was used; an empty string otherwise
/// @param msg the message to be forwarded
template <typename Error, typename Kind, typename Message>
[[noreturn]] inline void forwardFatalError(Error&& error, Kind&& kind, const SourceLocation& location, Message&& msg)
// NOLINTNEXTLINE(readability-function-size) Not used directly but via a macro which hides the number of parameter away
[[noreturn]] inline void forwardFatalError(
Error&& error, Kind&& kind, const SourceLocation& location, const char* stringifiedCondition, Message&& msg)
{
using K = typename std::remove_const<typename std::remove_reference<Kind>::type>::type;
static_assert(IsFatal<K>::value, "Must forward a fatal error!");

report(location, std::forward<Kind>(kind), std::forward<Error>(error), std::forward<Message>(msg));
report(location,
std::forward<Kind>(kind),
std::forward<Error>(error),
stringifiedCondition,
std::forward<Message>(msg));
panic(location);
abort();
}
Expand Down
23 changes: 10 additions & 13 deletions iceoryx_hoofs/reporting/include/iox/error_reporting/macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,34 +41,31 @@
/// @param error error object (or code)
/// @param kind kind of error, must be non-fatal
#define IOX_REPORT(error, kind) \
iox::er::forwardNonFatalError(iox::er::toError(error), kind, IOX_CURRENT_SOURCE_LOCATION)
iox::er::forwardNonFatalError(iox::er::toError(error), kind, IOX_CURRENT_SOURCE_LOCATION, "")

/// @brief report fatal error
/// @param error error object (or code)
#define IOX_REPORT_FATAL(error) \
iox::er::forwardFatalError(iox::er::toError(error), iox::er::FATAL, IOX_CURRENT_SOURCE_LOCATION)
iox::er::forwardFatalError(iox::er::toError(error), iox::er::FATAL, IOX_CURRENT_SOURCE_LOCATION, "")

/// @brief report error of some non-fatal kind if expr evaluates to true
/// @param expr boolean expression
/// @param condition boolean expression
/// @param error error object (or code)
/// @param kind kind of error, must be non-fatal
#define IOX_REPORT_IF(expr, error, kind) \
if (expr) \
#define IOX_REPORT_IF(condition, error, kind) \
if (condition) \
{ \
iox::er::forwardNonFatalError( \
iox::er::toError(error), \
kind, \
IOX_CURRENT_SOURCE_LOCATION); /* @todo iox-#1032 add strigified 'expr' as '#expr' */ \
iox::er::forwardNonFatalError(iox::er::toError(error), kind, IOX_CURRENT_SOURCE_LOCATION, #condition); \
} \
[] {}() // the empty lambda forces a semicolon on the caller side

/// @brief report fatal error if expr evaluates to true
/// @param expr boolean expression
/// @param condition boolean expression
/// @param error error object (or code)
#define IOX_REPORT_FATAL_IF(expr, error) \
if (expr) \
#define IOX_REPORT_FATAL_IF(condition, error) \
if (condition) \
{ \
iox::er::forwardFatalError(iox::er::toError(error), iox::er::FATAL, IOX_CURRENT_SOURCE_LOCATION); \
iox::er::forwardFatalError(iox::er::toError(error), iox::er::FATAL, IOX_CURRENT_SOURCE_LOCATION, #condition); \
} \
[] {}() // the empty lambda forces a semicolon on the caller side

Expand Down
Loading

0 comments on commit 079afd6

Please sign in to comment.