3

概括

使用时fgets(),我有错误检查代码,它会在fgets()返回null但尚未到达文件末尾时执行一些补救措施。我想练习这部分代码来验证它是否按预期工作。

是否有触发fgets()失败的规范方法?通过手动方式(以某种方式在调用 之间删除文件fgets())、一些测试设置(提供故意“损坏”的文件)或其他方式?


最小可重现示例

fgets_fail_test.cpp:

// Test code to show minimally reproducible example of fgets() error handling
// The desire is to manually trigger a failure in fgets()

#include <errno.h>
#include <iostream>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv) {
    FILE *fp = fopen("test_file.txt", "r"); //assume this works, not testing this
    char buf[100]; //assume large enough to hold data
    unsigned int lineno = 1;

    while (fgets(buf, 100, fp)) {
        std::cout << buf;
        lineno++;
    }

    if (feof(fp)) {
        std::cout << "End of file encountered.\n";
    }
    else if (ferror(fp)) { // how do I trigger an fgets error to cause this to return true?
        printf("Encountered read error at line no %u. Error: %d, %s.\n",
               lineno,
               errno,
               strerror(errno));
    }

    fclose(fp); // assume this works, not testing this

    return 0;
}

测试文件.txt:

ABCDEFG
HIJKLMN
OPQRSTU
VWXYZ
The quick brown fox
jumped over the
lazy dog.
Goodbye.

理论

虽然我可以简单地用一些测试脚手架替换有问题的代码(编写一个保持内部状态的 fgets 包装器,增加一个计数器,一旦它到达第 #N 行,它就会返回null并手动设置文件错误和 errno)我觉得应该有一些“内置”的方式来做到这一点?

如果唯一的解决方案是脚手架,我会这样做。老实说,也许我在这里太聪明了。

4

1 回答 1

1

在一些相关和链接的问题中给出了很多好的答案,这可能会使我的问题重复。虽然我在进行初始搜索时专注于fgets(),所以我无法找到这些。

一些相关的问题是:

因为我的程序从具有给定文件名格式的已知文件列表中读取数据,所以我需要使用一种允许我向程序提供错误文件的方法(无需修改代码)。我决定使用这个答案来做到这一点。

方法

为了生成一个会触发读取失败的错误文件fgets(),我利用了/proc/self/mem读取它会导致 I/O 错误的“功能”。

我删除了旧的输入文件,并将旧名称下的新文件链接到/proc/self/mem

ln -s /proc/self/mem test_file.txt

运行该文件然后产生以下输出:

Encountered read error at line no 1. Error: 5, Input/output error.

表明我们触发了错误。感谢@Artyer 的评论,他们最初将我与相关问题联系起来。

于 2019-07-16T17:07:32.697 回答