我必须测试一个提供其自己的abort_routine()函数的库(该库在内部调用abort(),但是实现可能会更改)。
此abort_routine()的要求之一是它可能不会返回。
我想知道是否可以测试此要求?
更新: 我没有使用gtest,只有llvm点亮了,诸如此类:返回0,返回1,assert(false)。
答案 0 :(得分:6)
这是fork
的一个很好的用例,我在测试中亲自使用。
您可以简单地fork()
,在子级_exit()
中运行该函数,获取结果,如果它指示通过SIGABRT
发出信号,则该子级将中止,否则就没有。
示例代码:
#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");
}
答案 1 :(得分:1)
作为一般解决方案,您可以通过将其作为单独的进程运行来进行测试,例如:
int main()
{
abort_routine();
printf("Didn't abort\n");
return 0;
}
您将能够看到它作为子进程运行的时机是否中止(打印一些中止输出,而不是非零退出)(打印该输出并以零退出)。
这大致就是gtest中的“死亡测试”如何工作的https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#how-it-works
在后台,ASSERT_EXIT()产生一个新进程并在该进程中执行死亡测试语句。具体如何发生的细节取决于平台
答案 2 :(得分:1)
请参见_Noreturn
关键字:
“ _Noreturn
关键字出现在函数声明中,并指定该函数不会通过执行return语句或到达函数主体的末尾而返回(可能通过执行longjmp返回)。声明_Noreturn
返回,则行为未定义。如果可以检测到此错误,建议使用编译器诊断。”
如果这样声明一个函数,则编译器应给出诊断消息。因此,您无需测试它,但可以检查编译器消息并进行代码审查