Skip to content

Commit 9b5bcba

Browse files
authored
Merge pull request #2146 from elBoberido/iox-1032-refactor-iox-require
iox-#1032 Refactor 'IOX_REQUIRE'
2 parents 3738732 + 95d1a94 commit 9b5bcba

File tree

10 files changed

+112
-42
lines changed

10 files changed

+112
-42
lines changed

doc/design/error_reporting.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ the case that it does not hold
165165
```cpp
166166
int x;
167167
// ...
168-
IOX_REQUIRE(x>=0, Code::OutOfBounds);
168+
IOX_REQUIRE(x>=0, "required condition violation message");
169169
```
170170

171171
The condition is required to hold and this requirement is always checked.

iceoryx_hoofs/reporting/include/iox/assertions.hpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,29 @@
4444
iox::er::forwardPanic(CURRENT_SOURCE_LOCATION, message); \
4545
} while (false)
4646

47-
/// @brief report fatal error if expr evaluates to false
48-
/// @note for conditions that may actually happen during correct use
49-
/// @param expr boolean expression that must hold
50-
/// @param error error object (or code)
51-
#define IOX_REQUIRE(expr, error) IOX_REPORT_FATAL_IF(!(expr), error)
52-
5347
//************************************************************************************************
5448
//* For documentation of intent, defensive programming and debugging
5549
//*
5650
//* There are no error codes/errors required here on purpose, as it would make the use cumbersome.
5751
//* Instead a special internal error type is used.
5852
//************************************************************************************************
5953

54+
/// @brief report fatal required condition violation if expr evaluates to false
55+
/// @note for conditions that may actually happen during correct use
56+
/// @param expr boolean expression that must hold
57+
/// @param message message to be forwarded in case of violation
58+
#define IOX_REQUIRE(expr, message) \
59+
do \
60+
{ \
61+
if (!(expr)) \
62+
{ \
63+
iox::er::forwardFatalError(iox::er::Violation::createRequiredConditionViolation(), \
64+
iox::er::REQUIRED_CONDITION_VIOLATION, \
65+
CURRENT_SOURCE_LOCATION, \
66+
message); /* @todo iox-#1032 add strigified 'expr' as '#expr' */ \
67+
} \
68+
} while (false)
69+
6070
/// @brief if enabled: report fatal precondition violation if expr evaluates to false
6171
/// @param expr boolean expression that must hold upon entry of the function it appears in
6272
/// @param message message to be forwarded in case of violation

iceoryx_hoofs/reporting/include/iox/error_reporting/custom/default/error_reporting_impl.hpp

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ template <class Message>
6767
panic();
6868
}
6969

70+
/// @todo iox-#1032 add a 'StringifiedCondition' template parameter
71+
7072
// Report any error, general version.
7173
template <class Kind, class Error>
7274
inline void report(const SourceLocation& location, Kind, const Error& error)
@@ -103,46 +105,67 @@ inline void report(const SourceLocation& location, iox::er::FatalKind kind, cons
103105
h.onReportError(ErrorDescriptor(location, code, module));
104106
}
105107

106-
template <class Error>
107-
inline void report(const SourceLocation& location, iox::er::PreconditionViolationKind kind, const Error& error)
108+
namespace detail
109+
{
110+
enum class NoMessage
111+
{
112+
};
113+
114+
template <class Kind, class Error, class Message>
115+
inline void report(const SourceLocation& location, Kind kind, const Error& error, Message&& msg)
108116
{
109117
auto code = toCode(error);
110118
auto module = toModule(error);
111-
IOX_ERROR_INTERNAL_LOG_FATAL(location, kind.name);
119+
if constexpr (std::is_same<NoMessage, Message>::value)
120+
{
121+
IOX_ERROR_INTERNAL_LOG_FATAL(location, kind.name);
122+
}
123+
else
124+
{
125+
IOX_ERROR_INTERNAL_LOG_FATAL(location, kind.name << " " << std::forward<Message>(msg));
126+
}
112127
auto& h = ErrorHandler::get();
113128
h.onReportViolation(ErrorDescriptor(location, code, module));
114129
}
130+
} // namespace detail
131+
132+
template <class Error>
133+
inline void report(const SourceLocation& location, iox::er::RequiredConditionViolationKind kind, const Error& error)
134+
{
135+
detail::report(location, kind, error, detail::NoMessage{});
136+
}
137+
138+
template <class Error>
139+
inline void report(const SourceLocation& location, iox::er::PreconditionViolationKind kind, const Error& error)
140+
{
141+
detail::report(location, kind, error, detail::NoMessage{});
142+
}
115143

