From 4874b72f409c9c52a948e6c481afe30ebc55140d Mon Sep 17 00:00:00 2001 From: kanjoe24 <165808281+kanjoe24@users.noreply.github.com> Date: Tue, 10 Sep 2024 15:11:16 +0000 Subject: [PATCH 1/2] Adding changes to fix double evaluation in UT_ASSERT macros #106 --- .vscode/launch.json | 8 +- include/ut_cunit.h | 490 +++++++++++++++++++++++-------------- tests/src/ut_test_assert.c | 258 +++++++++++++++++++ 3 files changed, 562 insertions(+), 194 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 85fa1b4..b405703 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,10 +7,10 @@ "request": "launch", "stopAtEntry": false, "externalConsole": false, - "cwd": "${workspaceFolder}/tests/bin/", - "program": "${workspaceFolder}/tests/bin/ut-test", - "environment": [ {"name": "LD_LIBRARY_PATH", "value":"${workspaceFolder}/tests/bin/"} ], - "args": [ "-d", "1", "-e", "2", "-d", "9", "-l", "${workspaceFolder}/tests/logs/", "-p", "${workspaceFolder}/tests/bin/assets/test_kvp.yaml" ], + "cwd": "${workspaceFolder}/tests/build/bin/", + "program": "${workspaceFolder}/tests/build/bin/ut-test", + "environment": [ {"name": "LD_LIBRARY_PATH", "value":"${workspaceFolder}/tests/build/bin/"} ], + "args": [ "-l", "${workspaceFolder}/tests/logs/", "-p", "${workspaceFolder}/tests/bin/assets/test_kvp.yaml" ], "MIMode": "gdb", "miDebuggerPath": "gdb", "setupCommands": [ diff --git a/include/ut_cunit.h b/include/ut_cunit.h index c55f4b4..9c1646e 100644 --- a/include/ut_cunit.h +++ b/include/ut_cunit.h @@ -40,8 +40,8 @@ * @note Test will continue to process * */ -#define UT_PASS(msg) \ - UT_LOG_PREFIX( UT_LOG_ASCII_GREEN"PASS "UT_LOG_ASCII_NC , UT_LOG_ASCII_GREEN msg UT_LOG_ASCII_NC ); \ +#define UT_PASS(msg) \ + UT_LOG_PREFIX(UT_LOG_ASCII_GREEN "PASS " UT_LOG_ASCII_NC, UT_LOG_ASCII_GREEN msg UT_LOG_ASCII_NC); \ CU_PASS(msg); /** @@ -49,8 +49,8 @@ * @param msg - message to display * @note Test will continue to process */ -#define UT_FAIL(msg) \ - UT_LOG_PREFIX( UT_LOG_ASCII_RED"FAIL "UT_LOG_ASCII_NC, UT_LOG_ASCII_RED msg UT_LOG_ASCII_NC); \ +#define UT_FAIL(msg) \ + UT_LOG_PREFIX(UT_LOG_ASCII_RED "FAIL " UT_LOG_ASCII_NC, UT_LOG_ASCII_RED msg UT_LOG_ASCII_NC); \ CU_FAIL(msg); /** @@ -59,8 +59,8 @@ * @note Test will exit * */ -#define UT_FAIL_FATAL(msg) \ - UT_LOG_PREFIX( UT_LOG_ASCII_RED"FAIL "UT_LOG_ASCII_NC, UT_LOG_ASCII_RED msg UT_LOG_ASCII_NC ); \ +#define UT_FAIL_FATAL(msg) \ + UT_LOG_PREFIX(UT_LOG_ASCII_RED "FAIL " UT_LOG_ASCII_NC, UT_LOG_ASCII_RED msg UT_LOG_ASCII_NC); \ CU_FAIL_FATAL(msg); /** @@ -68,24 +68,30 @@ * * @param value - expression to evaluate */ -#define UT_ASSERT(value) \ - if ( !(value) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT , #value ); \ - } \ - CU_ASSERT(value); +#define UT_ASSERT(value) \ + { \ + typeof(value) _value = (value); \ + if (!_value) \ + { \ + UT_LOG_ASSERT(UT_ASSERT, #value); \ + } \ + CU_ASSERT(_value); \ + } /** * @brief Asset (make sure) the expression evaluates to true and fail otherwise and exit the test * This function is fatal * @param value - expression to evaluate */ -#define UT_ASSERT_FATAL(value) \ - if ( !(value) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_FATAL , #value ); \ - } \ - CU_ASSERT_FATAL(value); +#define UT_ASSERT_FATAL(value) \ + { \ + typeof(value) _value = (value); \ + if (!(_value)) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_FATAL, #value); \ + } \ + CU_ASSERT_FATAL(_value); \ + } /** * @brief Asset (make sure) the pointers passed are equal, otherwise fail @@ -93,12 +99,16 @@ * @param value - pointer value actual * @param expected - pointer value expected */ -#define UT_ASSERT_PTR_EQUAL(actual, expected) \ - if ( ((const void*)(actual) != (const void*)(expected)) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_PTR_EQUAL, #actual , #expected ); \ - } \ - CU_ASSERT_PTR_EQUAL(actual, expected); +#define UT_ASSERT_PTR_EQUAL(actual, expected) \ + { \ + const void *_actual = (const void *)(actual); \ + const void *_expected = (const void *)(expected); \ + if (_actual != _expected) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_PTR_EQUAL, #actual, #expected); \ + } \ + CU_ASSERT_PTR_EQUAL(_actual, _expected); \ + } /** * @brief Assert(make sure) the pointers passed are equal, otherwise fail and exit the test @@ -106,12 +116,16 @@ * @param value - pointer value actual * @param expected - pointer value expected */ -#define UT_ASSERT_PTR_EQUAL_FATAL(actual, expected) \ - if ( ((const void*)(actual) != (const void*)(expected)) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_PTR_EQUAL_FATAL , #actual , #expected ); \ - } \ - CU_ASSERT_PTR_EQUAL_FATAL(actual, expected); +#define UT_ASSERT_PTR_EQUAL_FATAL(actual, expected) \ + { \ + const void *_actual = (const void *)(actual); \ + const void *_expected = (const void *)(expected); \ + if (_actual != _expected) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_PTR_EQUAL_FATAL, #actual, #expected); \ + } \ + CU_ASSERT_PTR_EQUAL_FATAL(_actual, _expected); \ + } /** * @brief Assert(make sure) the pointers passed NOT equal @@ -119,12 +133,16 @@ * @param value - pointer value actual * @param expected - pointer value expected */ -#define UT_ASSERT_PTR_NOT_EQUAL(actual, expected) \ - if ( ((const void*)(actual) == (const void*)(expected)) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_PTR_NOT_EQUAL, #actual , #expected ); \ - } \ - CU_ASSERT_PTR_NOT_EQUAL(actual, expected); +#define UT_ASSERT_PTR_NOT_EQUAL(actual, expected) \ + { \ + const void *_actual = (const void *)(actual); \ + const void *_expected = (const void *)(expected); \ + if (_actual == _expected) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_PTR_NOT_EQUAL, #actual, #expected); \ + } \ + CU_ASSERT_PTR_NOT_EQUAL(_actual, _expected); \ + } /** * @brief Assert(make sure) the pointers passed NOT equal, otherwise fail and exit the test @@ -132,12 +150,16 @@ * @param value - pointer value actual * @param expected - pointer value expected */ -#define UT_ASSERT_PTR_NOT_EQUAL_FATAL(actual, expected) \ - if ( ((const void*)(actual) == (const void*)(expected)) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_PTR_NOT_EQUAL_FATAL, #actual , #expected ); \ - } \ - CU_ASSERT_PTR_NOT_EQUAL_FATAL(actual, expected); +#define UT_ASSERT_PTR_NOT_EQUAL_FATAL(actual, expected) \ + { \ + const void *_actual = (const void *)(actual); \ + const void *_expected = (const void *)(expected); \ + if (_actual == _expected) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_PTR_NOT_EQUAL_FATAL, #actual, #expected); \ + } \ + CU_ASSERT_PTR_NOT_EQUAL_FATAL(_actual, _expected); \ + } /** * @brief Assert(make sure) the pointer value is NULL @@ -145,12 +167,15 @@ * * @param value - pointer value */ -#define UT_ASSERT_PTR_NULL(value) \ - if ( (NULL != (const void*)(value)) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_PTR_NULL , #value ); \ - } \ - CU_ASSERT_PTR_NULL(value); +#define UT_ASSERT_PTR_NULL(value) \ + { \ + const void *_value = (const void *)(value); \ + if (NULL != _value) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_PTR_NULL, #value); \ + } \ + CU_ASSERT_PTR_NULL(_value); \ + } /** * @brief Assert(make sure) the pointer value is NULL, otherwise fail and exit the test @@ -158,36 +183,45 @@ * * @param value - pointer value */ -#define UT_ASSERT_PTR_NULL_FATAL(value) \ - if ( (NULL != (const void*)(value)) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_PTR_NULL_FATAL , #value ); \ - } \ - CU_ASSERT_PTR_NULL_FATAL(value); +#define UT_ASSERT_PTR_NULL_FATAL(value) \ + { \ + const void *_value = (const void *)(value); \ + if (NULL != _value) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_PTR_NULL_FATAL, #value); \ + } \ + CU_ASSERT_PTR_NULL_FATAL(_value); \ + } /** * @brief Assert(make sure) the pointer value is NOT NULL, otherwise fail * * @param value - pointer value */ -#define UT_ASSERT_PTR_NOT_NULL(value) \ - if ( (NULL == (const void*)(value)) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_PTR_NOT_NULL, #value ); \ - } \ - CU_ASSERT_PTR_NOT_NULL(value); +#define UT_ASSERT_PTR_NOT_NULL(value) \ + { \ + const void *_value = (const void *)(value); \ + if (NULL == _value) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_PTR_NOT_NULL, #value); \ + } \ + CU_ASSERT_PTR_NOT_NULL(_value); \ + } /** * @brief Assert(make sure) the pointer value is NOT NULL, otherwise fail and exit the test * * @param value - pointer value */ -#define UT_ASSERT_PTR_NOT_NULL_FATAL(value) \ - if ( (NULL == (const void*)(value)) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_PTR_NOT_NULL_FATAL, #value ); \ - } \ - CU_ASSERT_PTR_NOT_NULL_FATAL(value); +#define UT_ASSERT_PTR_NOT_NULL_FATAL(value) \ + { \ + const void *_value = (const void *)(value); \ + if (NULL == _value) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_PTR_NOT_NULL_FATAL, #value); \ + } \ + CU_ASSERT_PTR_NOT_NULL_FATAL(_value); \ + } /** * @brief Assert(make sure) the expression is true, otherwise fail @@ -195,12 +229,15 @@ * @param value - expression to evaluate * @see UT_ASSERT - Same condition as UT_ASSERT */ -#define UT_ASSERT_TRUE(value) \ - if ( !(value) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_TRUE, #value ); \ - } \ - CU_ASSERT_TRUE(value); +#define UT_ASSERT_TRUE(value) \ + { \ + const int _value = (value); \ + if (!_value) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_TRUE, #value); \ + } \ + CU_ASSERT_TRUE(_value); \ + } /** * @brief Assert(make sure) the expression is true, otherwise fail and exit the test @@ -208,36 +245,45 @@ * @param value - expression to evaluate * @see UT_ASSERT - Same condition as UT_ASSERT_FATAL */ -#define UT_ASSERT_TRUE_FATAL(value) \ - if ( !(value) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_TRUE_FATAL, #value ); \ - } \ - CU_ASSERT_TRUE_FATAL(value); +#define UT_ASSERT_TRUE_FATAL(value) \ + { \ + const int _value = (value); \ + if (!_value) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_TRUE_FATAL, #value); \ + } \ + CU_ASSERT_TRUE_FATAL(_value); \ + } /** * @brief Assert(make sure) the expression is false, otherwise * * @param value - expression to evaluate */ -#define UT_ASSERT_FALSE(value) \ - if ( (value) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_FALSE, #value ); \ - } \ - CU_ASSERT_FALSE(value); +#define UT_ASSERT_FALSE(value) \ + { \ + const int _value = (value); \ + if (_value) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_FALSE, #value); \ + } \ + CU_ASSERT_FALSE(_value); \ + } /** * @brief Assert(make sure) the expression is false, otherwise fail and exit the test * * @param value - expression to evaluate */ -#define UT_ASSERT_FALSE_FATAL(value) \ - if ( (value) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_FALSE_FATAL , #value ); \ - } \ - CU_ASSERT_FALSE_FATAL(value); +#define UT_ASSERT_FALSE_FATAL(value) \ + { \ + const int _value = (value); \ + if (_value) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_FALSE_FATAL, #value); \ + } \ + CU_ASSERT_FALSE_FATAL(_value); \ + } /** * @brief Assert(make sure) the two expressions are equal, otherwise fail @@ -245,12 +291,16 @@ * @param actual - actual expression * @param expected - expected expression */ -#define UT_ASSERT_EQUAL(actual,expected) \ - if ( ((actual) != (expected)) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_EQUAL , #actual , #expected ); \ - } \ - CU_ASSERT_EQUAL(actual,expected); +#define UT_ASSERT_EQUAL(actual, expected) \ + { \ + const int _actual = (actual); \ + const int _expected = (expected); \ + if (_actual != _expected) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_EQUAL, #actual, #expected); \ + } \ + CU_ASSERT_EQUAL(_actual, _expected); \ + } /** * @brief Assert(make sure) the two expressions are equal, otherwise fail and exit the test @@ -258,12 +308,16 @@ * @param actual - actual expression * @param expected - expected expression */ -#define UT_ASSERT_EQUAL_FATAL(actual,expected) \ - if ( ((actual) != (expected)) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_EQUAL_FATAL , #actual , #expected ); \ - } \ - CU_ASSERT_EQUAL_FATAL(actual,expected); +#define UT_ASSERT_EQUAL_FATAL(actual, expected) \ + { \ + const int _actual = (actual); \ + const int _expected = (expected); \ + if (_actual != _expected) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_EQUAL_FATAL, #actual, #expected); \ + } \ + CU_ASSERT_EQUAL_FATAL(_actual, _expected); \ + } /** * @brief Assert(make sure) the two expressions are NOT equal, otherwise fail @@ -271,12 +325,16 @@ * @param actual - actual expression * @param expected - expected expression */ -#define UT_ASSERT_NOT_EQUAL(actual,expected) \ - if ( ((actual) == (expected)) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_NOT_EQUAL, #actual , #expected ); \ - } \ - CU_ASSERT_NOT_EQUAL(actual,expected); +#define UT_ASSERT_NOT_EQUAL(actual, expected) \ + { \ + const int _actual = (actual); \ + const int _expected = (expected); \ + if (_actual == _expected) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_NOT_EQUAL, #actual, #expected); \ + } \ + CU_ASSERT_NOT_EQUAL(_actual, _expected); \ + } /** * @brief Assert(make sure) the two expressions are NOT equal, otherwise fail and exit the test @@ -284,12 +342,16 @@ * @param actual - actual expression * @param expected - expected expression */ -#define UT_ASSERT_NOT_EQUAL_FATAL(actual,expected) \ - if ( ((actual) == (expected)) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_NOT_EQUAL_FATAL, actual , expected ); \ - } \ - CU_ASSERT_NOT_EQUAL_FATAL(actual,expected); +#define UT_ASSERT_NOT_EQUAL_FATAL(actual, expected) \ + { \ + const int _actual = (actual); \ + const int _expected = (expected); \ + if (_actual == _expected) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_NOT_EQUAL_FATAL, #actual, #expected); \ + } \ + CU_ASSERT_NOT_EQUAL_FATAL(_actual, _expected); \ + } /** * @brief Assert(make sure) the strings are equal, otherwise fail @@ -297,12 +359,17 @@ * @param actual - actual string * @param expected - expected string */ -#define UT_ASSERT_STRING_EQUAL(expected, actual) \ - if ( (strcmp((const char*)(actual), (const char*)(expected))) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_STRING_EQUAL, actual , expected ); \ - } \ - CU_ASSERT_STRING_EQUAL(actual,expected); +#define UT_ASSERT_STRING_EQUAL(expected, actual) \ + { \ + const char *_expected = (const char *)(expected); \ + const char *_actual = (const char *)(actual); \ + const int _result = strcmp(_actual, _expected); \ + if (_result) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_STRING_EQUAL, #actual, #expected); \ + } \ + CU_ASSERT_STRING_EQUAL(_actual, _expected); \ + } /** * @brief Assert(make sure) the strings are equal, otherwise fail and exit the test @@ -310,12 +377,17 @@ * @param actual - actual string * @param expected - expected string */ -#define UT_ASSERT_STRING_EQUAL_FATAL(expected, actual) \ - if ( (strcmp((const char*)(actual), (const char*)(expected))) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_STRING_EQUAL_FATAL, actual, expected ); \ - } \ - CU_ASSERT_STRING_EQUAL_FATAL(actual,expected); +#define UT_ASSERT_STRING_EQUAL_FATAL(expected, actual) \ + { \ + const char *_expected = (const char *)(expected); \ + const char *_actual = (const char *)(actual); \ + const int _result = strcmp(_actual, _expected); \ + if (_result) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_STRING_NOT_EQUAL_FATAL, #actual, #expected); \ + } \ + CU_ASSERT_STRING_EQUAL_FATAL(_actual, _expected); \ + } /** * @brief Assert(make sure) the strings are NOT equal, otherwise fail @@ -323,12 +395,17 @@ * @param actual - actual string * @param expected - expected string */ -#define UT_ASSERT_STRING_NOT_EQUAL(expected, actual) \ - if ( !(strcmp((const char*)(actual), (const char*)(expected))) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_STRING_NOT_EQUAL , actual , expected ); \ - } \ - CU_ASSERT_STRING_NOT_EQUAL(actual,expected); +#define UT_ASSERT_STRING_NOT_EQUAL(expected, actual) \ + { \ + const char *_expected = (const char *)(expected); \ + const char *_actual = (const char *)(actual); \ + const int _result = strcmp(_actual, _expected); \ + if (!_result) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_STRING_NOT_EQUAL, #actual, #expected); \ + } \ + CU_ASSERT_STRING_NOT_EQUAL(_actual, _expected); \ + } /** * @brief Assert(make sure) the strings are NOT equal, otherwise fail and exit the test @@ -336,12 +413,17 @@ * @param actual - actual string * @param expected - expected string */ -#define UT_ASSERT_STRING_NOT_EQUAL_FATAL(expected, actual) \ - if ( !(strcmp((const char*)(actual), (const char*)(expected))) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_STRING_NOT_EQUAL_FATAL , #actual , #expected ); \ - } \ - CU_ASSERT_STRING_NOT_EQUAL_FATAL(actual,expected); +#define UT_ASSERT_STRING_NOT_EQUAL_FATAL(expected, actual) \ + { \ + const char *_expected = (const char *)(expected); \ + const char *_actual = (const char *)(actual); \ + const int _result = strcmp(_actual, _expected); \ + if (!_result) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_STRING_NOT_EQUAL_FATAL, #actual, #expected); \ + } \ + CU_ASSERT_STRING_NOT_EQUAL_FATAL(_actual, _expected); \ + } /** * @brief Assert(make sure) the expression is true, otherwise fail with the log message @@ -350,12 +432,15 @@ * @param[in] message - message to log, if the assert fails * */ -#define UT_ASSERT_MSG(value, message) \ - if ( !(value) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_MSG , (value,message) ); \ - } \ - CU_ASSERT(value); +#define UT_ASSERT_MSG(value, message) \ + { \ + const int _value = (value); \ + if (!_value) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_MSG, #value, message); \ + } \ + CU_ASSERT(_value); \ + } /** * @brief Assert(make sure) the expression is true, otherwise fail with the log message and exit the test @@ -364,12 +449,15 @@ * @param[in] message - message to log, if the assert fails * */ -#define UT_ASSERT_MSG_FATAL(value, message) \ - if ( !(value) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_MSG_FATAL , (value,message) ); \ - } \ - CU_ASSERT_FATAL(value); +#define UT_ASSERT_MSG_FATAL(value, message) \ + { \ + const int _value = (value); \ + if (!_value) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_MSG_FATAL, #value, message); \ + } \ + CU_ASSERT_FATAL(_value); \ + } /** * @brief Assert(make sure) the expression is true, otherwise fail with the log message @@ -378,12 +466,15 @@ * @param[in] message - message to log, if the expression is true * */ -#define UT_ASSERT_TRUE_MSG(value, message) \ - if ( !(value) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_TRUE_MSG, (value,message) ); \ - } \ - CU_ASSERT_TRUE(value); +#define UT_ASSERT_TRUE_MSG(value, message) \ + { \ + const int _value = (value); \ + if (!_value) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_TRUE_MSG, #value, message); \ + } \ + CU_ASSERT_TRUE(_value); \ + } /** * @brief Assert(make sure) the expression is true, otherwise fail with the log message and exit the test @@ -392,12 +483,15 @@ * @param[in] message - message to log, if the expression is true * */ -#define UT_ASSERT_TRUE_MSG_FATAL(value, message) \ - if ( !(value) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_TRUE_MSG_FATAL, (value,message) ); \ - } \ - CU_ASSERT_TRUE_FATAL(value); +#define UT_ASSERT_TRUE_MSG_FATAL(value, message) \ + { \ + const int _value = (value); \ + if (!_value) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_TRUE_MSG_FATAL, #value, message); \ + } \ + CU_ASSERT_TRUE_FATAL(_value); \ + } /** * @brief Assert(make sure) the expression is false, otherwise fail with the log message @@ -406,12 +500,15 @@ * @param[in] message - message to log, if the expression is false * */ -#define UT_ASSERT_FALSE_MSG(value, message) \ - if ( (value) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_FALSE_MSG , (value,message) ); \ - } \ - CU_ASSERT_FALSE(value); +#define UT_ASSERT_FALSE_MSG(value, message) \ + { \ + const int _value = (value); \ + if (_value) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_FALSE_MSG, #value, message); \ + } \ + CU_ASSERT_FALSE(_value); \ + } /** * @brief Assert(make sure) the expression is false, otherwise fail with the log message and exit the test @@ -420,12 +517,15 @@ * @param[in] message - message to log, if the expression is false * */ -#define UT_ASSERT_FALSE_MSG_FATAL(value, message) \ - if ( (value) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_FALSE_MSG_FATAL, (value,message) ); \ - } \ - CU_ASSERT_FALSE_FATAL(value); +#define UT_ASSERT_FALSE_MSG_FATAL(value, message) \ + { \ + const int _value = (value); \ + if (_value) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_FALSE_MSG_FATAL, #value, message); \ + } \ + CU_ASSERT_FALSE_FATAL(_value); \ + } /** * @brief Assert(make sure) the expression is true, otherwise fail but always log the message @@ -434,14 +534,19 @@ * @param[in] message - message to log, will always log * */ -#define UT_ASSERT_LOG(value, message) \ - if ( !(value) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_LOG, (value,message) ); \ - } else { \ - UT_LOG_ASSERT( UT_ASSERT_LOG, (value,message) ); \ - } \ - CU_ASSERT(value); +#define UT_ASSERT_LOG(value, message) \ + { \ + const int _value = (value); \ + if (!_value) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_LOG, #value, message); \ + } \ + else \ + { \ + UT_LOG_ASSERT(UT_ASSERT_LOG, #value, message); \ + } \ + CU_ASSERT(_value); \ + } /** * @brief Assert(make sure) the expression is true, otherwise fail and exit the test, but always log the message @@ -450,14 +555,19 @@ * @param[in] message - message to log, will always log * */ -#define UT_ASSERT_LOG_FATAL(value, message) \ - if ( !(value) ) \ - { \ - UT_LOG_ASSERT( UT_ASSERT_LOG_FATAL, (value,message) ); \ - } else { \ - UT_LOG_ASSERT( UT_ASSERT_LOG_FATAL, (value,message) ); \ - } \ - CU_ASSERT_FATAL(value); +#define UT_ASSERT_LOG_FATAL(value, message) \ + { \ + const int _value = (value); \ + if (!_value) \ + { \ + UT_LOG_ASSERT(UT_ASSERT_LOG_FATAL, #value, message); \ + } \ + else \ + { \ + UT_LOG_ASSERT(UT_ASSERT_LOG_FATAL, #value, message); \ + } \ + CU_ASSERT_FATAL(_value); \ + } #endif /* UT -> CUNIT - Wrapper */ diff --git a/tests/src/ut_test_assert.c b/tests/src/ut_test_assert.c index 6e4cd2e..15a94ae 100644 --- a/tests/src/ut_test_assert.c +++ b/tests/src/ut_test_assert.c @@ -26,6 +26,7 @@ static UT_test_suite_t * gpLogSuite = NULL; static UT_test_suite_t * gpAssertSuite = NULL; +static UT_test_suite_t * gpAssertSuite1 = NULL; int ut_init_function( void ) { @@ -100,6 +101,26 @@ void test_ut_assert( void ) UT_LOG_ERROR("### This line should never be seen\n"); } +static bool returnBool(int num) +{ + UT_LOG("Inside [%s]", __func__); + return num != 0; +} + +void test_ut_assert_for_arg_function( void ) +{ + UT_LOG_STEP( "1: is expected to pass" ); + UT_ASSERT( returnBool(1)==returnBool(1) ); + + UT_LOG_STEP( "2: is expected to fail but not fatal:" ); + UT_ASSERT( returnBool(1)==returnBool(0) ); /* This line should assert */ + + UT_LOG_STEP( "3: is expected to assert & FATAL:" ); + UT_ASSERT_FATAL( returnBool(1)==returnBool(0) ); /* This line should assert */ + + UT_LOG_ERROR("### This line should never be seen\n"); +} + void test_ut_assert_pass( void ) { UT_LOG_STEP( "1: Test UT_PASS"); @@ -135,6 +156,36 @@ void test_ut_assert_ptr_NULL() UT_LOG_ERROR("### This line should never be seen\n"); } +// Function that returns a pointer to a static integer +static int *returnPointer(int value) +{ + UT_LOG("Inside [%s]", __func__); + static int num; // Static variable to persist beyond function scope + num = value; + return # // Return the address of the static variable +} + +// Function that returns a NULL pointer +static int *returnNullPointer() +{ + UT_LOG("Inside [%s]", __func__); + return NULL; +} + +void test_ut_assert_ptr_NULL_for_arg_function() +{ + UT_LOG_STEP( "1: UT_ASSERT_PTR_NULL (returnNullPointer() == NULL ) : no assertest_ut_logging_too_long_stringt"); + UT_ASSERT_PTR_NULL( returnNullPointer() ); + + UT_LOG_STEP( "2: UT_ASSERT_PTR_NULL (returnPointer() ==
) - This step should assert"); + UT_ASSERT_PTR_NULL( returnPointer(45) ); /* Should Fail, but not fatal */ + + UT_LOG_STEP( "3: UT_ASSERT_PTR_NULL_FATAL (returnPointer() ==
) - This step should assert & FATAL"); + UT_ASSERT_PTR_NULL_FATAL( returnPointer(46) ); /* Should Fail, but not fatal */ + + UT_LOG_ERROR("### This line should never be seen\n"); +} + void test_ut_assert_ptr_equal() { int *pTR1 = (int *)1; @@ -153,6 +204,29 @@ void test_ut_assert_ptr_equal() UT_LOG_ERROR("### This line should never be seen\n"); } +static int *returnPointer1(int value) +{ + UT_LOG("Inside [%s]", __func__); + static int num1; // Static variable to persist beyond function scope + num1 = value; + return &num1; // Return the address of the static variable +} + +void test_ut_assert_ptr_equal_for_arg_function() +{ + + UT_LOG_STEP( "1: UT_ASSERT_PTR_EQUAL (returnPointer1(1) == returnPointer1(2) ) : no assert"); + UT_ASSERT_PTR_EQUAL( returnPointer1(1), returnPointer1(2) ); + + UT_LOG_STEP( "2: UT_ASSERT_PTR_EQUAL (returnPointer1(2) != returnPointer(3) ) - this step should assert"); + UT_ASSERT_PTR_EQUAL( returnPointer1(2), returnPointer(3) ); /* Should Fail */ + + UT_LOG_STEP( "3: UT_ASSERT_PTR_EQUAL (returnPointer1(2) != returnPointer(3) ) - this step should assert & FATAL"); + UT_ASSERT_PTR_EQUAL_FATAL( returnPointer1(2), returnPointer(3) ); /* Should Fail */ + + UT_LOG_ERROR("### This line should never be seen\n"); +} + void test_ut_assert_ptr_NOT_equal() { int *pTR1 = (int *)1; @@ -171,6 +245,21 @@ void test_ut_assert_ptr_NOT_equal() UT_LOG_ERROR("### This line should never be seen\n"); } +void test_ut_assert_ptr_NOT_equal_for_arg_function() +{ + + UT_LOG_STEP( "1: UT_ASSERT_PTR_NOT_EQUAL (returnPointer1(1) != returnPointer(1) ) : no assert"); + UT_ASSERT_PTR_NOT_EQUAL( returnPointer1(1), returnPointer(1) ); + + UT_LOG_STEP( "2: UT_ASSERT_PTR_NOT_EQUAL (returnPointer1(1) == returnPointer1(2) ) - This step should assert"); + UT_ASSERT_PTR_NOT_EQUAL( returnPointer1(1), returnPointer1(2) ); /* Should Fail */ + + UT_LOG_STEP( "2: UT_ASSERT_PTR_NOT_EQUAL (returnPointer1(1) == returnPointer1(2)) - This step should assert & FATAL"); + UT_ASSERT_PTR_NOT_EQUAL_FATAL( returnPointer1(1), returnPointer1(2) ); /* Should Fail */ + + UT_LOG_ERROR("### This line should never be seen\n"); +} + void test_ut_assert_ptr_NOT_NULL() { int *pTR = (int*) 1; @@ -187,6 +276,20 @@ void test_ut_assert_ptr_NOT_NULL() UT_LOG_ERROR("### This line should never be seen\n"); } +void test_ut_assert_ptr_NOT_NULL_for_arg_function() +{ + UT_LOG_STEP( "1: UT_ASSERT_PTR_NOT_NULL (returnPointer1(1) = ) : no assert"); + UT_ASSERT_PTR_NOT_NULL( returnPointer1(1) ); + + UT_LOG_STEP( "2: UT_ASSERT_PTR_NOT_NULL (returnNullPointer() == NULL ) : this step should assert"); + UT_ASSERT_PTR_NOT_NULL( returnNullPointer() ); /* Should Fail */ + + UT_LOG_STEP( "3: UT_ASSERT_PTR_NOT_NULL (returnNullPointer() == NULL ) : this step should assert & FATAL"); + UT_ASSERT_PTR_NOT_NULL_FATAL( returnNullPointer() ); /* Should Fail */ + + UT_LOG_ERROR("### This line should never be seen\n"); +} + void test_ut_assert_TRUE() { UT_LOG_STEP( "1: UT_ASSERT_TRUE ( true==true ) : No Assert "); @@ -201,6 +304,20 @@ void test_ut_assert_TRUE() UT_LOG_ERROR("### This line should never be seen\n"); } +void test_ut_assert_TRUE_for_arg_function() +{ + UT_LOG_STEP( "1: UT_ASSERT_TRUE ( returnBool(1)==returnBool(2) ) : No Assert "); + UT_ASSERT_TRUE( returnBool(1)==returnBool(2) ); + + UT_LOG_STEP( "2: UT_ASSERT_TRUE ( returnBool(1)!=returnBool(2) ) : this step should assert"); + UT_ASSERT_TRUE( returnBool(1)!=returnBool(2) ); /* Should Fail */ + + UT_LOG_STEP( "3: UT_ASSERT_TRUE ( returnBool(1)!=returnBool(2) ) : this step should assert & FATAL"); + UT_ASSERT_TRUE_FATAL( returnBool(1)!=returnBool(2) ); /* Should Fail */ + + UT_LOG_ERROR("### This line should never be seen\n"); +} + void test_ut_assert_FALSE() { UT_LOG_STEP( "1: UT_ASSERT_FALSE ( true==false ) : No Assert "); @@ -215,6 +332,20 @@ void test_ut_assert_FALSE() UT_LOG_ERROR("### This line should never be seen\n"); } +void test_ut_assert_FALSE_for_arg_function() +{ + UT_LOG_STEP( "1: UT_ASSERT_FALSE ( returnBool(1)==returnBool(0) ) : No Assert "); + UT_ASSERT_FALSE( returnBool(1)==returnBool(0) ); + + UT_LOG_STEP( "2: UT_ASSERT_FALSE ( returnBool(1)!=returnBool(0) ) : this step should assert"); + UT_ASSERT_FALSE( returnBool(1)!=returnBool(0) ); /* Should fail */ + + UT_LOG_STEP( "2: UT_ASSERT_FALSE ( returnBool(1)!=returnBool(0) ) : this step should assert & FATAL"); + UT_ASSERT_FALSE_FATAL( returnBool(1)!=returnBool(0) ); /* Should fail */ + + UT_LOG_ERROR("### This line should never be seen\n"); +} + void test_ut_assert_EQUAL( void ) { UT_LOG_STEP( "1: UT_ASSERT_EQUAL ( true, true ) : PASS"); @@ -229,6 +360,20 @@ void test_ut_assert_EQUAL( void ) UT_LOG_ERROR("### This line should never be seen\n"); } +void test_ut_assert_EQUAL_for_arg_function( void ) +{ + UT_LOG_STEP( "1: UT_ASSERT_EQUAL ( returnBool(1), returnBool(2) ) : PASS"); + UT_ASSERT_EQUAL( returnBool(1), returnBool(2) ); + + UT_LOG_STEP( "2: UT_ASSERT_EQUAL ( returnBool(1), returnBool(0) ) : : this step should assert " ); + UT_ASSERT_EQUAL( returnBool(1), returnBool(0) ); /* Should FAIL */ + + UT_LOG_STEP( "3: UT_ASSERT_EQUAL ( returnBool(1), returnBool(0) ) : : this step should assert & FATAL" ); + UT_ASSERT_EQUAL_FATAL( returnBool(1), returnBool(0) ); /* Should FAIL */ + + UT_LOG_ERROR("### This line should never be seen\n"); +} + void test_ut_assert_STRING_EQUAL( void ) { UT_LOG_STEP( "1: UT_ASSERT_STRING_EQUAL ( bob, bob ) : No Assert "); @@ -243,6 +388,32 @@ void test_ut_assert_STRING_EQUAL( void ) UT_LOG_ERROR("### This line should never be seen\n"); } +static const char *returnString() +{ + UT_LOG("Inside [%s]", __func__); + return "bob"; +} + +static const char *returnString1() +{ + UT_LOG("Inside [%s]", __func__); + return "fred"; +} + +void test_ut_assert_STRING_EQUAL_for_arg_function( void ) +{ + UT_LOG_STEP( "1: UT_ASSERT_STRING_EQUAL ( returnString(), returnString() ) : No Assert "); + UT_ASSERT_STRING_EQUAL( returnString(), returnString() ); + + UT_LOG_STEP( "2: UT_ASSERT_STRING_EQUAL ( returnString(), returnString1() ) : : this step should assert"); + UT_ASSERT_STRING_EQUAL( returnString(), returnString1() ); /* Should FAil */ + + UT_LOG_STEP( "3: UT_ASSERT_STRING_EQUAL ( returnString(), returnString1() ) : : this step should assert & FATAL"); + UT_ASSERT_STRING_EQUAL_FATAL( returnString(), returnString1() ); /* Should FAil */ + + UT_LOG_ERROR("### This line should never be seen\n"); +} + void test_ut_assert_STRING_NOT_EQUAL( void ) { UT_LOG_STEP( "1: UT_ASSERT_STRING_NOT_EQUAL ( bob, fred ) : no assert"); @@ -257,6 +428,20 @@ void test_ut_assert_STRING_NOT_EQUAL( void ) UT_LOG_ERROR("### This line should never be seen\n"); } +void test_ut_assert_STRING_NOT_EQUAL_for_arg_function( void ) +{ + UT_LOG_STEP( "1: UT_ASSERT_STRING_NOT_EQUAL ( returnString(), returnString1() ) : no assert"); + UT_ASSERT_STRING_NOT_EQUAL( returnString(), returnString1() ); + + UT_LOG_STEP( "2: UT_ASSERT_STRING_NOT_EQUAL ( returnString(), returnString() ) : this step should assert"); + UT_ASSERT_STRING_NOT_EQUAL( returnString(), returnString() ); /* Should FAIL */ + + UT_LOG_STEP( "3: UT_ASSERT_STRING_NOT_EQUAL ( returnString(), returnString() ) : this step should assert & FATAL"); + UT_ASSERT_STRING_NOT_EQUAL_FATAL( returnString(), returnString() ); /* Should FAIL */ + + UT_LOG_ERROR("### This line should never be seen\n"); +} + void test_ut_assert_msg( void ) { UT_LOG_STEP( "1: is expected not to assert" ); @@ -273,6 +458,22 @@ void test_ut_assert_msg( void ) UT_LOG_ERROR("### This line should never be seen\n"); } +void test_ut_assert_msg_for_arg_function( void ) +{ + UT_LOG_STEP( "1: is expected not to assert" ); + UT_ASSERT_MSG( returnBool(1)==returnBool(1), "should not assert"); + + UT_LOG( "This test should cause 2 assert checks, so a test pass, it will quit the test early" ); + + UT_LOG_STEP( "2: is expected to fail" ); + UT_ASSERT_MSG( returnBool(0)==returnBool(1), "Step 2 : Asserted Correctly if you see this message :"); /* This line should assert */ + + UT_LOG_STEP( "3: is expected to fail" ); + UT_ASSERT_MSG_FATAL( returnBool(0)==returnBool(1), "Step 2 : Asserted Correctly if you see this message :"); /* This line should assert & FATAL*/ + + UT_LOG_ERROR("### This line should never be seen\n"); +} + void test_ut_assert_msg_true( void ) { UT_LOG_STEP( "1: is expected not to assert" ); @@ -289,6 +490,22 @@ void test_ut_assert_msg_true( void ) UT_LOG_ERROR("### This line SHOULD never be seen\n"); } +void test_ut_assert_msg_true_for_arg_function( void ) +{ + UT_LOG_STEP( "1: is expected not to assert" ); + UT_ASSERT_TRUE_MSG( returnBool(1)==returnBool(1), "should not assert"); + + UT_LOG( "This test should cause 2 assert checks, so a test pass, it will quit the test early" ); + + UT_LOG_STEP( "2: is expected to fail" ); + UT_ASSERT_TRUE_MSG( returnBool(0)==returnBool(1), "Step 2 : Asserted Correctly if you see this message :"); /* This line should assert */ + + UT_LOG_STEP( "3: is expected to fail" ); + UT_ASSERT_TRUE_MSG_FATAL( returnBool(0)==returnBool(1), "Step 3 : Asserted Correctly if you see this message :"); /* This line should assert & FATAL*/ + + UT_LOG_ERROR("### This line SHOULD never be seen\n"); +} + void test_ut_assert_msg_false( void ) { UT_LOG_STEP( "1: is expected not to assert" ); @@ -305,6 +522,22 @@ void test_ut_assert_msg_false( void ) UT_LOG_ERROR("### This line SHOULD never be seen\n"); } +void test_ut_assert_msg_false_for_arg_function( void ) +{ + UT_LOG_STEP( "1: is expected not to assert" ); + UT_ASSERT_FALSE_MSG( returnBool(1)==returnBool(0), "should not assert"); + + UT_LOG( "This test should cause 2 assert checks, so a test pass, it will quit the test early" ); + + UT_LOG_STEP( "2: is expected to fail" ); + UT_ASSERT_FALSE_MSG( returnBool(1)==returnBool(1), "Step 2 : Asserted Correctly if you see this message :"); /* This line should assert */ + + UT_LOG_STEP( "3: is expected to fail" ); + UT_ASSERT_FALSE_MSG_FATAL( returnBool(1)==returnBool(1), "Step 3 : Asserted Correctly if you see this message :"); /* This line should assert & FATAL */ + + UT_LOG_ERROR("### This line SHOULD never be seen\n"); +} + void test_ut_assert_log( void ) { UT_ASSERT_LOG( true==true, "Step 1: ASSERT_LOG : should log and NOT fail :"); @@ -313,6 +546,14 @@ void test_ut_assert_log( void ) UT_LOG_INFO("+++ This line SHOULD be seen\n"); } +void test_ut_assert_log_for_arg_function( void ) +{ + UT_ASSERT_LOG( returnBool(1)==returnBool(1), "Step 1: ASSERT_LOG : should log and NOT fail :"); + UT_ASSERT_LOG( returnBool(1)==returnBool(0), "Step 2: ASSERT_LOG : should log and NOT fail :"); /* This line should assert */ + + UT_LOG_INFO("+++ This line SHOULD be seen\n"); +} + /** * @brief Main launch function for assert functions */ @@ -345,5 +586,22 @@ void register_assert_functions(void) UT_add_test( gpAssertSuite, "UT_ASSERT_TRUE_MSG", test_ut_assert_msg_true); UT_add_test( gpAssertSuite, "UT_ASSERT_FALSE_MSG", test_ut_assert_msg_false); UT_add_test( gpAssertSuite, "UT_ASSERT Log", test_ut_assert_log); + + gpAssertSuite1 = UT_add_suite("ut-core-assert-tests-with_function_args", ut_init_function, ut_clean_function); + assert(gpAssertSuite1 != NULL); + UT_add_test( gpAssertSuite1, "UT_ASSERT ptr_NULL with function as args", test_ut_assert_ptr_NULL_for_arg_function); + UT_add_test( gpAssertSuite1, "UT_ASSERT ptr_equal with function as args", test_ut_assert_ptr_equal_for_arg_function); + UT_add_test( gpAssertSuite1, "UT_ASSERT with function as args", test_ut_assert_for_arg_function); + UT_add_test( gpAssertSuite1, "UT_ASSERT ptr_NOT_equal with function as args", test_ut_assert_ptr_NOT_equal_for_arg_function); + UT_add_test( gpAssertSuite1, "UT_ASSERT ptr_NOT_NULL with function as args", test_ut_assert_ptr_NOT_NULL_for_arg_function); + UT_add_test( gpAssertSuite1, "UT_ASSERT TRUE with function as args", test_ut_assert_TRUE_for_arg_function); + UT_add_test( gpAssertSuite1, "UT_ASSERT FALSE with function as args", test_ut_assert_FALSE_for_arg_function); + UT_add_test( gpAssertSuite1, "UT_ASSERT EQUAL with function as args", test_ut_assert_EQUAL_for_arg_function); + UT_add_test( gpAssertSuite1, "UT_ASSERT STRING_EQUAL with function as args", test_ut_assert_STRING_EQUAL_for_arg_function); + UT_add_test( gpAssertSuite1, "UT_ASSERT STRING_NOT_EQUAL with function as args", test_ut_assert_STRING_NOT_EQUAL_for_arg_function); + UT_add_test( gpAssertSuite1, "UT_ASSERT MSG with function as args", test_ut_assert_msg_for_arg_function); + UT_add_test( gpAssertSuite1, "UT_ASSERT MSG_TRUE with function as args", test_ut_assert_msg_true_for_arg_function); + UT_add_test( gpAssertSuite1, "UT_ASSERT MSG_FALSE with function as args", test_ut_assert_msg_false_for_arg_function); + UT_add_test( gpAssertSuite1, "UT_ASSERT LOG with function as args", test_ut_assert_log_for_arg_function); } From 8e3602c14e44fb695c341e280063f7f8fceed54d Mon Sep 17 00:00:00 2001 From: kanjoe24 <165808281+kanjoe24@users.noreply.github.com> Date: Fri, 13 Sep 2024 10:32:08 +0000 Subject: [PATCH 2/2] CHANGELOG.md 3.2.3 --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b50c68..18b3676 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,18 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [3.2.3](https://github.com/rdkcentral/ut-core/compare/3.2.2...3.2.3) + +- PR: i106: Adding changes to fix double evaluation in UT_ASSERT macros [`#109`](https://github.com/rdkcentral/ut-core/pull/109) +- Adding changes to fix double evaluation in UT_ASSERT macros #106 [`4874b72`](https://github.com/rdkcentral/ut-core/commit/4874b72f409c9c52a948e6c481afe30ebc55140d) +- Merge tag '3.2.2' into develop [`81bdd52`](https://github.com/rdkcentral/ut-core/commit/81bdd52a6cf63b897c00b6bb89789280cdeabb69) + #### [3.2.2](https://github.com/rdkcentral/ut-core/compare/3.2.1...3.2.2) +> 5 September 2024 + - Update the current ut-control version to 1.4.2 [`#105`](https://github.com/rdkcentral/ut-core/pull/105) +- CHANGELOG.md 3.2.2 [`0719725`](https://github.com/rdkcentral/ut-core/commit/07197257137dec08c24669e4318a45f6ec0ecc3d) - Update the current ut-control version to 1.4.2 #104 [`9496235`](https://github.com/rdkcentral/ut-core/commit/9496235b8adfc79f01b22bb55ddec5f28e8958f6) - Merge tag '3.2.1' into develop [`daa77e5`](https://github.com/rdkcentral/ut-core/commit/daa77e5c0a9a77ede7baa0b833eb99a3fce4e2e1)