Mocking functions declared in nested headers, and union issues?

507 views
Skip to first unread message

ILikeFish

unread,
Aug 10, 2012, 6:36:26 AM8/10/12
to throwth...@googlegroups.com
Hi,

I've been using Ceedling for a while, and am now trying to generate CMock mocks for a module that has nested headers.  Is it possible to generate mocks for the functions declared in those nested headers (at least those included using "" rather than <>)?  I am already using :use_test_preprocessor: TRUE.

Also, the code has the following:

typedef union {
  UINT32 uclass;
  UINT8 ubytes[sizeof(UINT32)];
} T_MB_MClass;

When mocks are generated for a function that uses this, I get compiler errors:

build/test/mocks/MockMB_Register.c:373:21: warning: comparison between pointer and integer [enabled by default]
build/test/mocks/MockMB_Register.c:377:28: error: invalid operands to binary == (have ‘T_MB_MClass’ and ‘void *’)

Is there any way round this?

       Gem:: 0.12.2
  Ceedling:: 0.10.226
CException:: 1.2.20
     CMock:: 2.0.217
     Unity:: 2.0.137

Thanks
J

Mark Vander Voord

unread,
Aug 10, 2012, 7:09:16 AM8/10/12
to throwth...@googlegroups.com
Hi

CMock will purposefully not follow all your includes and mock those too... that leads to all sorts of linking nightmares where you have real versions of functions and mocked versions of functions trying to be used at the same time.

The solution, however, is pretty straightforward, if I understand what you are looking for correctly.  In your test file, you just need to add a #include for the included headers that you also would like mocked.  If this becomes tedious and you find yourself including the same list of files over and over again, you can always make a header file which is a collection of the function prototypes you mock often, and just generate a mock for that in your tests.  This is actually a pretty useful approach and serves to document the "public API" portion of those files.

Concerning the union issues, from the error you listed it seems like CMock is trying to treat your custom type as a pointer, which seems strange.  If you read up on using :treat_as you can figure out how to control how CMock treats custom types.  If you would like more help from us, I'm happy to.  Please post the function prototype that is getting mocked and the mock that is generated where the error is listed.  We can figure out what is going on more quickly if we look at some code, I bet.  :)

I hope this helps,

Mark

schwar...@gmail.com

unread,
Sep 21, 2012, 5:33:36 AM9/21/12
to throwth...@googlegroups.com
Hi,

I have the same error so here is the code generated:
void ppd_StartShortingOnly(Ppd_t* this, ShortingDefinition_t ShortingDefinition) 
{                                                                                
  UNITY_LINE_TYPE cmock_line = TEST_LINE_NUM;                                    
  CMOCK_ppd_StartShortingOnly_CALL_INSTANCE* cmock_call_instance = (CMOCK_ppd_StartShortingOnly_CALL_INSTANCE*)CMock_Guts_GetAddressFor(Mock.ppd_StartShortingOnly_CallInstance);
  Mock.ppd_StartShortingOnly_CallInstance = CMock_Guts_MemNext(Mock.ppd_StartShortingOnly_CallInstance);
  if (Mock.ppd_StartShortingOnly_IgnoreBool)                                     
  {                                                                              
    return;                                                                      
  }                                                                              
  if (Mock.ppd_StartShortingOnly_CallbackFunctionPointer != NULL)                
  {                                                                              
    Mock.ppd_StartShortingOnly_CallbackFunctionPointer(this, ShortingDefinition, Mock.ppd_StartShortingOnly_CallbackCalls++);
    return;                                                                      
  }                                                                              
  UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, "Function 'ppd_StartShortingOnly' called more times than expected.");
  cmock_line = cmock_call_instance->LineNumber;                                  
  if (cmock_call_instance->Expected_this == NULL)                                
    { UNITY_TEST_ASSERT_NULL(this, cmock_line, "Expected NULL. Function 'ppd_StartShortingOnly' called with unexpected value for argument 'this'."); }
  else if (cmock_call_instance->Expected_this_Depth == 0)                        
    { UNITY_TEST_ASSERT_EQUAL_PTR(cmock_call_instance->Expected_this, this, cmock_line, "Function 'ppd_StartShortingOnly' called with unexpected value for argument 'this'."); }
  else                                                                           
    { UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(cmock_call_instance->Expected_this), (void*)(this), sizeof(Ppd_t), cmock_call_instance->Expected_this_Depth, cmock_line, "Function 'ppd_StartShortingOnly' called with unexpected value for argument 'this'."); }
  if (&cmock_call_instance->Expected_ShortingDefinition == NULL)                 
    { UNITY_TEST_ASSERT_NULL(ShortingDefinition, cmock_line, "Expected NULL. Function 'ppd_StartShortingOnly' called with unexpected value for argument 'ShortingDefinition'."); }
  else                                                                           
    { UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(&cmock_call_instance->Expected_ShortingDefinition), (void*)(&ShortingDefinition), sizeof(ShortingDefinition_t), 1, cmock_line, "Function 'ppd_StartShortingOnly' called with unexpected value for argument 'ShortingDefinition'."); }
}  

This is the typedef:
typedef struct
{   uint16_t            ShortingInMs;
    Bool                crossFilterShortingAndReset;
    uint16_t            FilterShortingInMs;
    uint16_t            FilterSlowingInMs;
} ShortingDefinition_t;


And here comes the prototype:
void ppd_StartShortingOnly(Ppd_t * this ,ShortingDefinition_t ShortingDefinition);



Thanks!

mvandervoord

unread,
Sep 21, 2012, 7:45:44 AM9/21/12
to throwth...@googlegroups.com, schwar...@gmail.com
The ideal solution would be to create a unity_helper file and give this type a nice way to handle this new type.  This isn't necessary to getting it to work, though.  You should be able to just add the type to your :treat_as in your config file... maybe something like this:

:cmock:
  :treat_as:
    ShortingDefinition_t: MEMORY

I believe that should force it to treat that as a memory comparison.  This might be tricky, though, because your bool_t is likely a byte, leaving a byte of padding that is outside your control.  When it does the memory comparison, it's possible that this will not be the same in both cases.  You could force the entire structure to zero before writing to it, which would help.

Another thing to verify is that you have the latest CMock release... old versions didn't have as much support for this stuff.

If you still have problems, can you post a portion of your header being mocked (enough to reproduce the issue)  and the configuration yaml file you are using? 

Good luck

Mark

schwar...@gmail.com

unread,
Sep 21, 2012, 8:20:21 AM9/21/12
to throwth...@googlegroups.com, schwar...@gmail.com
Hi Mark,

thanks for this fast answer. Unfortunately it wasn't helping.

But while creating the header, I experimented with c-mock without our standard yaml file - tada this worked. It seems that
:cmock:                                                                                                                                     
  :plugins:                                                                      
    - :array
was the one giving me these headaches.

Therefore: Thanks for poking me in the right direction ;)

Simon                                        

mvandervoord

unread,
Sep 21, 2012, 9:56:54 AM9/21/12
to throwth...@googlegroups.com, schwar...@gmail.com
Interesting.  So when you disabled the :array plugin, the problem went away?  Apparently we have an issue with our array plugin.  I'll check into that.  Thanks for letting us know.  :)

Mark
Reply all
Reply to author
Forward
0 new messages