是否有一种方法在试图写入文件的进程中生成错误?(用于测试目的)

Is there a way to generate an error in a process attempting to write to a file? (for test purposes)

本文关键字:进程 测试 用于 文件 错误 一种 方法 是否      更新时间:2023-10-16

当我在编写测试时,有一个特殊的FILE*,我是这样处理的:

// first we open the file
bool FileOutput::open(std::string const& filename)
{
    if(f_file.is_open())
    {
        throw std::runtime_error("already open");
    }
    f_file.open(filename.c_str());
    if(!f_file.is_open())
    {
        return false;
    }
    return true;
}
// later we write to it
void FileOutput::internal_write(std::string const& data)
{
    f_file << data;
    if(!f_file)
    {
        throw std::runtime_error("I/O error: could not write to output.");
    }
}

在编写测试时,我想在internal_write()中触发一个I/O错误。换句话说,我就是<<操作符(以及任何底层I/O函数)生成一个错误,使!f_file变为真。

这是一个测试,以确保错误确实结束抛出。所以我并不打算用不同的方式编写代码。

请注意,关闭文件不是一个好主意,f_file不能从外部访问,并且没有close()函数(当对象被销毁时它会关闭)。

我研究了锁,但它看起来不像会工作。当线程阻塞文件一小段时间时,它会在这里阻塞而不会超时。还能做些什么呢?

请注意,关闭文件不是一个好主意,f_file不能从外部访问,也没有close()函数(它在对象被销毁时关闭)。

关闭坏只是因为f_file不可访问?如果是这样,那么写一个shell脚本,当你的测试程序运行时获取测试程序的PID并关闭所需的文件句柄。

脚本执行两个步骤:

1)运行lsof获取文件句柄

lsof -p PID | grep yourfile | awk '{print $4}' | tr -d wru

第4个字段将是文件句柄的编号。将其传递给环境变量HANDLE_ID_FROM_LSOF。

2)运行gdb关闭你需要变坏的句柄

gdb --batch-silent your-program -p PID -ex "call close($HANDLE_ID_FROM_LSOF)" -ex "detach"

运行gdb后,文件句柄将被关闭,希望你会得到一个你需要的错误。至少在strace中,它看起来像这样:

write(1, "10606216n10606217n10606218n10606"..., 65536) = 65536
write(1, "7n10613498n10613499n10613500n106"..., 65536) = 65536
write(1, "779n10620780n10620781n10620782n1"..., 65536) = 65536
write(1, "n15827311n15827312n15827313n1582"..., 65536) = -1 EBADF (Bad file descriptor)
write(1, "n15834593n15834594n15834595n1583"..., 65536) = -1 EBADF (Bad file descriptor)
write(1, "n15841875n15841876n15841877n1584"..., 65536) = -1 EBADF (Bad file descriptor)

下面是这个脚本的一个例子:

$ cat close_file.sh
#!/bin/sh
TARGET_PROG=$1
TARGET_PID=$2
TARGET_FILE=$3
TARGET_FILE_FD=$(lsof -p $TARGET_PID | grep seq.txt | awk '{print $4}' |  tr -d wur)
gdb --batch-silent $TARGET_PROG  -p $TARGET_PID -ex "call close($TARGET_FILE_FD)" -ex "detach"

第一个参数是程序的完整路径,第二个参数是进程ID,第三个参数是需要关闭的文件名。

这个例子展示了如何运行这个脚本。首先运行您的测试程序。然后运行脚本。下面是运行它的一个示例:

$ ./close_file.sh /usr/bin/seq 16640 seq.txt