I have to test a library that provides its own abort_routine() function (that calls abort() internally, but the implementation may change).
One of the requirements for this abort_routine() is that it may not return.
I'm wondering if it's possible to test this requirement?
UPDATE: I'm not using gtest, only llvm's lit and stuff like these: return 0, return 1, assert(false).
This is a nice use case for fork
and I use it myself in my tests.
You can simply fork()
, run the function in the child, _exit()
the child, reap the result, and if it indicates the process was signaled with SIGABRT
, the child aborted, otherwise it didn't.
Example code:
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
int fork_and_reap(int *Ws, void Fn(void *), void *Arg)
{
pid_t pid; if (0>(pid=fork())) return -1;
if(0==pid) (void)Fn(Arg), _exit(0);
else for(;;){
if(0>waitpid(pid,Ws,WUNTRACED)){
if(EINTR==errno) continue;
else abort();
}else if(!WIFEXITED(*Ws)&&!WIFSIGNALED(*Ws)){ //shouldn't have stopped
if(0>kill(pid,SIGTERM) ||0>kill(pid,SIGCONT)) abort();
}else break;
}
return 0;
}
void aborting(void *A){ (void)A; abort(); }
void not_aborting(void *A){ (void)A; }
int main()
{
int ws;
if(0<=fork_and_reap(&ws, aborting, 0) && WIFSIGNALED(ws) && WTERMSIG(SIGABRT)) puts("aborted"); else puts("didn't abort");
if(0<=fork_and_reap(&ws, not_aborting, 0) && WIFSIGNALED(ws) && WTERMSIG(SIGABRT)) puts("aborted"); else puts("didn't abort");
}
As a general solution, you could test it by running it as a separate process, something like:
int main()
{
abort_routine();
printf("Didn't abort\n");
return 0;
}
You will be able to see when you run it as a child process if it aborted (printed some abort output instead, non zero exit) or not (printed that output and exited with zero).
This is roughly how the "death tests" in gtest work, https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#how-it-works
Under the hood, ASSERT_EXIT() spawns a new process and executes the death test statement in that process. The details of how precisely that happens depend on the platform
See the _Noreturn
keyword:
"The _Noreturn
keyword appears in a function declaration and specifies that the function does not return by executing the return statement or by reaching the end of the function body (it may return by executing longjmp). If the function declared _Noreturn
returns, the behavior is undefined. A compiler diagnostic is recommended if this can be detected."
If a function is declared as such, the compiler should give a diagnostics message. So you do not need to test it but can inspect the compiler messages and do a code review
https://en.cppreference.com/w/c/language/_Noreturn
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With