Unit testing for exit() in C - c

I'm using the CUnit framework for the way it displays the testing results. (I'm a programming & S.O. newbie so step by step answers really appreciated).
Is there any way I can use the same CUnit framework for when I'm testing for functions that I expect to exit()? It doesnt seem so to me, but I'm keen to ask anyway - it would display the pass/fail result along with my other CUnit tests so its ideal.
If not, I've been looking at other noob-friendly solutions (such as this SO post), but I cannot use GOTO/setjmp/longjmp. The solution also needs to be portable.
I'm using Mac & gcc command line to run this code.
EDIT
One of the suggested solutions is to use C Pre-Processor (CPP) Directive /"mocking", which looks ideal? I have used the below code in my test.c file:
#define ERROR(PHRASE) {fprintf(stderr,"Fatal Error %s occurred in %s, line %d\n",PHRASE, FILE, LINE); exit(2);}
#ifdef ERROR(PHRASE)
#define ERROR(PHRASE) {printf("In test phase");}
#endif
#ifndef ERROR(PHRASE #define ERROR(PHRASE) {printf("Not In test phase");}
#endif
Here is the error message that the terminal gives me:
test.c:30:9: warning: 'ERROR' macro redefined [-Wmacro-redefined]
#define ERROR(PHRASE) {printf("In test phase");}
^
test.c:26:9: note: previous definition is here
#define ERROR(PHRASE) {fprintf(stderr,"Fatal Error %s occured in %s, lin...
^
test.c:32:14: warning: extra tokens at end of #ifndef directive
[-Wextra-tokens]
#ifndef ERROR(PHRASE) {printf("Not In test phase");}
Removing the (PHRASE) still gives the same errors.
EDIT
If helpful for anyone else, mocking using the #ifdef was the easiest way to solve this issue in the end. This website was helpful too.

