Writing a macro such that static is disabled when testing

293 Views Asked by At

I am having trouble writing this macro. I am using ceedling.

I have a file, "globals.h", which has the following code:

#ifndef globals
    #ifndef UNITY
        #define STATIC static
    #else
        #define STATIC
    #endif
    #define globals 1
#endif

So, what should happen here is that any method which uses STATIC will be static if the code is not being tested with unity, else it will be not static.

My test file includes "unity.h", and then includes "globals.h", and then includes "protocol.h".

The file being tested, "protocol.c", includes "globals.h" and then "protocol.h".

The test file, "test_protocol.c", includes "unity.h", then "globals.h", then "protocol.h".

From my understanding, UNITY should be defined first, then it will go to globals.h, and define STATIC as nothing, since UNITY has been defined already in UNITY.h

However, the behavior I am seeing is that no matter what I do, I cannot get globals.h to enter that #else directive, and so it appears to be impossible to have STATIC be defined as anything other than static.

However, I know that what i am trying to accomplish is possible, because many people recommend this strategy and have implemented it. So, what am I doing that is causing globals.h to think that UNITY is not defined, when it is?

1

There are 1 best solutions below

0
On

test_protocol.c doesn't need to include globals.h file. The point of view from test_protocol.c is that everything in protocol.c has external linkage, but itself doesn't need that.

Because protocol.c and test_protocol.c are in different translation unit, UNITY defined in UNITY.h is not seen in protocol.c because it doesn't include UNITY.h.

Of course, the code under test must be kept intact. So we must somehow tell protocol.c about UNITY flag during the test but not in the normal compilation. That is where the section :defines: in the yaml file shines.

The project.yml file has already defined a TEST macro:

:defines:
  # in order to add common defines:
  #  1) remove the trailing [] from the :common: section
  #  2) add entries to the :common: section (e.g. :test: has TEST defined)
  :common: &common_defines []
  :test:
    - *common_defines
    - TEST                      # <--- here
  :test_preprocess:
    - *common_defines
    - TEST                      # <--- and here

You need to define UNITY in here too or just use the TEST macro in your globals.h. The TEST macros are there for this purpose anyway.

This ensures the flag TEST is passed to every translation unit if it is compiled by ceedling for testing, but not there if you use the normal compiler as usual.