Mock/Wrap static functions called by a non-static function under test - c

I would like to test some functions by implementing unit tests with cmocka framework.
For example I have a non-static function under test which calls two static functions. Because of the fact that these static functions interact with hardware I want to mock/wrap them and use a wrap function instead of the real function when testing.
Like described in the cmocka documentation I've used the --wrap=myfunction linker flags when building/linking my tests.
The tests compile but when I run them the real static functions will be called instead of the wraps.
When I declare the static functions non-static it doesn't work either and also the real functions are called. The only solution I've found is to outsource the functions in an extra .c-file...but that's a really bad workaround because it manipulates the code very much.

As #Paul wrote, this is simply how --wrap works, the functions need to be in a different compilation unit if you want gcc to wrap them. Generally, static methods are private implementation details which you don't want to expose for testing.
So to add some more options to the other answer:
Obviously, the simplest way to mock these functions without polluting the original code with conditionals is to extract them into a separate layer (in this case, a HAL).
You can make the static modifier conditional, which will allow wrapping with cmocka. This does less polluting to the original code than a bunch of #ifdefs:
#ifndef UNIT_TESTING
# define mockable_static static
#else
# define mockable_static
#endif
// then, replace 'static' with 'mockable_static'
mockable_static void some_static_method(void) {
...
}
Use objcopy to globalize and weaken selected static functions, as explained in this answer.

If you have a .c file with a public function and two static functions, and the public function calls the static functions, then you cannot prevent the static functions being called. After all, they are one compilation unit.
You can:
test them as a whole
use #ifdef conditional compilation to replace the static functions with simplified, non-hardware calling static functions to test the public function
use #ifdef conditional compilation to replace the public function with a specialised public function to test the static functions.

Related

Best way to abstract away an init function?

