Files
torstenandCopilot 342ffd3e5c Update submodule to latest BUILD_RTI fixes
- HandlerMinelayerData: BUILD_RTI Guards für RTI-Abhängigkeiten
- svcTabCommon: Export-Header-Fix via Fallback-Target
- TrainingAreaBase: Stub-Header für BUILD_RTI=OFF
- ddsfts: Include-Pfad und Dependency-Fixes
- BUILD_RTI=OFF Compilation vollständig unterstützt

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Entire-Checkpoint: 01M0JNZA586SACX1PRZ2DJAE5S
2026-08-21 19:30:20 +02:00

625 lines
23 KiB
C

/*
* (c) Copyright, Real-Time Innovations, 2002-2022.
* All rights reserved.
* No duplications, whole or partial, manual or electronic, may be made
* without express written permission. Any such copies, or
* revisions thereof, must display this notice unaltered.
* This code contains trade secrets of Real-Time Innovations, Inc.
*/
#ifndef rtitest_assert_h
#define rtitest_assert_h
#include <stdio.h>
#include <float.h>
#include "rtitest/test_assert_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup RTITestAssertion Assertions
* @brief Macros to assert conditions in unit tests.
*/
/**
* @defgroup RTITestUtilities Utilities
* @brief Macros to help writing unit tests.
*/
/** @internal
* @ingroup RTITestAssertion
* @brief Define this variable to print a debug message every time
* a unit test calls RTITest_assert() or RTITest_assertWithStr()
*/
#ifdef RTI_TEST_ENABLE_DEBUG_ASSERT
#define RTITest_debugAssert(str__) \
RTITestLogger_log( \
RTI_TEST_LOG_BIT_EXCEPTION, \
&RTI_TEST_LOG_EMPTY_TEMPLATE, \
"[DEBUG %s:%d] executing command: %s", \
__FILE__, \
__LINE__, \
#str__)
#else
#define RTITest_debugAssert(str__)
#endif
/** @internal
* @ingroup RTITestAssertion
* @brief Copy a message into RTITest_g_lastAssertErrorMessage. Expects the
* message as a formatted string and its parameters as variadic arguments.
*
* @details This macro is used in other assert macros to introduce some extra
* information in the JUnit output XML.
*/
#define RTITest_setLastAssertErrorMessage(...) \
if (RTITest_g_lastAssertErrorMessage != NULL) { \
int unusedReturnValue__; \
unusedReturnValue__ = RTITestLog_snprintf( \
RTITest_g_lastAssertErrorMessage, \
RTI_TEST_MAX_ASSERT_ERROR_MESSAGE_SIZE, \
__VA_ARGS__); \
(void) unusedReturnValue__; \
}
/** @internal
* @ingroup RTITestAssertion
* @brief Log an assert message and copy the message on
* RTITest_g_lastAssertErrorMessage.
* @param logMessage__ \b In. The message format, with its variadic arguments.
*/
#define RTITest_assertLog(logMessage__, ...) \
(void) METHOD_NAME; \
RTITest_setLastAssertErrorMessage(__VA_ARGS__); \
RTITestLogger_log(RTI_TEST_LOG_BIT_EXCEPTION, (logMessage__), __VA_ARGS__)
/** @internal
* @ingroup RTITestAssertion
* @brief Log an assert message with function name and copy the message on
* RTITest_g_lastAssertErrorMessage.
* @param functionName__ \b In. The function name.
* @param logMessage__ \b In. The message format, with its variadic arguments.
*/
#define RTITest_assertLogWithFunctionName(functionName__, logMessage__, ...) \
RTITest_setLastAssertErrorMessage(__VA_ARGS__); \
RTITestLogger_logWithFunctionName( \
RTI_TEST_LOG_BIT_EXCEPTION, \
(functionName__), \
(logMessage__), \
__VA_ARGS__)
/** @internal
* @ingroup RTITestAssertion
* @brief Assert that a statement is true. Otherwise, log the given message.
* @param statement__ \b In. Statement to be run and asserted.
* @param str__ \b In. Message to be printed in case of failure.
* @details Calls `goto done` if the assertion fails. Therefore, this macro requires a `done` label to be defined in the method that this assertion is called in.
*/
#define RTITest_assertWithStr(statement__, str__) \
RTITest_debugAssert(statement__); \
if (!(statement__)) { \
const char *strConst__ = str__; \
RTITest_assertLog( \
&RTI_TEST_LOG_EMPTY_TEMPLATE, \
"[%s:%d] assertion failed: %s reason: %s", \
__FILE__, \
__LINE__, \
#statement__, \
strConst__); \
goto done; \
}
/**
* @ingroup RTITestAssertion
* @brief Assert that statement__ is TRUE with a custom action
* on failure
*
* @details If statement__ is not true, then failAction__ will
* be performed
*/
#define RTITest_assertWithAction(statement__, failAction__) \
RTITest_debugAssert(statement__); \
if (!(statement__)) { \
RTITest_assertLog( \
&RTI_TEST_LOG_EMPTY_TEMPLATE, \
"[%s:%d] assertion failed: %s", \
__FILE__, \
__LINE__, \
#statement__); \
failAction__; \
}
/**
* @ingroup RTITestAssertion
* @brief Run and assert a statement. If false, go to done tag.
* @param statement__ \b In. Statement to be asserted.
* @details Calls `goto done` if the assertion fails. Therefore, this macro requires a `done` label to be defined in the method that this assertion is called in.
*/
#define RTITest_assert(statement__) \
RTITest_assertWithAction(statement__, goto done)
/**
* @ingroup RTITestAssertion
* @brief Run and assert a statement after the done tag. This sets the variable
result to RTI_TEST_RETCODE_FAILED if the statement evaluates to false.
* @param statement__ \b In. Statement to be run and asserted.
*/
#define RTITest_assertAfterDone(statement__) \
RTITest_assertWithAction(statement__, result = RTI_TEST_RETCODE_FAILED)
/**
* @ingroup RTITestAssertion
* @brief Run and assert a statement. In case of failure, only prints a message,
no other action is run.
* @param statement__ \b In. Statement to be run and asserted.
*/
#define RTITest_assertWithNoAction(statement__) \
RTITest_assertWithAction(statement__,)
/*
* Use almost equals macros only if you cannot get the right precision. Use
* regular assert equals macros instead.
*/
/**
* @ingroup RTITestAssertion
* @brief Assert that two floating point numbers are almost equal.
* @param limit__ \b In. The maximum difference between the two numbers.
* @param actual__ \b In. The actual value.
* @details Calls `goto done` if the assertion fails. Therefore, this macro requires a `done` label to be defined in the method that this assertion is called in.
*/
#define RTITest_assertAlmostEqualsFloat(limit__, actual__) \
RTITest_assertComparisonForFloatingPointTypeWithAction( \
limit__, \
actual__, \
float, \
==, \
0.0000007, \
goto done)
/**
* @ingroup RTITestAssertion
* @brief Assert that two doubles are almost equal.
* @param limit__ \b In. The maximum difference between the two numbers.
* @param actual__ \b In. The actual value.
* @details Calls `goto done` if the assertion fails. Therefore, this macro requires a `done` label to be defined in the method that this assertion is called in.
*/
#define RTITest_assertAlmostEqualsDouble(limit__, actual__) \
RTITest_assertComparisonForFloatingPointTypeWithAction( \
limit__, \
actual__, \
double, \
==, \
0.0000007, \
goto done)
/**
* @ingroup RTITestAssertion
* @brief Assert that two given Sequence Numbers are equal.
* @param expected__ \b In. The expected Sequence Number.
* @param actual__ \b In. The actual Sequence Number.
* @details Calls `goto done` if the assertion fails. Therefore, this macro requires a `done` label to be defined in the method that this assertion is called in.
*/
#define RTITest_assertEqualsSN(expected__, actual__) \
{ \
RTITest_assertComparisonForType( \
(expected__).low, \
(actual__).low, \
unsigned int, \
"%u", \
==); \
RTITest_assertComparisonForType( \
(expected__).high, \
(actual__).high, \
int, \
"%d", \
==); \
}
/** @internal
* @ingroup RTITestAssertion
* @brief Assert that an operation is true for two given DDS_Duration_t values.
* @param expected__ \b In. The expected DDS_Duration_t value.
* @param actual__ \b In. The actual DDS_Duration_t value.
* @param operation__ \b In. The operation to be asserted.
* @param failAction__ \b In. Action to be run if the assertion fails.
*/
#define RTITest_assertComparisonForDDS_Duration_tWithAction(expected__, actual__, operation__, failAction__) \
{ \
RTITest_assertComparisonForTypeWithAction( \
expected__.sec, \
actual__.sec, \
int, \
"%d", \
operation__, \
failAction__); \
RTITest_assertComparisonForTypeWithAction( \
expected__.nanosec, \
actual__.nanosec, \
unsigned int, \
"%d", \
operation__, \
failAction__); \
}
/** @internal
* @ingroup RTITestAssertion
* @brief Assert that an operation is true for two given DDS_Duration_t values.
* @param expected__ \b In. The expected DDS_Duration_t value.
* @param actual__ \b In. The actual DDS_Duration_t value.
* @param operation__ \b In. The operation to be asserted.
* @details Calls `goto done` if the assertion fails. Therefore, this macro requires a `done` label to be defined in the method that this assertion is called in.
*/
#define RTITest_assertComparisonForDDS_Duration_t(expected__, actual__, operation__) \
RTITest_assertComparisonForDDS_Duration_tWithAction( \
expected__, \
actual__, \
operation__, \
goto done)
/**
* @ingroup RTITestAssertion
* @brief Assert that two given DDS_Duration_t values are equal.
* @param expected__ \b In. The expected DDS_Duration_t value.
* @param actual__ \b In. The actual DDS_Duration_t value.
* @details Calls `goto done` if the assertion fails. Therefore, this macro requires a `done` label to be defined in the method that this assertion is called in.
*/
#define RTITest_assertEqualsDDS_Duration_t(expected__, actual__) \
RTITest_assertComparisonForDDS_Duration_t(expected__, actual__, ==)
/**
* @ingroup RTITestAssertion
* @brief Assert that two given strings are equal.
* @param expected__ \b In. The expected string.
* @param actual__ \b In. The actual string.
* @pre expected__ != NULL && actual__ != NULL
* @details Calls `goto done` if the assertion fails. Therefore, this macro requires a `done` label to be defined in the method that this assertion is called in.
*/
#define RTITest_assertEqualsString(expected__, actual__) \
RTITest_debugAssert(strcmp((expected__), (actual__)) == 0); \
if (strcmp((expected__), (actual__)) != 0) { \
const char *expectedConst__ = expected__; \
const char *actualConst__ = actual__; \
RTITest_assertLog( \
&RTI_TEST_LOG_EMPTY_TEMPLATE, \
"[%s:%d] assertion failed: strcmp(%s, %s) == 0: expected: %s, " \
"actual: %s", \
__FILE__, \
__LINE__, \
#expected__, \
#actual__, \
expectedConst__, \
actualConst__); \
goto done; \
}
/**
* @ingroup RTITestAssertion
* @brief Assert that two given strings are not equal.
* @param expected__ \b In. The expected string.
* @param actual__ \b In. The actual string.
* @pre expected__ != NULL && actual__ != NULL
* @details Calls `goto done` if the assertion fails. Therefore, this macro requires a `done` label to be defined in the method that this assertion is called in.
*/
#define RTITest_assertNotEqualsString(expected__, actual__) \
RTITest_debugAssert(strcmp((expected__), (actual__)) != 0); \
if (strcmp((expected__), (actual__)) == 0) { \
const char *expectedConst__ = expected__; \
const char *actualConst__ = actual__; \
RTITest_assertLog( \
&RTI_TEST_LOG_EMPTY_TEMPLATE, \
"[%s:%d] assertion failed: strcmp(%s, %s) != 0: not expected: %s, " \
"actual: %s", \
__FILE__, \
__LINE__, \
#expected__, \
#actual__, \
expectedConst__, \
actualConst__); \
goto done; \
}
/**
* @ingroup RTITestAssertion
* @brief Assert that expectedSubStr__ is contained in actualStr__.
* @param expectedSubStr__ \b In. The substring to be searched.
* @param actualStr__ \b In. The string to be scanned.
*
* @details Example: RTITest_assertSubString("a","abc");
* @details Calls `goto done` if the assertion fails. Therefore, this macro requires a `done` label to be defined in the method that this assertion is called in.
*/
#define RTITest_assertSubString(expectedSubStr__, actualStr__) \
RTITest_debugAssert(strstr((actualStr__), (expectedSubStr__)) == NULL); \
if (strstr((actualStr__), (expectedSubStr__)) == NULL) { \
RTITest_assertLog( \
&RTI_TEST_LOG_EMPTY_TEMPLATE, \
"[%s:%d] assertion failed: expected to find string %s in %s", \
__FILE__, \
__LINE__, \
expectedSubStr__, \
actualStr__); \
goto done; \
}
/**
* @ingroup RTITestAssertion
* @brief Assert that a given object is not NULL.
* @param object__ \b In. The object to be asserted.
* @details Calls `goto done` if the assertion fails. Therefore, this macro requires a `done` label to be defined in the method that this assertion is called in.
*/
#define RTITest_assertNotNull(object__) \
RTITest_assertNotNullWithAction(object__, goto done)
/**
* @ingroup RTITestAssertion
* @brief Assert that a given object is not NULL.
* @param object__ \b In. The object to be asserted.
* @param failAction__ \b In. Action to be run if the assertion fails.
*/
#define RTITest_assertNotNullWithAction(object__, failAction__) \
RTITest_debugAssert((object__) != NULL); \
if ((object__) == NULL) { \
RTITest_assertLog( \
&RTI_TEST_LOG_EMPTY_TEMPLATE, \
"[%s:%d] pointer is null: %s", \
__FILE__, \
__LINE__, \
#object__); \
failAction__; \
}
/**
* @ingroup RTITestAssertion
* @brief Assert that a given object is NULL.
* @param object__ \b In. The object to be asserted.
* @details Calls `goto done` if the assertion fails. Therefore, this macro requires a `done` label to be defined in the method that this assertion is called in.
*/
#define RTITest_assertNull(object__) \
RTITest_assertNullWithAction(object__, goto done)
/**
* @ingroup RTITestAssertion
* @brief Assert that a given object is NULL.
* @param object__ \b In. The object to be asserted.
* @param failAction__ \b In. Action to be run if the assertion fails.
*/
#define RTITest_assertNullWithAction(object__, failAction__) \
RTITest_debugAssert((object__) == NULL); \
if ((object__) != NULL) { \
RTITest_assertLog( \
&RTI_TEST_LOG_EMPTY_TEMPLATE, \
"[%s:%d] pointer is not null: %s", \
__FILE__, \
__LINE__, \
#object__); \
failAction__; \
}
/**
* @ingroup RTITestAssertion
* @brief Assert that two given DDS_ReturnCode_t return codes are equal.
* @param retcode__ \b In. The actual DDS_ReturnCode_t return code.
* @param failAction__ \b In. Action to be run if the assertion fails.
* @param expectedRetcode__ \b In. The expected DDS_ReturnCode_t return code.
*/
#define RTITest_assertRetcodeWithAction( \
retcode__, \
failAction__, \
expectedRetcode__) \
{ \
DDS_ReturnCode_t retCodeTmp__ = (retcode__); \
RTITest_debugAssert(retCodeTmp__ == (expectedRetcode__)); \
if (retCodeTmp__ != (expectedRetcode__)) { \
if ((int) retCodeTmp__ < 0) { \
RTITest_assertLog( \
&RTI_TEST_LOG_EMPTY_TEMPLATE, \
"[%s:%d] assertion failed: %s == %s", \
__FILE__, \
__LINE__, \
#retcode__, \
#expectedRetcode__); \
} else { \
unsigned int retCodeAsUInt__ = (unsigned int) retCodeTmp__; \
unsigned int index__ = \
(retCodeAsUInt__ < RTI_TEST_NUM_RETCODES - 1 \
? retCodeAsUInt__ \
: RTI_TEST_NUM_RETCODES); \
index__ = \
(retCodeTmp__ == DDS_RETCODE_NOT_ALLOWED_BY_SECURITY \
? RTI_TEST_NUM_RETCODES - 1 \
: index__); \
RTITest_assertLog( \
&RTI_TEST_LOG_EMPTY_TEMPLATE, \
"[%s:%d] assertion failed: %s == %s: got %s", \
__FILE__, \
__LINE__, \
#retcode__, \
#expectedRetcode__, \
RTITest_g_returnCodeStrings[index__]); \
} \
failAction__; \
} \
}
/**
* @ingroup RTITestAssertion
* @brief Assert that a given DDS_ReturnCode_t return code is DDS_RETCODE_OK.
* Otherwise, run the given action.
* @param retcode__ \b In. The actual DDS_ReturnCode_t return code.
* @param failAction__ \b In. Action to be run if the assertion fails.
*/
#define RTITest_assertOkWithAction(retcode__, failAction__) \
RTITest_assertRetcodeWithAction(retcode__, failAction__, DDS_RETCODE_OK)
/**
* @ingroup RTITestAssertion
* @brief Assert that a given DDS_ReturnCode_t return code is DDS_RETCODE_OK.
* @param retcode__ \b In. The actual DDS_ReturnCode_t return code.
* @details Calls `goto done` if the assertion fails. Therefore, this macro requires a `done` label to be defined in the method that this assertion is called in.
*/
#define RTITest_assertOk(retcode__) \
RTITest_assertOkWithAction((retcode__), goto done)
#define RTITest_assertPassed(retcode__) \
RTITest_assertEqualsInt(RTI_TEST_RETCODE_PASSED, (retcode__))
/**
* @ingroup RTITestAssertion
* @brief Assert that a given DDS_ReturnCode_t return code is DDS_RETCODE_ERROR.
* Otherwise, run the given action.
* @param retcode__ \b In. The actual DDS_ReturnCode_t return code.
* @param failAction__ \b In. Action to be run if the assertion fails.
*/
#define RTITest_assertErrorWithAction(retcode__, failAction__) \
RTITest_assertRetcodeWithAction(retcode__, failAction__, DDS_RETCODE_ERROR)
/**
* @ingroup RTITestAssertion
* @brief Assert that two DDS_ReturnCode_t return codes are equal, otherwise
* goto done. This macro requires the done label to be defined.
* @param expected__ \b In. The expected DDS_ReturnCode_t.
* @param retcode__ \b In. The actual DDS_ReturnCode_t.
*/
#define RTITest_assertEqualsRetcode(expected__, retcode__) \
RTITest_assertRetcodeWithAction(retcode__, goto done, expected__)
/**
* @ingroup RTITestAssertion
* @brief Assert that a given DDS_ReturnCode_t return code is DDS_RETCODE_ERROR.
* @param retcode__ \b In. The actual DDS_ReturnCode_t return code.
* @details Calls `goto done` if the assertion fails. Therefore, this macro requires a `done` label to be defined in the method that this assertion is called in.
*/
#define RTITest_assertError(retcode__) \
RTITest_assertErrorWithAction((retcode__), goto done)
/*
* Use after the done label to set the test result to failed if the assert fails
* requires the test result variable to be named 'result'
*/
/**
* @ingroup RTITestAssertion
* @brief Assert that a given DDS_ReturnCode_t return code is DDS_RETCODE_OK.
* Otherwise, set the result variable to RTI_TEST_RETCODE_FAILED.
* @param retcode__ \b In. The actual DDS_ReturnCode_t return code.
*/
#define RTITest_assertOkAfterDone(retcode__) \
RTITest_assertOkWithAction((retcode__), result = RTI_TEST_RETCODE_FAILED)
/**
* @ingroup RTITestAssertion
* @brief Assert that a given statement is false.
* Otherwise, run the given action
*/
#define RTITest_assertFalseWithAction(statement__, failAction__) \
RTITest_debugAssert(statement__); \
if ((statement__)) { \
RTITest_assertLog( \
&RTI_TEST_LOG_EMPTY_TEMPLATE, \
"[%s:%d] assertion failed: !%s", \
__FILE__, \
__LINE__, \
#statement__); \
failAction__; \
}
/**
* @ingroup RTITestAssertion
* @brief Assert that a given statement is false.
* @param statement__ \b In. The statement to be asserted.
* @details Calls `goto done` if the assertion fails. Therefore, this macro requires a `done` label to be defined in the method that this assertion is called in.
*/
#define RTITest_assertFalse(statement__) \
RTITest_assertFalseWithAction(statement__, goto done)
/**
* @ingroup RTITestAssertion
* @brief Run and assert a statement after the done tag. This sets the variable
result to RTI_TEST_RETCODE_FAILED if the statement evaluates to true.
* @param statement__ \b In. Statement to be run and asserted.
*/
#define RTITest_assertFalseAfterDone(statement__) \
RTITest_assertFalseWithAction(statement__, result = RTI_TEST_RETCODE_FAILED)
/**
* @ingroup RTITestAssertion
* @brief Assert that a given value is within a given tolerance.
* Otherwise, run the given action.
* @param expected__ \b In. The expected value.
* @param count__ \b In. The actual value.
* @param tolerance_percentage__ \b In. The tolerance percentage.
* @param failAction__ \b In. Action to be run if the assertion fails.
* @details Checks whether count__ is within a margin specified by expected__ and a
* tolerance_percentage__
*/
#define RTITest_assertMarginWithAction(expected__, count__, tolerance_percentage__, failAction__) \
{ \
double tolerance = (double) (tolerance_percentage__) / 100; \
double max_count = (double) (expected__) * (1 + tolerance); \
double min_count = (double) (expected__) * (1 - tolerance); \
if (!((double) (count__) >= min_count \
&& (double) (count__) <= max_count)) { \
RTITest_assertLog( \
&RTI_TEST_LOG_EMPTY_TEMPLATE, \
"%s:[%s:%d]: value out of range: [%f, %f], count: %f\n", \
RTI_FUNCTION_NAME, \
__FILE__, \
__LINE__, \
min_count, \
max_count, \
(double) (count__)); \
failAction__; \
} \
}
/**
* @ingroup RTITestAssertion
* @brief Assert that a given value is within a given tolerance.
* @param expected__ \b In. The expected value.
* @param count__ \b In. The actual value.
* @param tolerance_percentage__ \b In. The tolerance percentage.
* @details Checks whether count__ is within a margin specified by expected__ and a
* tolerance_percentage__.
* @details Calls `goto done` if the assertion fails. Therefore, this macro requires a `done` label to be defined in the method that this assertion is called in.
*/
#define RTITest_assertMargin(expected__, count__, tolerance_percentage__) \
RTITest_assertMarginWithAction( \
expected__, \
count__, \
tolerance_percentage__, \
goto done)
/**
* @ingroup RTITestUtilities
* @brief Make a test fail with a given message.
* @param msg__ \b In. The message to be printed.
* @details Calls `goto done` if the assertion fails. Therefore, this macro requires a `done` label to be defined in the method that this assertion is called in.
*/
#define RTITest_fail(msg__) \
RTITest_assertLog( \
&RTI_TEST_LOG_EMPTY_TEMPLATE, \
"%s[%s:%d] %s\n", \
RTI_FUNCTION_NAME, \
__FILE__, \
__LINE__, \
msg__); \
goto done;
/** @internal
* @ingroup RTITestUtilities
* @brief True if Simple Participant Discovery Protocol 2 is enabled, false otherwise.
* @param participantQos__ \b In. The participant QoS.
*/
#define RTITest_isSpdp2Enabled(participantQos__) \
(participantQos__.discovery_config.builtin_discovery_plugins \
& DDS_DISCOVERYCONFIG_BUILTIN_SPDP2)
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* rtitest_assert_h */