是否可以测试中止例程不返回?

时间:2019-04-19 10:22:48

标签: c++ c linux testing gcc

我必须测试一个提供其自己的abort_routine()函数的库(该库在内部调用abort(),但是实现可能会更改)。

此abort_routine()的要求之一是它可能不会返回。

我想知道是否可以测试此要求?

更新: 我没有使用gtest,只有llvm点亮了,诸如此类:返回0,返回1,assert(false)。

3 个答案:

答案 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返回,则行为未定义。如果可以检测到此错误,建议使用编译器诊断。”

如果这样声明一个函数,则编译器应给出诊断消息。因此,您无需测试它,但可以检查编译器消息并进行代码审查

https://en.cppreference.com/w/c/language/_Noreturn