116144
template <class Error>
117145
inline void report(const SourceLocation& location, iox::er::AssumptionViolationKind kind, const Error& error)
118146
{
119-
auto code = toCode(error);
120-
auto module = toModule(error);
121-
IOX_ERROR_INTERNAL_LOG_FATAL(location, kind.name);
122-
auto& h = ErrorHandler::get();
123-
h.onReportViolation(ErrorDescriptor(location, code, module));
147+
detail::report(location, kind, error, detail::NoMessage{});
148+
}
149+
150+
template <class Error, class Message>
151+
inline void
152+
report(const SourceLocation& location, iox::er::RequiredConditionViolationKind kind, const Error& error, Message&& msg)
153+
{
154+
detail::report(location, kind, error, std::forward<Message>(msg));
124155
}
125156

126157
template <class Error, class Message>
127158
inline void
128159
report(const SourceLocation& location, iox::er::PreconditionViolationKind kind, const Error& error, Message&& msg)
129160
{
130-
auto code = toCode(error);
131-
auto module = toModule(error);
132-
IOX_ERROR_INTERNAL_LOG_FATAL(location, kind.name << " " << std::forward<Message>(msg));
133-
auto& h = ErrorHandler::get();
134-
h.onReportViolation(ErrorDescriptor(location, code, module));
161+
detail::report(location, kind, error, std::forward<Message>(msg));
135162
}
136163

137164
template <class Error, class Message>
138165
inline void
139166
report(const SourceLocation& location, iox::er::AssumptionViolationKind kind, const Error& error, Message&& msg)
140167
{
141-
auto code = toCode(error);
142-
auto module = toModule(error);
143-
IOX_ERROR_INTERNAL_LOG_FATAL(location, kind.name << " " << std::forward<Message>(msg));
144-
auto& h = ErrorHandler::get();
145-
h.onReportViolation(ErrorDescriptor(location, code, module));
168+
detail::report(location, kind, error, std::forward<Message>(msg));
146169
}
147170

148171
} // namespace er

iceoryx_hoofs/reporting/include/iox/error_reporting/error_kind.hpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ struct FatalKind
3737
static constexpr char const* name = "Fatal Error";
3838
};
3939

