Search code examples
cunit-testingstatic-librariesstatic-functions

Dealing with static functions when building a program as a library


To implement unit testing for one of my programs, I've added a makefile rule to build the program as a static library when "make check" is run. I wrap main() with #ifndef TEST_LIB and #endif (TEST_LIB is defined when it's built as a library).

Then I created some small C files to test some functions from that library.

Some of the functions from the library are declared statically.

Which you may guess produces warnings such as this when I try to compile the tests:

/../test/config_test.c:15:3: warning: implicit declaration of function ‘realize_home’ [-Wimplicit-function-declaration]

Because realize_home is declared statically in the source code (a .c file) for the program.

One solution I tried was to #include config_rmw.c (which contains the static functions) into the .c unit file (config_test). That actually works and doesn't give me any warnings when I compile, even though config_rmw.c is already built into the library.

Another solution I thought of was something like

#ifndef TEST_LIB
static
#endif
void function()
{
    definition
}

And adding the prototype to the header, which an #ifdef statement.

#ifdef TEST_LIB
function prototype
#endif

But doing that doesn't feel quite right, especially when it would have to be done for more functions as I proceed with implementing more unit tests.

I read in a book recently that static functions should go into a header file. I tried that but it only partially solved my problem. I wound up with compiler warnings like:

In file included from ../../src/rmw.c:38:0: ../../src/config_rmw.h:86:1: warning: ‘realize_home’ defined but not used [-Wunused-function] realize_home (char **str) ^~~~~~~~~~~~

I did some reading and I kind of understand why that happens. And basically that means I'd get a separate copy of that function in each .c file that #includes the header file where it's defined. Which I don't need. The reason I declare some functions statically is because they're only needed in one file.

Then I read some comments where people said static functions should never be defined in header files!

So... I'm stuck with wondering about the best approach and other options. I prefer to keep my programs organized and practice good coding skills.

I wrote some tests using just a script-based approach, which doesn't require my program to be built as a library, but I think there would be advantages to using both methods, depending on the functions that are being tested.

UPDATE (Addition) The program has 20 source files (including headers) and ~4K lines of code.


Solution

  • I'll do what was suggested here

    I think #including the .c file will be fine for the tests. If for some reason that ever causes trouble, the "wrapper function" approach suggested by pan64 should be an acceptable compromise.

    static void realize_home(char **)
    {
        implementation
    }
    #ifdef UNITTEST
    void test_realize_home(char **v)
    {
        realize_home(v);
    }
    #endif