Just so you know what to search for, what you want to do is "mock" the exit() call. The basic idea is to choose a different implementation for the exit function, generally at compile time. Frankly, C doesn't make this particularly easy, but there are some options with varying levels of portability and intrusiveness.
This article describes something that is pretty portable, but also fairly intrusive. Basically, you use macros and/or function pointers to toggle back and forth, which means modifying your code a bit, but honestly it's not that big of a deal.
For something potentially less intrusive but also much less portable, this article has a couple of ideas (I believe both would work on MacOS). Here you get the linker to redirect the exit() call to another function, which you provide. The good news is that it doesn't require any modifications to your code. The bad news is that it requires you to gain the cooperation of the linker, and won't work everywhere (LD_PRELOAD won't work on Windows, and AFAIK --wrap requires GNU ld or something compatible).

One aspect that might be considered if there are issues/increased effort with regards to testing is if there's any scope to change the program being tested in some way that would help with testing without significantly increasing the complexity of the code.
In this case, is there scope to replace the calls to exit() with error return codes from functions, such that the callers can do things such as tidy up, or log state, before actually exiting? If so, this both simplifies testing and is likely to simplify fault-finding when the code is actually used in release/production, as it can be quite tricky to work out why a program just ups and dies on you, especially if the code is tucked away in a library function!

If you want to do something non-intrusive, you can run the function under test as a separate process. You start this with CreateProcess (Windows) or fork (and possibly execv on Max and Linux. Your test code then use wait to test the exit code and pass if the created process exits correctly.

Related

How to trace how/where the printf is disabled?

My product embeds TCL VM to run TCL script. We basically take the TCL 8.4 source and integrate it to our product, the whole product is programmed in C.
Now I need to debug some issue and best I can have some insight about TCL VM at run time. So I add some printf to the TCL source, but I cannot see any print out. Note that the printf added to our side of the code works as expected.
This leads me to suspect that somewhere in TCL the printf is disabled.
I see the following code snippet in TCL source:
#ifdef TCL_COMPILE_DEBUG
fprintf(stdout, " Starting stack top=%d\n", eePtr->stackTop);
fflush(stdout);
#endif
I rebuild TCL by enabling the TCL_COMPILE_DEBUG, still I cannot see print out.
Any suggestion how I should proceed from here?
It seems unlikely that the standard library's fprintf() is disabled. Instead, I see three main alternatives:
The fprintf() you have added is never being called. That could be because it's in the wrong place, because conditional compilation directives cause it to be omitted, or perhaps for some other reason.
The fprintf() being called is not the standard library's, and it does not do what you expect. It might instead be a local function in the TCL VM's code, or the TCL VM might #define it to something else altogether. Depending on exactly how you integrate TCL into your larger code, these possibilities might be limited in scope to just TCL.
stdout does not mean what you think it does inside the TCL code. This would almost surely be as a result of it being #defined to something else, for some reason important to the TCL VM. In that case, there might or might not be a way to get the real stdout in that scope.
I'd suggest you grep the TCL code you have integrated for the fprintf and stdout symbols, to look for macro definitions and alternative implementations. It would also be worthwhile to check the preprocessor output to make sure your call is still there (and is still the call you expected). If you are compiling with GCC, then you can preprocess your sources without compiling the result via gcc -E.

Function call inside assert == bad?

I have just dug up a bug in some code we're working with* that was failing due to the following situation:
Assert(SomeVitalFunction(foo) == OK)
This worked fine all the time the DEBUG macros were #defined:
#ifdef DEBUG
#define Assert(x) if((x) == 0){/*some error handling*/}
#else
#define Assert(x)
#endif
But when we #undef'd DEBUG it has the effect of deleting the vital function call from the code.
I can't for the life of me work out how that could ever work with DEBUG #undef'd, and it seems a bad idea generally to put any sort of function call inside an assert like this.
Have I missed something?
* = Edit to clarify following Carpetsmoker's comment: The code comes from a particularly backward cabal of Elbonian code slaves, our task has been to hack, slash, shave, polish, sanitize and apply lipstick to the thing.
You have missed nothing.
Asserts should always be written as if they could disappear at the flick of a compiler switch.
You can call functions that take a relatively long time to complete inside an assert (for example analysing the integrity of a data structure), because the function call will not be present in the release build. The flip side of this is that you cannot call functions that are necessary for correct operation.
It depends upon what SomeVitalFunction is doing. If it has no interesting side-effects, it is ok to use it inside an assert. But if calling or not calling SomeVitalFunction is essential to the program, it is a bug.
For instance, on POSIX, kill(2) with a 0 signal is only useful to test if a process is living. I would imagine that you might be sometimes tempted to use
assert(kill(sompid, 0) == 0); // process sompid exists
assuming that you always suppose that the process sompid is still running.
Likewise, you might use assert(hash_table_count(htbl)>0); to check that some hash table htbl is not empty.
BTW, notice that assert(3) is documented as being ignored if you compile with -DNDEBUG preprocessor option (not if -DDEBUG is not given).

How to automatically call all functions in C source code

have you ever heard about automatic C code generators?
I have to do a kind of strange API functionality research which includes at least one attempt of every function execution. It may lead to crushes, segmentation faults - no matter. I just need to register every function call.
So i got a long list (several hundreds) of functions from sources using
ctags -x --c-kinds=f *.c
Can i use any tool to generate code calling every of them? Thanks a lot.
UPD: thanks for all your answers.
You could also consider customizing the GCC compiler, e.g. with a MELT extension (which e.g. would generate the testing during some customized compilation). Then you might even define your own #pragma or __attribute__ to parameterize these functions (enabling their auto-testing, giving default arguments for testing, etc etc).
However, I'm not sure it is the right approach for unit testing. There are many unit testing frameworks (but I am not very familiar with them).
Maybe something like autoconf could help you with that: as described here. In particular check for AC_CHECK_FUNCS. Autoconf creates small programs to test the existence of registered functions.

hidden routines linked in c program

Hullo,
When one disasembly some win32 exe prog compiled by c compiler it
shows that some compilers links some 'hidden' routines in it -
i think even if c program is an empty one and has a 5 bytes or so.
I understand that such 5 bytes is enveloped in PE .exe format but
why to put some routines - it seem not necessary for me and even
somewhat annoys me. What is that? Can it be omitted? As i understand
c program (not speaking about c++ right now which i know has some
initial routines) should not need such complementary hidden functions..
Much tnx for answer, maybe even some extended info link, cause this
topic interests me much
//edit
ok here it is some disasembly Ive done way back then
(digital mars and old borland commandline (i have tested also)
both make much more code, (and Im specialli interested in bcc32)
but they do not include readable names/symbols in such dissassembly
so i will not post them here
thesse are somewhat readable - but i am not experienced in understending
what it is ;-)
https://dl.dropbox.com/u/42887985/prog_devcpp.htm
https://dl.dropbox.com/u/42887985/prog_lcc.htm
https://dl.dropbox.com/u/42887985/prog_mingw.htm
https://dl.dropbox.com/u/42887985/prog_pelles.htm
some explanatory comments whats that heere?
(I am afraid maybe there is some c++ sh*t here, I am
interested in pure c addons not c++ though,
but too tired now to assure that it was compiled in c
mode, extension of compiled empty-main prog was c
so I was thinking it will be output in c not c++)
tnx for longer explanations what it is
Since your win32 exe file is a dynamically linked object file, it will contain the necessary data needed by the dynamic linker to do its job, such as names of libraries to link to, and symbols that need resolving.
Even a program with an empty main() will link with the c-runtime and kernel32.dll libraries (and probably others? - a while since I last did Win32 dev).
You should also be aware that main() is only the entry point of your program - quite a bit has already gone on before this point such as retrieving and tokening the command-line, setting up the locale, creating stderr, stdin, and stdout and setting up the other mechanism required by the c-runtime library such a at_exit(). Similarly, when your main() returns, the runtime does some clean-up - and at the very least needs to call the kernel to tell it that you're done.
As to whether it's necessary? Yes, unless you fancy writing your own program prologue and epilogue each time. There are probably are ways of writing minimal, statically linked applications if you're sufficiently masochistic.
As for storage overhead, why are you getting so worked up? It's not enough to worry about.
There are several initialization functions that load whenever you run a program on Windows. These functions, among other things, call the main() function that you write - which is why you need either a main() or WinMain() function for your program to run. I'm not aware of other included functions though. Do you have some disassembly to show?
You don't have much detail to go on but I think most of what you're seeing is probably the routines of the specific C runtime library that your compiler works with.
For instance there will be code enabling it to run from the entry point 'main' which portable executable format understands to call the main(char ** args) that you wrote in your C program.

Using callback functions for error handling in C

I have been thinking about the difficulty incurred with C error handling.. like who actually does
if(printf("hello world")==-1){exit(1);}
But you break common standards by not doing such verbose, and usually useless coding. Well what if you had a wrapper around the libc? like so you could do something like..
//main...
error_catchall(my_errors);
printf("hello world"); //this will automatically call my_errors on an error of printf
ignore=1; //this makes it so the function will return like normal and we can check error values ourself
if(fopen.... //we want to know if the file opened or not and handle it ourself.
}
int my_errors(){
if(ignore==0){
_exit(1); //exit if we aren't handling this error by flagging ignore
}
return 0;
//this is called when there is an error anywhere in the libc
}
...
I am considering making such a wrapper as I am synthesizing my own BSD licensed libc(so I already have to touch the untouchable..), but I would like to know what people think about it..
would this actually work in real life and be more useful than returning -1?
during this years I've seen several attempts to mimics try/catch in ANSI C:
http://simgrid.gforge.inria.fr/doc/group__XBT__ex.html
http://llg.cubic.org/trycatch/
I think that try/catch approach is more simple than your.
But how would you be able to catch the error when it was expected? For example I might expect a file open to fail and want to deal with it in code instead of the generic error catcher.
To do this you would need two versions of every function. One that trapped errors and one the returns errors.
I did something like this long ago without modifying the library. I just created wrapper functions for common calls that did error checking. So my errchk_malloc call checked the return and raised an error if the allocation failed. Then I just used this version everywhere in place of the built in malloc.
if the goal is to exit cleanly as soon as you encounter an error that's ok... but if you want to do a minimum of error recovery, i can't see how your approach is useful...
To avoid this kind of problem, I sometimes use LD_PRELOAD_PATH to integrate my error management (only for my own projects since this is not a really good practice...)
Do you really want to change the standard behaviors of your LIBC ? You could add a few extensions around common functions.
For example, Gnome uses g_malloc and g_try_malloc. The former will abort on failure while the later will simply yield a null-pointer like malloc.

Resources