40+
struct RequiredConditionViolationKind
41+
{
42+
static constexpr char const* name = "Required Condition Violation";
43+
};
44+
4045
struct PreconditionViolationKind
4146
{
4247
static constexpr char const* name = "Precondition Violation";
@@ -62,6 +67,11 @@ struct IsFatal<FatalKind> : public std::true_type
6267
{
6368
};
6469

70+
template <>
71+
struct IsFatal<RequiredConditionViolationKind> : public std::true_type
72+
{
73+
};
74+
6575
template <>
6676
struct IsFatal<PreconditionViolationKind> : public std::true_type
6777
{
@@ -86,6 +96,12 @@ bool constexpr isFatal<FatalKind>(FatalKind)
8696
return IsFatal<FatalKind>::value;
8797
}
8898

99+
template <>
100+
bool constexpr isFatal<RequiredConditionViolationKind>(RequiredConditionViolationKind)
101+
{
102+
return IsFatal<RequiredConditionViolationKind>::value;
103+
}
104+
89105
template <>
90106
bool constexpr isFatal<PreconditionViolationKind>(PreconditionViolationKind)
91107
{
@@ -101,6 +117,9 @@ bool constexpr isFatal<AssumptionViolationKind>(AssumptionViolationKind)
101117
// indicates serious condition, unable to continue
102118
constexpr FatalKind FATAL;
103119

120+
// indicates a bug (contract breach by caller)
121+
constexpr RequiredConditionViolationKind REQUIRED_CONDITION_VIOLATION;
122+
104123
// indicates a bug (contract breach by caller)
105124
constexpr PreconditionViolationKind PRECONDITION_VIOLATION;
106125

iceoryx_hoofs/reporting/include/iox/error_reporting/errors.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ class Violation
7070
return !(*this == rhs);
7171
}
7272

73+
static Violation createRequiredConditionViolation()
74+
{
75+
return Violation(ErrorCode(ErrorCode::REQUIRED_CONDITION_VIOLATION));
76+
}
77+
7378
static Violation createPreconditionViolation()
7479
{
7580
return Violation(ErrorCode(ErrorCode::PRECONDITION_VIOLATION));

iceoryx_hoofs/reporting/include/iox/error_reporting/macros.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@
6161
{ \
6262
if (expr) \
6363
{ \
64-
iox::er::forwardNonFatalError(iox::er::toError(error), kind, CURRENT_SOURCE_LOCATION); \
64+
iox::er::forwardNonFatalError( \
65+
iox::er::toError(error), \
66+
kind, \
67+
CURRENT_SOURCE_LOCATION); /* @todo iox-#1032 add strigified 'expr' as '#expr' */ \
6568
} \
6669
} while (false)
6770

iceoryx_hoofs/reporting/include/iox/error_reporting/types.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ struct ErrorCode
3333

3434
type value;
3535

36-
static constexpr type ASSUMPTION_VIOLATION{0};
37-
static constexpr type PRECONDITION_VIOLATION{1};
36+
static constexpr type REQUIRED_CONDITION_VIOLATION{0};
37+
static constexpr type ASSUMPTION_VIOLATION{1};
38+
static constexpr type PRECONDITION_VIOLATION{2};
3839

3940
constexpr explicit ErrorCode(uint32_t value)
4041
: value(value)

iceoryx_hoofs/test/moduletests/error_reporting/test_error_reporting_macros.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,25 +128,25 @@ TEST_F(ErrorReportingMacroApi_test, reportConditionalNoError)
128128
IOX_TESTING_EXPECT_OK();
129129
}
130130

131-
TEST_F(ErrorReportingMacroApi_test, requireConditionSatisfied)
131+
TEST_F(ErrorReportingMacroApi_test, checkRequireConditionSatisfied)
132132
{
133133
::testing::Test::RecordProperty("TEST_ID", "3c684878-20f8-426f-bb8b-7576b567d04f");
134-
auto f = []() { IOX_REQUIRE(true, MyCodeA::OutOfBounds); };
134+
auto f = []() { IOX_REQUIRE(true, ""); };
135135

136136
runInTestThread(f);
137137

138138
IOX_TESTING_EXPECT_OK();
139139
}
140140

141-
TEST_F(ErrorReportingMacroApi_test, requireConditionNotSatisfied)
141+
TEST_F(ErrorReportingMacroApi_test, checkRequireConditionViolate)
142142
{
143143
::testing::Test::RecordProperty("TEST_ID", "fb62d315-8854-401b-82af-6161ae45a34e");
144-
auto f = []() { IOX_REQUIRE(false, MyCodeA::OutOfBounds); };
144+
auto f = []() { IOX_REQUIRE(false, ""); };
145145

146146
runInTestThread(f);
147147

148148
IOX_TESTING_EXPECT_PANIC();
149-
IOX_TESTING_EXPECT_ERROR(MyCodeA::OutOfBounds);
149+
IOX_TESTING_EXPECT_REQUIRED_CONDITION_VIOLATION();
150150
}
151151

152152
TEST_F(ErrorReportingMacroApi_test, checkPreconditionSatisfied)

iceoryx_hoofs/testing/error_reporting/testing_support.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ bool hasError()
3131
return ErrorHandler::instance().hasError();
3232
}
3333

