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.
Related
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.
Let's say I'm writing a library of functions, and each function makes use of a global array to perform its duties. I don't want to expose that array to non library code, so I declare it as static like so:
library.h:
void function1();
void function2();
library.c:
#include "library.h"
static int arr[ARBITRARY_SIZE];
void function1() {...} // both of these
void function2() {...} // make use arr
If I now want to use this library in my code, I would #include "library.c" at the top of my code.
If I understand correctly, #include simply copies and pastes in place the contents of the #includeed file. If this is the case, the user's code would itself contain the static definition of arr. Given that, how would I, as the author of the library, protect my library variables? If this is not the case, please correct me about what #include does!
static keyword doesn't protect the memory used by a variable, you can pass out of a function (with visibility of it) a reference to the variable so the variable is accessible out of the block where it is defined. Then the calling code can use that reference to modify it as desired.
static serves two purposes:
inside a block in a function body, it states that: despite the variable has visibility only in the inside of the block where it is defined, its life is all the program life (it is not created/destroyed when the program enters/exist the definition block)
outside a block, it gives local file visibility (the variable name is exposed nowhere out of the definition compilation unit). But that doesn't imply that there's no accessability to that global chunk of memory. You can, if you have a pointer reference pointing to it, still modify it as you want.
#include just text includes the include file contents verbatim in the compilation flow, so everything declared static in the include file has visibility in the including file (after the point of inclussion), and locally in every compilation unit that also includes the header file. But all definitions of it are different and independent, and they don't refer to the same variable (as they are local definitions in different compilation units), as it happens if you name two local variables of different blocks (even when nesting the blocks) with the same name, they are different variables.
If I now want to use this library in my code, I would #include "library.c" at the top of my code.
That will only work if you use this library in a single source file.
As soon as you add foo.c and bar.c which both #include "library.c" and try to link them together, you would get a multiply-defined function1 and function2 symbol error (because each of foo.o and bar.o will now provide their own separate definitions.
You could fix this by making the functions static as well: static void function1() { ... }, etc. but this not how people usually use libraries, because that method causes long compile times and larger than necessary executable. In addition, if you are using this method, you don't need the library.h file at all.
Instead, what people usually do is compile library.c into library.o, #include "library.h" at the top of their source files, then link everything together.
I don't want to expose that array to non library code, so I declare it as static like so:
That is a valid thing to do, and achieves your purpose (so long as you #include "library.h" and not library.c).
Note that using global arrays (as well as most other globals) makes code harder to reason about, and causes additional difficulties when making code thread-safe, and thus it's best to use globals very sparingly.
How can I write a test in Ceedling for a function that uses static global variable?
I would like to test for each possible value of the variable to achieve a good test coverage.
//Pseudo code for file_under_test.c
static int global_var;
int func_under_test(){
switch(global_var){
case x:
return some_value;
case y:
return some_other_value;
.
.
.
.
default:
return something;
}
}
This is a super common problem in unit testing C code and the most common solution I know of is to define the static keyword out of existence when testing. This requires some planning and is hard to do in legacy code but any static that I plan on testing against is replaced by some other string. Usually STATIC or better yet TESTABLE_STATIC.
Remember that ceedling and probable most unit test frameworks sets a compile time macro TEST so you code would be
//Pseudo code for file_under_test.c
#ifdef TEST
#define TESTABLE_STATIC
#else
#define TESTABLE_STATIC static
#endif
TESTABLE_STATIC int global_var;
int func_under_test(){
switch(global_var){
case x:
return some_value;
case y:
return some_other_value;
.
.
.
.
default:
return something;
}
}
Then in your test file you just treat the variable as a global
// your ceedling test
#include <your_functions.h>
extern int global_var;
void test_function_under_test(void)
{
// your test code setting global_var as needed
global_var = some_test_value;
TEST_ASSERT_EQUAL(expected_val, func_under_test());
}
I usually hide the TESTABLE_STATIC in a project header file or if you have a datatypes.h file so it is generally available everywhere in my project.
This also works for unit testing your static functions in a translation unit.
This question does not really have anything specifically to do with Ceedling (or Unity, CMock, etc), but I rather think this is an example of interpreting the word "unit" in a very specific way. The short version of my answer is that the example function you have written here does not really constitute a self-contained "unit", so I would claim that this is not really "unit-testable".
Only think of a "function" as a "unit" if it is a pure function or if you can find an appropriate seam (e.g. stubs, spies, or mocks to external interfaces)! Otherwise you would by neccessity need to check for implementation details inside the test, which makes for very brittle tests.
In order to have a "unit" of testable code, you need to both be able to see the effects of the unit under test (e.g. comparing the returned value and/or checking for other side effects) AND to be able to stimulate the unit under test (e.g. by passing arguments into a the function or by first setting up some side effects which the unit under test relies on).
The example function is relying on the side effects of some other function (one which has the side effect of modifying your static "global" variable), so a "proper unit" in this case would need include whatever function you have which triggers these side effects. I suppose your file already has at least one such function, or your example code would never return anything different*.
*This is unless your example actually has the side effect of modifying the static variable itself. In that case there should at least be a function which resets the "global state", otherwise your tests will not be isolated from each other (i.e. it is hard to make them order-independent). A better solution would be to explicitly expose the dependency of your state through the arguments to func_under_test, like func_under_test(struct some_opaque_type *state) and add a struct some_opaque_type *init_for_func_under_test() function.
TL;DR: If your function is not a pure function (e.g. it relies on hidden state and/or has side effects itself) or if you don't have the appropriate "seams" (e.g. stubs or spies), then also include functions which can modify the hidden state or verify the side effects in your definition of unit under test.
I used a wrapper, that includes the orginal C file and adds some helpers for test
So you have an unchanged orginal c source, but access to all the needed internals.
file wrapped_for_test.h
#include <file_under_test.h>
void set_for_test(int value);
file wrapped_for_test.c
#include <file_under_test.c>
void set_for_test(int value)
{
global_var = value;
}
You can create a test helper function in file_under_test.c that will setup the global_var before calling func_under_test(). If needed this test function helper can be compiled only for testing purpose (using specific #ifdef) so that is it not shipped with the rest of the code if your code is build for eg a product.
file_under_test.h:
void set_for_test(int value);
file_under_test.c
#ifdef TESTS
void set_for_test(int value)
{
global_var = value;
}
#endif
test_file.c:
#include <assert.h>
#include "file_under_test.h"
// some other tests
set_for_test(3);
assert (func_under_test() == something);
//...
I would like to write a C library with fast access by including just header files without using compiled library. For that I have included my code directly in my header file.
The header file contains:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#ifndef INC_TEST_H_
#define INC_TEST_H_
void test(){
printf("hello\n");
}
#endif
My program doesn't compile because I have multiple reference to function test(). If I had a correct source file with my header it works without error.
Is it possible to use only header file by including code inside in a C app?
Including code in a header is generally a really bad idea.
If you have file1.c and file2.c, and in each of them you include your coded.h, then at the link part of the compilation, there will be 2 test functions with global scope (one in file1.c and the other one in file2.c).
You can use the word "static" in order to say that the function will be restricted so it is only visible in the .c file which includes coded.h, but then again, it's a bad idea.
Last but not least: how do you intend to make a library without a .so/.a file? This is not a library; this is copy/paste code directly in your project.
And when a bug is found in your "library", you will be left with no solution apart correcting your code, redispatch it in every project, and recompile every project, missing the very point of a dynamic library: The ability to "just" correct the library without touching every program using it.
If I understand what you're asking correctly, you want to create a "library" which is strictly source code that gets #incuded as necessary, rather than compiled separately and linked.
As you have discovered, this is not easy when you're dealing with functions - the compiler complains of multiple definitions (you will have the same problem with object definitions).
You have a couple of options at this point.
You could declare the function static:
static void test( void )
{
...
}
The static keyword limits the function's visibility to the current translation unit, so you don't run into multiple definition errors at link time. It means that each translation unit is creating its own separate "instance" of the function, leading to a bit of code bloat and slightly longer build times. If you can live with that, this is the easiest solution.
You could use a macro in place of a function:
#define TEST() (printf( "hello\n" ))
except that macros are not functions and do not behave like functions. While macro-based "libraries" do exist, they are not trivial to implement correctly and require quite a bit of thought. Remember that macro arguments are not evaluated, they're just expanded in place, which can lead to problems if you pass expressions with side effects. The classic example is:
#define SQUARE(x) ((x)*(x))
...
y = SQUARE(z++);
SQUARE(z++) expands to ((z++)*(z++)), which leads to undefined behavior.
Separate compilation is a Good Thing, and you should not try to avoid it. Doing everything in one source file is not scalable, and leads to maintenance headaches.
My program do not compiled because I have multiple reference to test() function
That is because the .h file with the function is included and compiled in multiple C source files. As a result, the linker encounters the function with global scope multiple times.
You could have defined the function as static, which means it will have scope only for the curent compilation unit, so:
static void test()
{
printf("hello\n");
}
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.