mock_assert

50 views
Skip to first unread message

Steve Byan

unread,
Feb 10, 2010, 1:51:09 PM2/10/10
to cmoc...@googlegroups.com
mock_assert() is busted on LP64 64-bit platforms.

// Replacement for assert.
void mock_assert(const int result, const char* const expression,
const char* const file, const int line) {
if (!result) {
if (global_expecting_assert) {
longjmp(global_expect_assert_env, (int)expression);
} else {
print_error("ASSERT: %s\n", expression);
_fail(file, line);
}
}
}

The corresponding setjmp in the expect_assert_failure() macro casts the value back to a char * through a particularly contorted cast:

if (expression) { \
print_message("Expected assertion %s occurred\n", \
*((const char**)&expression)); \

First, why "*((const char**)&expression))" rather than "((const char *) expression)"? Second, this is totally busted on LP64 64-bit platforms; the int argument to longjump simply can't hold a pointer.

Any suggested fixes?

Best regards,
-Steve


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

Steve Byan

unread,
Feb 17, 2010, 11:51:09 PM2/17/10
to cmoc...@googlegroups.com

On Feb 10, 2010, at 1:51 PM, Steve Byan wrote:

> Second, this is totally busted on LP64 64-bit platforms; the int argument to longjump simply can't hold a pointer.
>
> Any suggested fixes?

The only idea I've come up with is to use a volatile global to pass mock_assert()'s expression parameter back to the longjmp handler. The code looks something like this:

cmockery.c:

// Replacement for assert.
volatile const char * mock_assert_message;

void mock_assert(const int result, const char* const expression,
const char* const file, const int line) {
if (!result) {
if (global_expecting_assert) {

mock_assert_message = expression;
longjmp(global_expect_assert_env, ((NULL == expression) ? 0 : 1));


} else {
print_error("ASSERT: %s\n", expression);
_fail(file, line);
}
}
}


cmockery.h:

extern volatile const char * mock_assert_message;

#define expect_assert_failure(function_call) \
{ \
mock_assert_message = NULL; \
const int expression = setjmp(global_expect_assert_env); \
global_expecting_assert = 1; \


if (expression) { \
print_message("Expected assertion %s occurred\n", \

mock_assert_message); \
global_expecting_assert = 0; \
} else { \
function_call ; \
global_expecting_assert = 0; \
print_error("Expected assert in %s\n", #function_call); \
_fail(__FILE__, __LINE__); \
} \
}


Comments?

Stewart Miles

unread,
Feb 18, 2010, 11:52:57 AM2/18/10
to cmoc...@googlegroups.com
I'm sorry I haven't been involved in many discussions recently.  It's great that some people are jumping on board with working on cmockery.

It maybe neater to place all of the globals associated with the assert into a structure.

typedef struct AssertData {
  jmp_buf assert_environment;
  int assert_expected;
  const char *assert_expression;
} AssertData;

The you end up with...

cmockery.c:

AssertData global_assert_data;

// Replacement for assert.                                                      
void mock_assert(const int result, const char* const expression,
                 const char* const file, const int line) {
    if (!result) {
        if (global_assert_data.assert_expected) {
          global_assert_data.assert_expression = expression;
          longjmp(global_assert_data.environment, 1));
        } else {
            print_error("ASSERT: %s\n", expression);
            _fail(file, line);
        }
    }
}

cmockery.h:

extern AssertData global_assert_data;

#define expect_assert_failure(function_call) \
  { \                
    const int assert_failed = setjmp(global_assert_data.environment); \
    global_assert_data.expected = 1; \
    if (assert_failed) { \
      print_message("Expected assertion %s occurred\n", \
                    global_assert_data.assert_expression ? \
                    global_assert_data.assert_expression : "(NULL)")); \
      global_assert_data.assert_expression = NULL; \
      global_assert_data.expected = 0; \
    } else { \
      function_call ; \
      global_assert_data.expected = 0; \
--
You received this message because you are subscribed to the Google Groups "Cmockery" group.
To post to this group, send email to cmoc...@googlegroups.com.
To unsubscribe from this group, send email to cmockery+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/cmockery?hl=en.


Steve Byan

unread,
Feb 23, 2010, 4:07:08 PM2/23/10
to cmoc...@googlegroups.com

On Feb 18, 2010, at 8:52 AM, Stewart Miles wrote:

> I'm sorry I haven't been involved in many discussions recently. It's great that some people are jumping on board with working on cmockery.

Thanks, it's good to hear from you.

>
> It maybe neater to place all of the globals associated with the assert into a structure.
>
> typedef struct AssertData {
> jmp_buf assert_environment;
> int assert_expected;
> const char *assert_expression;
> } AssertData;
>

Thanks, that's a great idea.

Reply all
Reply to author
Forward
0 new messages