Ceedling/CMock: how to make parts of a .h file visible for Cmock only

1.4k Views Asked by At

In my module there are function like macros. This is no obstacle for a module test, but it is an obstacle for other modules which include this module.

My question: is there a way to make a part of the .h file visible for CMock only?

e.g.:

Module_1.h:

#ifdef MODULE_TEST_CMOCK
    void FunctionLikeMacro_1(unsigned int x);
    unsigned int FunctionLikeMacro_2(void);
#else
    #define FunctionLikeMacro_1(x) (HWREGISTER_1 = (unsigned int)x)
    #define FunctionLikeMacro_2 ((unsigned int)HWREGISTER_2)
#endif

This is the way I would prefer. But where should I define MODULE_TEST_CMOCK? I can't define it in the Project.yml because with this change, my module tests for Module_1 would fail. But on the other hand, in my module tests for Module_2, which needs a mocked version of Module_1.h, I can't expect calls of FunctionLikeMacro_1 and FunctionLikeMacro_2.

Thank you for your time. :)

2

There are 2 best solutions below

0
On

According to docs/CeedlingPacket.md, you can add specific defines to each test file that is to be compiled to the :defines: section in project.yml:

defines: command line defines used in test and release compilation by configured tools

...

<test_name>:

Add preprocessor definitions for specified . For example:

:defines:
  :test_foo_config:
    - FOO_SPECIFIC_FEATURE

So in your case, you would have to add MODULE_TEST_CMOCK for all test files in which want to mock Module_1.h to the :defines: seciton in project.yml.

I tried it using your example header file two test files: test/test_module1.c which included Module_1.h directly and test/test_module2.c which included mock_Module_1.h. I added this to my project.yml:

:defines:
  :test_module2:
    - MODULE_TEST_CMOCK

And this seemed to work fine. I could use FunctionLikeMacro_2_IgnoreAndReturn() from test/test_module2.c and the tests behaved as expected, while the macros were being used directly for the tests in test/test_module1.c.

0
On

When Ceedling compiles and builds your tests it does so with a define TEST set so you can write you header files to change their nature when compiled for test. So for example if you are doing embedded work and you do all your register I/O via macros, you can convert then to functions for unit testing and then just mock them.

// my_reg_io.h

#ifndef TEST  // production code

#define WRITE_REG(add, val) *(add) = (val)
#define READ_REG(add)  *(add)

#else  // test code
// mockable prototypes
void _my_fake_write(void *add, int val);
int _my_fake_read(void *add);

#define WRITE_REG(add, val) _my_fake_write((add), (val))
#define READ_REG(add)  _my_fake_read(add)

#endif

In the case of the read, you can use the stub mock to inject behavior into your code to test hardware interfaces without the need for hardware. Super useful.