c - 如何捕捉对 exit() 的调用(用于单元测试)

标签 c unit-testing exit

我正在为个人项目编写一个动态数组,并尝试对所有函数进行单元测试。我正在尝试为 util_dyn_array_check_index() 编写单元测试,但在这样做时遇到了问题,因为我做出了调用 exit(-1) 的设计决定,如果有索引越界。我想检查我的单元测试,它在提供无效索引时调用 exit()。但是如果我给它一个无效的索引,它就会退出我的测试程序。是否有可能以某种方式捕捉到对 exit() 的调用被抛出,或者在我的测试程序中重新定义 exit() 以防止它结束测试?

来自 this answer我查看了 atexit(),但它看起来并没有停止退出,只是在退出前执行一个或多个用户定义的函数。这对我不起作用,因为在此之后我还有其他测试要运行。我最后的想法是我可以使 util_dyn_array_check_index() 成为一个宏而不是一个函数,并重新定义 exit() 成为我测试程序中的一个不同的函数,但我会如果可以避免,我宁愿不将其设为宏。

这是我的代码:

这个结构的细节并不重要,只是为了完整性而提供

//basically a Vec<T>
typedef struct {
    //a pointer to the data stored
    void * data;
    //the width of the elements to be stored in bytes
    size_t stride;
    //the number of elements stored
    size_t len;
    //the number of elements able to be stored without reallocating
    size_t capacity;
} util_dyn_array;

这是我要测试的功能。

//exits with -1 if index is out of bounds
inline void util_dyn_array_check_index(util_dyn_array * self, size_t index) {
    if (index >= self->len) {
        exit(-1);
    }
    return;
}

这是我希望测试的框架(为清楚起见,省略了一些我用来使编写测试更好的宏魔法)。

bool test_dyn_array_check_index() {
    util_dyn_array vector = util_dyn_array_new(sizeof(int), 16);
    for(int i = 0; i < 16; i++) {
        util_dyn_array_push(&vector, (void*)&i);
    }

    for(int i = 0; i < 16; i++) {
        //if nothing happens, its successful
        util_dyn_array_check_index(&vector, i);
    }

    //somehow check that it calls exit without letting it crash my program
    {
        util_dyn_array_check_index(&vector, 16);
    }

    return true;

}

显然我可以更改我的代码以返回 bool 或写入 errno,但我更希望它退出,因为它通常是一个无法恢复的错误。

最佳答案

在标准 C 中定义另一个 exit() 是 UB(如果包含 header ,则既作为函数又作为宏)。不过,在许多环境中,您很可能能够摆脱它。

话虽如此,在这里做这样的事情是没有意义的,因为我们正在谈论exit()。该函数不希望在此之后继续执行,因此这几乎迫使您将其替换为 longjmp() 或使用文本替换将其转换为 return (假设 void 返回类型)。在这两种情况下,这意味着您需要假设函数不会让事物处于损坏状态(比如持有一些资源)。这是一个很多假设,但如果您的单元测试框架打算绑定(bind)到这个特定项目,这可能是一个合理的出路。

与其尝试修改被测试函数的行为,我建议您将对在自己的进程中运行测试的支持添加到您的测试框架中。除了能够测试这些东西之外,还有很多优点。例如,您可以免费并行运行测试并隔离它们之间的许多副作用。

关于c - 如何捕捉对 exit() 的调用(用于单元测试),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64190847/

相关文章:

python - 如何从外部停止执行 Python 函数?

在 while 循环中使用 continue 后代码未执行

java - 如何在android中以分钟和秒为单位获取音频长度

AngularJS - 带 $timeout 的单元测试

python - Pygame 窗口没有关闭

erlang - 通过退出信号传递变量 [Erlang]

c - 如何打印内存地址?

c - 在 C 中使用文字值与计算值时答案不正确

java - 具有泛型类型的 Mockito 和 RestTemplate

asp.net-mvc - 为什么要测试我的 HTMLHelpers?