I am making a low level library that requires initialization to work properly which I implemented with a init function. I am wondering if there is a way to make the init call be called once the user calls a library function ideally without:
Any overhead
No repeated calls
No exposed global variables. (my current solution does this, which I don't quite like)
my current solution as per comment request:
bool isinit = 0;
void init()
{
isinit = 1;
// init code
}
void lib_function()
{
if(!isinit) init();
// function code
}
The compiler seems to be smart enough (using -0fast on gcc) to not make that comparison each time a lib_function is called, but this still exposes a global variable which I don't like.
Best way to abstract away an init function?
Surely your library has some state. Typically, a library exposes functions that work on a specific structure. Do not use global variables - do not write spaghetti code. Expose the structure that holds the state of your library, and make all functions of your library take a pointer to the structure as an argument. Use a namespace - prepend all exported symbols with a prefix. An init function is just like int lib_init(struct lib_the_struct *t); - it will be self-understandable that users need to initialize the structure with that function before use. For example: fopen(), pthread_create.
Write an init function in your library. Write clear documentation stating, that the user of your library has to call the function once before calling any other function. For example: https://curl.se/libcurl/c/curl_global_init.html .
If you're happy with a solution that is a common extension rather than part of the C standard, you can mark your init function with the constructor attribute, which ensures it will be called automatically during program initialization (or during shared library load if you eventually end up using that).
I would fix this with assert so that the if will dissappear in release build and if you forget to call the init_function somewhere you get the error while developing.
Also turn isinit into a static so every library can have its own variable with the same name.
#include <assert.h>
#ifndef NDEBUG
static int isinit = 0;
#endif
void lib_function()
{
assert(isinit && "library: init not called");
}
There will be overhead if you run if(!isinit) init(); each time you call a function. At least an extra branch.
As for removing global variables, do in your example but static bool isinit = 0;. This reduces the scope of the variable to the local translation unit (.c file and all .h files it includes). It's no longer "global". Note that this isn't ideal in multi-threaded scenarios - you will have to protect the variable with a mutex then.
Overall though, what you are trying to do isn't a good idea. It is very common convention for C libraries to have an init function and the user of the library is expected to call it before calling anything else or they are to blame, not your library. Naturally you have to make this clear to them with source code documentation. It is common to have a list of prerequisites in source code comments together with every function declaration placed in the header file of the library.

What happens if I don't declare all functions in header?

I'm currently practicing a unit test with GTest, and noticed that I didn't declare all functions written on the target source code (target.c) to its header (target.h). Since I didn't do the test for those undeclared functions, I couldn't notice until now.
Now, it seems that those header-undeclared functions work as 'private' functions since they are not callable from the test code (which includes header of the target source code).
Can I consider this as a way to declare a private function or should I be aware of something else for safety?
No. that does not make your function private. It just then requires the caller to extern that function themselves. Using the static key word is the appropriate way to create a private function. Eg:
static void myfunc ()
{
...
}
Not including it in the header doesn't make it a private function, since any other C file could add an extern void myfunc() in either their header or C code and gain access to that function. At compile time, all of that is going to be linked (assuming you are compiling all the files).
BUT all static objects will only have module level (or file scope) visibility
The same goes for variables you only want in the filescope.

nesting preprocessor directives or other trickery to conditionally redefine the static keyword

I am using unity for unit testing.
I have a header throughout my project that I include with some helper macros, like an assert wrapper that I can use to track which assert fired.
In that header I also have the following definition:
#define static //nothing
I learned that little trick from this article:
http://www.embedded.com/design/programming-languages-and-tools/4007177/2/Doing-C-code-unit-testing-on-a-shoestring-Part-1-The-basics-and-the-tools
This allows me to write unit tests for static functions and it allows me to access any relevant file scope data from my test harness.
The trouble is this totally breaks static at the function scope. The article goes on to say if I do this:
#define static extern
Then any variable that is static at the function scope can then be defined within the test harness. We're off to the races, right? Not exactly.
Because the following occurs
void foo()
{
extern bool my_flag = false;
}
Now we are supplying an initializer to declaration, which is invalid. So that means any static variable I handled this way would inherently need to be initialized after startup.
Because static variables within functions are relatively uncommon, I thought I might circumvent this by defining a new symbol, LOCAL_STATIC. So now in my header I have the following
#define static extern
#define LOCAL_STATIC static
But that does not work because those directives are evaluated strictly in order - #define LOCAL_STATIC static becomes #define LOCAL_STATIC extern, or at least that is what seems to be happening. Because LOCAL_STATIC produces the same error and indeed ends up getting changed to extern by the preprocessor.
So is there any way around this?
AFAIK anything like this is impossible:
#define LOCAL_STATIC \
#undef static \
static \
#define static extern
The only thing I can think of is to leave static alone and define a new symbol, something like HARNESS_ACCESSIBLE.
#ifdef UNIT_TEST
#define HARNESS_ACCESSIBLE extern
#else
#define HARNESS_ACCESSIBLE static
#endif
But that is going to clutter up the production code with this new weird thing "HARNESS_ACCESSIBLE". Static variables within functions are generally rare, but almost all static functions (except trivial helper functions) will need to be externally accessible by my test runner.
I've been trying to avoid writing a separate script that has to run before builds, but I am getting to that point now.
I think your idea of creating a HARNESS_ACCESSIBLE macro is the cleanest way of going about this. You definitely don't want to be #define-ing away static for just the reasons you described.
I don't think using this macro will be cluttering up your code. You'll just be putting this in place of static, and it gives you the option of specifying exactly which functions you want to be able to unit test and keeping those minor utility functions explicitly static.

Possible to have separate "namespace" in one file?

Is it possible to block access to variables and functions as you would by having a separate file but in the same file? Like how in javascript you would use anonymous functions.
You can have hiding in the sense that the declaration of the static function or static variable can follow after the function it is hiding from. Using a macro, you can hack your way into hiding a function or variable after it has been defined.
static void foo () { /* ... */ }
static int g_hidden_from_foo;
static void bar () { /* can use foo() */ }
#define foo foo_is_now_private
/* effectively hides foo */
This may satisfy your curiosity, but I can't say it is convenient (or wise).
If you are open to using compiler extensions, GCC has nested functions, which is more or less similar to anonymous functions.
This is not directly possible in C. The unit of code in C is the translation unit, which is the fancy way of saying the file you're editing (plus header files).
Any code in a particular translation unit can "see" any of the preceding declarations and definitions. There is no way to change that in standard C. You can use macros or naming tricks to hide identifiers, but you can't outright stop access, especially not in a readable/convenient way.
If you're willing to use separate files you can simply avoid putting a declaration in your public header file to make the data "hidden" and can make function declarations as static to make them completely inaccessible to other translation units.
If you use C++ instead then you can get a bit further by using classes with protected and private members, as C++ protection semantics are per-class rather than per-translation-unit.

How to test a static function

As applying unit-test to some C code, we run into a problem that some static function can not be called at the test file, without modifying the source code. Is there any simple or reasonable way to overcome this problem?
I have a test harness. In dire cases - like trying to test a static function, I use:
#include "code_under_test.c"
...test framework...
That is, I include the whole of the file containing the function under test in the test harness. It is a last resort - but it works.
Can you give more information as to why you can't call the function?
Is it not available because it's private to a .c file? If so, you're best bet is to use conditional compilation that allows for access to the function in order to allow for other compilation units to access it. For example
SomeHeaderSomewher.h
#if UNIT_TEST
#define unit_static
#else
#define unit_static static
#endif
Foo.h
#if UNIT_TEST
void some_method
#endif
Foo.cpp
unit_static void some_method() ...
For unit tests, we actually have the test code within the source file itself and we conditionally compile it in when testing. This gives the unit tests full access to all functions and file-level variables (static or otherwise).
The unit tests themselves are not static - this allows us to call the unit tests from a single super-test program which unit tests all compilation units.
When we ship the code, we conditionally compile out the unit tests but this isn't actually necessary (if you want to be certain you're shipping exactly the same code you tested).
We've always found it invaluable to have the unit tests in the same place as the code you're testing since it makes it more obvious that you need to update the tests if and when the code changes.
No - you cannot directly test a static function without modifying the source at least a little (that is the definition of static in C - that it cannot be called from a function in a different file).
You could create a separate function within the test file that just calls the static function?
For example:
//Your fn to test
static int foo(int bar)
{
int retVal;
//do something
return retVal;
}
//Wrapper fn
int test_foo(int bar)
{
return foo(bar);
}
We usually don't test our static functions directly, but rather ensure that the logic they perform is adequately tested by different tests of the calling function.
static functions are essentially helper functions to the public (i.e. exposed) functions. So IMO, your unit tests should call the public interface with inputs that exercise all the paths in the static function.
The output (return values / side effects) of the public function should be used to test the effect of the static.
This means you need to have appropriate stubs to 'catch' these side effects. (e.g. if a function calls file IO, you need to provide stubs to override these file IO lib functions). The best way to do this by making each test suite a seperate project/executable and avoid linking to any external lib functions. You can mock even C functions, but it's not worth the effort.
Anyway, this is the approach I've used so far and it works for me. Good luck
#define static
This is a very bad idea. If you have a variable declared local to a function, it changes the behavior of the function. Example:
static int func(int data)
{
static int count = 0;
count += data;
return count;
}
You could call the function from the unit test, as func() would be exported, however the basic functionality of the code would be modified.
--kurt
If you are under Unix environment you can include in test file additional header yourheader_static.h with declarations of your static functions and translate obj file code_under_test.o through objdump --globalize-symbols=syms_name_file to globalize local symbols. They will be visible as if they are non-static functions.
Just to add to the accepted answer by Jonathan Leffler, and elaborate on other's mention of a wrapper function:
Create a test source file, as in test_wrapper_foo.c, where foo.c is the original.
In test_wrapper_foo.c:
#include "foo.c"
// Prototype
int test_wrapper_foo();
// wrapper function
int test_wrapper_foo() {
// static function to test
return foo();
}
Assuming that the static function foo in foo.c has prototype: int foo(void);
build test_wrapper_foo.c through your makefile instead of foo.c (note that this will not break any dependencies on functions in foo.c by other external functions)
In your unit test script, call test_wrapper_foo() instead of foo().
This approach leaves the original source intact, while giving you access to the function from your test framework.
You could add a non-static function to call the static function, then call the non-static function.
static int foo ()
{
return 3;
}
#ifdef UNIT_TEST
int test_foo ()
{
if (foo () == 3)
return 0;
return 1;
}
#endif
If you're using Ceedling and trying to use the #include "code_under_test.c" method, the test build will fail because it will automatically try to build "code_under_test.c" once when #included and also because it's the target of the test.
I've been able to get around it by a slight modification to the code_under_test.c code and a couple of other changes. Wrap the whole code_under_test.c file with this check:
#if defined(BUILD)
...
#endif // defined(BUILD)
Add this to your test harness:
#define BUILD
#include "code_under_test.c"
Add the BUILD define to your Makefile or project config file:
# Makefile example
..
CFLAGS += -DBUILD
..
Your file will now build from your environment and when included from your test harness. Ceedling will now not be able to build the file a second time (ensure your project.yml file does NOT define BUILD).
All the above suggested answers (except a few) suggest conditional compilation which requires modification to source. As such that shouldn't be an issue, it just would add clutter (just for testing). Rather you can do something like this.
Say your function to be tested is
static int foo(int);
You make another header file called testing_headers.h which will have the contents -
static int foo(int);
int foo_wrapper(int a) {
return foo(a);
}
Now while compiling your c file for testing you can force include this header from the compiler options.
For clang and gcc the flag is --include. For Microsoft C compiler it is /FI.
This will require absolutely 0 change to your c file and you will be able to write a non static wrapper to your function.
If you don't want a non static wrapper, you can also create a non static global function pointer initialised to foo.
You can then call the function using this global function pointer.
There are 2 ways to do this.
Include the c source file into the unit testing source file, so the static method now is in the scope of unit testing source file and callable.
Do a trick:
#define static
in the head of unit testing source file.
It will convert keyword static to "nothing" or I can say, it removes static from your c source code.
In some unit testing tool, we can use config option "pre-processor" to do this trick, just put in the config:
static=
The tool willl convert all static keyword to "nothing"
But I must say, using these ways make the static method (or variable) loses the specific meaning of it.

Resources