I'm very new at testing so please let me know if I am just going off in completely the wrong direction at any point. Having said that, assume I want to test the following function, foo.
int foo(int i) {
//Lots of code here
i = bar();
//Some more changes to i happen here, conditional on what bar returned
return i;
}
In this example, both foo and bar are functions written by myself and I have already tested bar.
Since the output of foo is conditional on the output of bar, I assume that in order to test foo, I need to create a mock of bar. In order to do that, and assuming that the definition of bar is kept inside a separate source file from foo, I could create a new source file, include that instead of the one where the actual definition of bar is found, and put a mock of bar in that file.
int bar(void) {
return HARD_CODED_VALUE;
}
However, there are 2 problems with this approach:
1) What happens if bar returns multiple values (such as an error code or an actual value) and I need to ensure that foo reacts correctly for each possibility? I can't create multiple definitions for bar. One thought I did have was to create a static int in bar and then increment it every time bar gets called. Then I just have a conditional on this int, call bar multiple times and thus return multiple values. However, I am unsure whether introducing more complex logic into a mock function is good practice or if there is a better way to achieve this:
int bar(void) {
static int i = 0;
i++;
if(i == 1) {
return HARD_CODED_VALUE_1
}
else if(i == 2) {
return HARD_CODED_VALUE_2
}
else {
fprintf(stderr, "You called bar too many times\n");
exit(1);
}
}
2) What happens if bar is in the same source file as foo? I can't redefine bar nor separate foo and bar without altering my source code which would be a real pain.
Well, there are a few ways around that problem.
You could use preprocessor hooks to swap out bar() when a UNITTEST flag is set:
#ifdef UNITTEST
return mockBar();
#else
return bar();
#endif
You could simulate Dependency Injection, and require a pointer to bar() as a parameter to the function. I'm not saying that's a great idea in practice, but you could do it.
void foo( void (*bar)() ) {
I'm sure there are others, but that's just 2 that came off the top of my head...
What you want to do is substitute the called function with a stub returning known values. The same would apply when using an external dependency, i.e. a database or networking code. With C there are two usable "seams" (to use the terminology from Working Effectively with Legacy Code) that allow you to perform that substitute:
Using preprocessor commands to replace the function body with a macro, e.g.
#ifdef TEST
#define bar(x) { if (x) then y; else z; }
#endif
Move bar(x) into a separate library, and then maintain two versions of the library. The first is your production code and the second is a test library that contains a test stub of bar(x).
A third option is to use dependency injection, by refactoring the bar(x) call out into a function pointer parameter as ircmaxell demonstrated.
void foo( void (*bar)() )
I have tried these approaches with non-OO C++ code and found the first to be by far the most useful. The second introduces a pretty tough maintainability issue (multiple versions of the same libraries and the functions within need to be maintained in conjunction), while the latter obviously negatively impacts upon the readability and understandability of the code.
The preprocessor directives, on the other hand, can be quite localized and the alternate definitions can be separated out into a header file that is only included if tested, i.e.
#ifdef TEST
#include "subsystem_unittest.h"
#endif
There are libraries for mocking. These libraries usually find a way to address those very questions. Sophisticated libraries will allow you to configure in your test what bar() should return at each point in the test.
I'm not sure they'll be handling the case where bar() and foo() are in the same source file very well but they might. In this case I would consider bar() and foo() to be part of the same unit but that is an entirely different argument.
Here is a C++ code fragment (source) from GoogleMock as an example. It creates a Mock turtle object which the Painter should call the PenDown method once and when it does the PenDown method will return 500. If the Painter doesn't call PenDown then the test would fail.
#include "path/to/mock-turtle.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using ::testing::AtLeast; // #1
TEST(PainterTest, CanDrawSomething) {
MockTurtle turtle; // #2
EXPECT_CALL(turtle, PenDown()) // #3
.WillOnce(Return(500));
Painter painter(&turtle); // #4
EXPECT_TRUE(painter.DrawCircle(0, 0, 10));
} // #5
int main(int argc, char** argv) {
// The following line must be executed to initialize Google Mock
// (and Google Test) before running the tests.
::testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}
Of course this particular library is using OOP which you may or may not be doing. I would guess there are other libraries out there for non-OOP too.
Is bar() an awkward dependency ? Is there a problem with the unit test for foo using the actual implementation of bar ?
If not, then I don't see a problem. You do not have to mock everything.
Related
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);
//...
How to #define a function to be replaced by another?
For example, if I have a function Stuff(int numbers) and would like to replace it with Stuff2(int numbers, int otherNumbers).
So, when Stuff() is called, Stuff2() is used instead.
Using #define is a basic global text replacement.
#define Stuff(number) Stuff2(number,0)
The zero is here for illustration; replace it with whatever the appropriate default is. If necessary, you could even call a function or use more macro magic to compute it.
Update
So, following the commentary, OP is trying to redirect main().
This is a technique with a highly-specific use-case. The first thing to remember is that main() is not a normal function. That’s right, main() is special.
As a result, you cannot just replace main() and expect things to work happily. There must be a main(), and it must be declared according to one of your compiler’s accepted variations. (IMO, you should prefer to use one of the two variations required by the C Standard.)
Intercepting the user’s main()
The technique is commonly used by libraries that want to have an app-level control over your application, but want you to think that everything is normal.
They do this by declaring main() in the library’s code, and #defining main to something else in the header so that when you write "main()" it is actually a different function. For example:
// quuxlib.c
int main( int argc, char** argv )
{
int exit_code = 0;
// library does initializations here
...
// call the user's main(), LOL
exit_code = UsersMain( argc, argv );
// perform cleanup
...
return exit_code;
}
The library's header:
// quuxlib.h
#define main UsersMain
...
And now the user’s code looks normal:
#include "quuxlib.h"
int main( int argc, char** argv ) // This is actually UsersMain()!
{
// Use quuxlib without any further thought
}
Caveats and Best Practices
This technique is, IMHO, bad design. It seeks to obscure what is actually happening. A better library design would be explicit, and either:
Require you to properly initialize and finalize the library in your main()
Expect you to use an explicit entry procedure
The former is preferred, as it gets along with all kinds of stuff better. For example, Tcl hooks things properly. Here you simply create an interpreter, use it, and terminate normally.
#include "tcl.h"
int main()
{
Tcl_Interp* interp = Tcl_CreateInterp();
int status = Tcl_Eval( interp, "puts {Hello world!}" );
return 0;
}
Tcl also goes one step further, providing Tcl_Main and Tcl_AppInit to make life very easy. See an example here.
Using an explicit entry procedure is the very same thing as the main() replacement trick, just without pretending anything:
#include "quuxlib.h"
int AppMain() // required by QuuxLib
{
// my main program here
...
return 0;
}
The problems
To finish, the problems with re#defining main are:
it obscures what is really happening
it uses a global macro replacement
Good design doesn't try to hide things from you. A global macro replacement is also bad. In this case, "main" is not a reserved word. You could have a valid local identifier called "main". Using a global macro replacement obviates that possibility.
Finally, having a library provide explicit initialization and finalization procedures rather than take over main increases the flexibility available to the user. A library that takes your main() cannot be used with another library that does the same, nor can it really be trusted to handle things that can go wrong (IMHO) as well as a library the provides proper and explicit hooks for the library user to handle that kind of stuff.
The trade-off is pretty for common cases vs versatility.
Well, I think I’m pretty firmly into rambling now, so it’s time to stop...
I have seen people write code in this fashion:
void function2()
{.....
..more blah blah...
.<I think i will stop nesting my function here>...
..blah blah. over and out....
}
void function1()
{.....
..blah blah...
function2();
....
}
void LCD_disp_main ()
{
<automatic, static... variable declaration>
....
function1(); //calling a function 1
.....
}
as opposed to writing the definitions that you would normally put in function and put it inline here.
void LCD_disp_main ()
{
<automatic, static... variable declaration>
....
<function1() and function2();> //instead of calling function1 and fucntion2 just inline it here.
.....
}
What is the benefit of one over the other?
Doesn't the first set cause the stack to keep growing everytime you call a new function albeit it will grow the same mount in option 2? Context switching?
Well, it's for readability, maintainability and obeying the convention that a function should do one thing only and do it well and lots of other benefits as well. Imagine how you would write a callback if you lump all your code into a single function. If you are so worried about the size of the stack frame why don't you write everything in the main() function?
BTW, context switching does not apply here, it's used to define the process of swapping processes / threads off the processor.
These are not "nested functions". It is true that on a poor compiler it would waste more stack. However putting into functions makes the code a) reusable, b) groups related things together.
An optimizing compiler would know to inline the contents of all these functions so the resulting code would be more or less identical for both cases - especially if the functions were declared with internal linkage (i.e. the keyword static).
This is not a lambda function question, I know that I can assign a lambda to a variable.
What's the point of allowing us to declare, but not define a function inside code?
For example:
#include <iostream>
int main()
{
// This is illegal
// int one(int bar) { return 13 + bar; }
// This is legal, but why would I want this?
int two(int bar);
// This gets the job done but man it's complicated
class three{
int m_iBar;
public:
three(int bar):m_iBar(13 + bar){}
operator int(){return m_iBar;}
};
std::cout << three(42) << '\n';
return 0;
}
So what I want to know is why would C++ allow two which seems useless, and three which seems far more complicated, but disallow one?
EDIT:
From the answers it seems that there in-code declaration may be able to prevent namespace pollution, what I was hoping to hear though is why the ability to declare functions has been allowed but the ability to define functions has been disallowed.
It is not obvious why one is not allowed; nested functions were proposed a long time ago in N0295 which says:
We discuss the introduction of nested functions into C++. Nested
functions are well understood and their introduction requires little
effort from either compiler vendors, programmers, or the committee.
Nested functions offer significant advantages, [...]
Obviously this proposal was rejected, but since we don't have meeting minutes available online for 1993 we don't have a possible source for the rationale for this rejection.
In fact this proposal is noted in Lambda expressions and closures for C
++ as a possible alternative:
One article [Bre88] and proposal N0295 to the C
++ committee [SH93] suggest adding nested functions to C
++ . Nested functions are similar to lambda expressions, but are defined as statements within a function body, and the resulting
closure cannot be used unless that function is active. These proposals
also do not include adding a new type for each lambda expression, but
instead implementing them more like normal functions, including
allowing a special kind of function pointer to refer to them. Both of
these proposals predate the addition of templates to C
++ , and so do not mention the use of nested functions in combination with generic algorithms. Also, these proposals have no way to copy
local variables into a closure, and so the nested functions they
produce are completely unusable outside their enclosing function
Considering we do now have lambdas we are unlikely to see nested functions since, as the paper outlines, they are alternatives for the same problem and nested functions have several limitations relative to lambdas.
As for this part of your question:
// This is legal, but why would I want this?
int two(int bar);
There are cases where this would be a useful way to call the function you want. The draft C++ standard section 3.4.1 [basic.lookup.unqual] gives us one interesting example:
namespace NS {
class T { };
void f(T);
void g(T, int);
}
NS::T parm;
void g(NS::T, float);
int main() {
f(parm); // OK: calls NS::f
extern void g(NS::T, float);
g(parm, 1); // OK: calls g(NS::T, float)
}
Well, the answer is "historical reasons". In C you could have function declarations at block scope, and the C++ designers did not see the benefit in removing that option.
An example usage would be:
#include <iostream>
int main()
{
int func();
func();
}
int func()
{
std::cout << "Hello\n";
}
IMO this is a bad idea because it is easy to make a mistake by providing a declaration that does not match the function's real definition, leading to undefined behaviour which will not be diagnosed by the compiler.
In the example you give, void two(int) is being declared as an external function, with that declaration only being valid within the scope of the main function.
That's reasonable if you only wish to make the name two available within main() so as to avoid polluting the global namespace within the current compilation unit.
Example in response to comments:
main.cpp:
int main() {
int foo();
return foo();
}
foo.cpp:
int foo() {
return 0;
}
no need for header files. compile and link with
c++ main.cpp foo.cpp
it'll compile and run, and the program will return 0 as expected.
You can do these things, largely because they're actually not all that difficult to do.
From the viewpoint of the compiler, having a function declaration inside another function is pretty trivial to implement. The compiler needs a mechanism to allow declarations inside of functions to handle other declarations (e.g., int x;) inside a function anyway.
It will typically have a general mechanism for parsing a declaration. For the guy writing the compiler, it doesn't really matter at all whether that mechanism is invoked when parsing code inside or outside of another function--it's just a declaration, so when it sees enough to know that what's there is a declaration, it invokes the part of the compiler that deals with declarations.
In fact, prohibiting these particular declarations inside a function would probably add extra complexity, because the compiler would then need an entirely gratuitous check to see if it's already looking at code inside a function definition and based on that decide whether to allow or prohibit this particular declaration.
That leaves the question of how a nested function is different. A nested function is different because of how it affects code generation. In languages that allow nested functions (e.g., Pascal) you normally expect that the code in the nested function has direct access to the variables of the function in which it's nested. For example:
int foo() {
int x;
int bar() {
x = 1; // Should assign to the `x` defined in `foo`.
}
}
Without local functions, the code to access local variables is fairly simple. In a typical implementation, when execution enters the function, some block of space for local variables is allocated on the stack. All the local variables are allocated in that single block, and each variable is treated as simply an offset from the beginning (or end) of the block. For example, let's consider a function something like this:
int f() {
int x;
int y;
x = 1;
y = x;
return y;
}
A compiler (assuming it didn't optimize away the extra code) might generate code for this roughly equivalent to this:
stack_pointer -= 2 * sizeof(int); // allocate space for local variables
x_offset = 0;
y_offset = sizeof(int);
stack_pointer[x_offset] = 1; // x = 1;
stack_pointer[y_offset] = stack_pointer[x_offset]; // y = x;
return_location = stack_pointer[y_offset]; // return y;
stack_pointer += 2 * sizeof(int);
In particular, it has one location pointing to the beginning of the block of local variables, and all access to the local variables is as offsets from that location.
With nested functions, that's no longer the case--instead, a function has access not only to its own local variables, but to the variables local to all the functions in which it's nested. Instead of just having one "stack_pointer" from which it computes an offset, it needs to walk back up the stack to find the stack_pointers local to the functions in which it's nested.
Now, in a trivial case that's not all that terrible either--if bar is nested inside of foo, then bar can just look up the stack at the previous stack pointer to access foo's variables. Right?
Wrong! Well, there are cases where this can be true, but it's not necessarily the case. In particular, bar could be recursive, in which case a given invocation of bar might have to look some nearly arbitrary number of levels back up the stack to find the variables of the surrounding function. Generally speaking, you need to do one of two things: either you put some extra data on the stack, so it can search back up the stack at run-time to find its surrounding function's stack frame, or else you effectively pass a pointer to the surrounding function's stack frame as a hidden parameter to the nested function. Oh, but there's not necessarily just one surrounding function either--if you can nest functions, you can probably nest them (more or less) arbitrarily deep, so you need to be ready to pass an arbitrary number of hidden parameters. That means you typically end up with something like a linked list of stack frames to surrounding functions, and access to variables of surrounding functions is done by walking that linked list to find its stack pointer, then accessing an offset from that stack pointer.
That, however, means that access to a "local" variable may not be a trivial matter. Finding the correct stack frame to access the variable can be non-trivial, so access to variables of surrounding functions is also (at least usually) slower than access to truly local variables. And, of course, the compiler has to generate code to find the right stack frames, access variables via any of an arbitrary number of stack frames, and so on.
This is the complexity that C was avoiding by prohibiting nested functions. Now, it's certainly true that a current C++ compiler is a rather different sort of beast from a 1970's vintage C compiler. With things like multiple, virtual inheritance, a C++ compiler has to deal with things on this same general nature in any case (i.e., finding the location of a base-class variable in such cases can be non-trivial as well). On a percentage basis, supporting nested functions wouldn't add much complexity to a current C++ compiler (and some, such as gcc, already support them).
At the same time, it rarely adds much utility either. In particular, if you want to define something that acts like a function inside of a function, you can use a lambda expression. What this actually creates is an object (i.e., an instance of some class) that overloads the function call operator (operator()) but it still gives function-like capabilities. It makes capturing (or not) data from the surrounding context more explicit though, which allows it to use existing mechanisms rather than inventing a whole new mechanism and set of rules for its use.
Bottom line: even though it might initially seem like nested declarations are hard and nested functions are trivial, more or less the opposite is true: nested functions are actually much more complex to support than nested declarations.
The first one is a function definition, and it is not allowed. Obvious, wt is the usage of putting a definition of a function inside another function.
But the other twos are just declarations. Imagine you need to use int two(int bar); function inside the main method. But it is defined below the main() function, so that function declaration inside the function makes you to use that function with declarations.
The same applies to the third. Class declarations inside the function allows you to use a class inside the function without providing an appropriate header or reference.
int main()
{
// This is legal, but why would I want this?
int two(int bar);
//Call two
int x = two(7);
class three {
int m_iBar;
public:
three(int bar):m_iBar(13 + bar) {}
operator int() {return m_iBar;}
};
//Use class
three *threeObj = new three();
return 0;
}
This language feature was inherited from C, where it served some purpose in C's early days (function declaration scoping maybe?).
I don't know if this feature is used much by modern C programmers and I sincerely doubt it.
So, to sum up the answer:
there is no purpose for this feature in modern C++ (that I know of, at least), it is here because of C++-to-C backward compatibility (I suppose :) ).
Thanks to the comment below:
Function prototype is scoped to the function it is declared in, so one can have a tidier global namespace - by referring to external functions/symbols without #include.
Actually, there is one use case which is conceivably useful. If you want to make sure that a certain function is called (and your code compiles), no matter what the surrounding code declares, you can open your own block and declare the function prototype in it. (The inspiration is originally from Johannes Schaub, https://stackoverflow.com/a/929902/3150802, via TeKa, https://stackoverflow.com/a/8821992/3150802).
This may be particularily useful if you have to include headers which you don't control, or if you have a multi-line macro which may be used in unknown code.
The key is that a local declaration supersedes previous declarations in the innermost enclosing block. While that can introduce subtle bugs (and, I think, is forbidden in C#), it can be used consciously. Consider:
// somebody's header
void f();
// your code
{ int i;
int f(); // your different f()!
i = f();
// ...
}
Linking may be interesting because chances are the headers belong to a library, but I guess you can adjust the linker arguments so that f() is resolved to your function by the time that library is considered. Or you tell it to ignore duplicate symbols. Or you don't link against the library.
This is not an answer to the OP question, but rather a reply to several comments.
I disagree with these points in the comments and answers: 1 that nested declarations are allegedly harmless, and 2 that nested definitions are useless.
1 The prime counterexample for the alleged harmlessness of nested function declarations is the infamous Most Vexing Parse. IMO the spread of confusion caused by it is enough to warrant an extra rule forbidding nested declarations.
2 The 1st counterexample to the alleged uselessness of nested function definitions is frequent need to perform the same operation in several places inside exactly one function. There is an obvious workaround for this:
private:
inline void bar(int abc)
{
// Do the repeating operation
}
public:
void foo()
{
int a, b, c;
bar(a);
bar(b);
bar(c);
}
However, this solution often enough contaminates the class definition with numerous private functions, each of which is used in exactly one caller. A nested function declaration would be much cleaner.
Specifically answering this question:
From the answers it seems that there in-code declaration may be able to prevent namespace pollution, what I was hoping to hear though is why the ability to declare functions has been allowed but the ability to define functions has been disallowed.
Because consider this code:
int main()
{
int foo() {
// Do something
return 0;
}
return 0;
}
Questions for language designers:
Should foo() be available to other functions?
If so, what should be its name? int main(void)::foo()?
(Note that 2 would not be possible in C, the originator of C++)
If we want a local function, we already have a way - make it a static member of a locally-defined class. So should we add another syntactic method of achieving the same result? Why do that? Wouldn't it increase the maintenance burden of C++ compiler developers?
And so on...
Just wanted to point out that the GCC compiler allows you to declare functions inside functions. Read more about it here. Also with the introduction of lambdas to C++, this question is a bit obsolete now.
The ability to declare function headers inside other functions, I found useful in the following case:
void do_something(int&);
int main() {
int my_number = 10 * 10 * 10;
do_something(my_number);
return 0;
}
void do_something(int& num) {
void do_something_helper(int&); // declare helper here
do_something_helper(num);
// Do something else
}
void do_something_helper(int& num) {
num += std::abs(num - 1337);
}
What do we have here? Basically, you have a function that is supposed to be called from main, so what you do is that you forward declare it like normal. But then you realize, this function also needs another function to help it with what it's doing. So rather than declaring that helper function above main, you declare it inside the function that needs it and then it can be called from that function and that function only.
My point is, declaring function headers inside functions can be an indirect method of function encapsulation, which allows a function to hide some parts of what it's doing by delegating to some other function that only it is aware of, almost giving an illusion of a nested function.
Nested function declarations are allowed probably for
1. Forward references
2. To be able to declare a pointer to function(s) and pass around other function(s) in a limited scope.
Nested function definitions are not allowed probably due to issues like
1. Optimization
2. Recursion (enclosing and nested defined function(s))
3. Re-entrancy
4. Concurrency and other multithread access issues.
From my limited understanding :)
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.