mock_assert breakage

14 views
Skip to first unread message

Steve Byan

unread,
Feb 16, 2010, 4:06:27 PM2/16/10
to cmoc...@googlegroups.com
mock_assert is declared to accept an integer as its first argument:

void mock_assert(const int result, const char* const expression,
const char* const file, const int line)

The example tests then substitute mock_assert for the standard C assert macro:

#undef assert
#define assert(expression) \
mock_assert((int)(expression), #expression, __FILE__, __LINE__);

However, this is incorrect, as assert is required to accept a pointer as its expression, as many of the cmockery examples do. See for example assert_module.c.

First, a NULL pointer is not guaranteed have a zero bit pattern; mock_assert implicitly assumes that it does. The standard C assert handles this correctly but cmockery does not. Second, even on platforms where NULL has the zero bit-pattern but where a pointer is larger than an int, cmockery's assert may incorrectly slice off the high-order bits of a pointer, causing a) incorrect assertion failures and b) failure to correctly display the value of the assert expression.

I'm thinking of a fix along the lines of adding an additional parameter to mock_assert to contain the value of the expression:

void mock_assert(const int result, const LargestIntegralType value, const char* const expression,
const char* const file, const int line)

and then changing the assert macro to something like this:

#undef assert
#define assert(expression) \
mock_assert((expression), cast_to_largest_integral_type(expression), #expression, __FILE__, __LINE__)

This implies that the code-under-test will have to #include <cmockery.h> when UNIT_TESTING is true, or at least some cmockery_assert.h subset.

I don't see a way around including a header without losing the ability to pass the bit-value of the expression on to mock_assert. On my system, the standard C assert uses a hack something like this:

#define assert(expression) \
((void) ((expression) ? 0 : mock_assert(#expression, __FILE__, __LINE__)

where mock_assert assumes it's only called with a false assertion. This avoids the sticky pointer/integral type issue, but doesn't allow mock_assert to access the value of the expression.


BTW, the assert macro definition really shouldn't have a semicolon at the end.

Best regards,
-Steve

--
Steve Byan <stev...@me.com>
Littleton, MA 01460

Steve Byan

unread,
Feb 16, 2010, 4:42:24 PM2/16/10
to cmoc...@googlegroups.com

On Feb 16, 2010, at 4:06 PM, Steve Byan wrote:

> and then changing the assert macro to something like this:
>
> #undef assert
> #define assert(expression) \
> mock_assert((expression), cast_to_largest_integral_type(expression), #expression, __FILE__, __LINE__)

oops, make that:

mock_assert(((expression) ? 1 : 0) , cast_to_largest_integral_type(expression), #expression, __FILE__, __LINE__)

Reply all
Reply to author
Forward
0 new messages