34+
bool hasRequiredConditionViolation()
35+
{
36+
auto code = iox::er::ErrorCode{iox::er::ErrorCode::REQUIRED_CONDITION_VIOLATION};
37+
return ErrorHandler::instance().hasViolation(code);
38+
}
39+
3440
bool hasPreconditionViolation()
3541
{
3642
auto code = iox::er::ErrorCode{iox::er::ErrorCode::PRECONDITION_VIOLATION};
@@ -45,7 +51,7 @@ bool hasAssumptionViolation()
4551

4652
bool hasViolation()
4753
{
48-
return hasPreconditionViolation() || hasAssumptionViolation();
54+
return hasRequiredConditionViolation() || hasPreconditionViolation() || hasAssumptionViolation();
4955
}
5056

5157
bool isInNormalState()

iceoryx_hoofs/testing/include/iceoryx_hoofs/testing/error_reporting/testing_support.hpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ bool hasPanicked();
5050
/// @brief indicates whether the test error handler registered any error
5151
bool hasError();
5252

53+
/// @brief indicates whether the test error handler registered a required condition violation
54+
bool hasRequiredConditionViolation();
55+
5356
/// @brief indicates whether the test error handler registered a precondition violation
5457
bool hasPreconditionViolation();
5558

@@ -120,11 +123,11 @@ inline void runInTestThread(Function&& testFunction, Args&&... args)
120123

121124
#define IOX_TESTING_ASSERT_NO_ERROR() ASSERT_FALSE(iox::testing::hasError())
122125

123-
#define IOX_TESTING_ASSERT_VIOLATION() \
124-
ASSERT_TRUE(iox::testing::hasPreconditionViolation() || iox::testing::hasAssumptionViolation())
126+
#define IOX_TESTING_ASSERT_VIOLATION() ASSERT_TRUE(iox::testing::hasViolation())
127+
128+
#define IOX_TESTING_ASSERT_NO_VIOLATION() ASSERT_FALSE(iox::testing::hasViolation())
125129

126-
#define IOX_TESTING_ASSERT_NO_VIOLATION() \
127-
ASSERT_FALSE(iox::testing::hasPreconditionViolation() || iox::testing::hasAssumptionViolation())
130+
#define IOX_TESTING_ASSERT_REQUIRED_CONDITION_VIOLATION() ASSERT_TRUE(iox::testing::hasRequiredConditionViolation())
128131

129132
#define IOX_TESTING_ASSERT_PRECONDITION_VIOLATION() ASSERT_TRUE(iox::testing::hasPreconditionViolation())
130133

@@ -142,11 +145,11 @@ inline void runInTestThread(Function&& testFunction, Args&&... args)
142145

143146
#define IOX_TESTING_EXPECT_NO_ERROR() EXPECT_FALSE(iox::testing::hasError())
144147

145-
#define IOX_TESTING_EXPECT_VIOLATION() \
146-
EXPECT_TRUE(iox::testing::hasPreconditionViolation() || iox::testing::hasAssumptionViolation())
148+
#define IOX_TESTING_EXPECT_VIOLATION() EXPECT_TRUE(iox::testing::hasViolation())
149+
150+
#define IOX_TESTING_EXPECT_NO_VIOLATION() EXPECT_FALSE(iox::testing::hasViolation())
147151

148-
#define IOX_TESTING_EXPECT_NO_VIOLATION() \
149-
EXPECT_FALSE(iox::testing::hasPreconditionViolation() || iox::testing::hasAssumptionViolation())
152+
#define IOX_TESTING_EXPECT_REQUIRED_CONDITION_VIOLATION() EXPECT_TRUE(iox::testing::hasRequiredConditionViolation())
150153

151154
#define IOX_TESTING_EXPECT_PRECONDITION_VIOLATION() EXPECT_TRUE(iox::testing::hasPreconditionViolation())
152155

0 commit comments

Comments
 (0)