【问题标题】:Is it possible to test that an abort-routine doesn't return?是否可以测试中止例程不返回?
【发布时间】:2019-04-19 10:22:47
【问题描述】:

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

这个 abort_routine() 的一个要求是它不能返回。

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

更新: 我没有使用 gtest,只有 llvm 的 lit 和类似的东西:return 0,return 1,assert(false)。

【问题讨论】:

标签: c++ c linux testing gcc


【解决方案1】:

这是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");
}

【讨论】:

    【解决方案2】:

    作为一般解决方案,您可以通过将其作为单独的进程运行来对其进行测试,例如:

    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() 生成一个新进程并在该进程中执行死亡测试语句。具体发生的精确程度取决于平台

    【讨论】:

    • 谢谢,但是……我们的测试系统将每个文件夹中的所有文件都解释为测试。所以我不确定我们是否可以添加一个实际上不是测试的特殊文件,而是一个单独的测试过程......
    • 给它一个特殊的命令行,比如“--die”,这样默认就以0退出?或者使用具有类似 gtest 描述的条件的单个二进制文件(我怀疑在 Windows 上使用命令行参数,例如 POSIX 上的“--death-test-x=this_test”和fork)。
    【解决方案3】:

    查看_Noreturn关键字:

    "_Noreturn关键字出现在函数声明中,指定函数不通过执行return语句或到达函数体末尾返回(它可能通过执行longjmp返回)。如果函数声明@ 987654325@ 返回,行为未定义。如果可以检测到,建议进行编译器诊断。"

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

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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-18
    • 1970-01-01
    • 2013-09-13
    相关资源
    最近更新 更多