有没有办法在尝试写入文件的进程中生成错误? (用于测试目的)

时间:2014-06-04 08:22:00

标签: c++ linux testing io

在我编写测试时,有一个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错误。换句话说,我是&lt;&lt;运算符(以及任何基础I / O函数)生成错误,以使!f_file成为真。

这是一个测试,以确保错误确实最终投掷。所以我不打算以不同的方式编写代码。

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

我看了锁,但看起来不会起作用。当线程阻塞文件一段时间时,它会在没有超时的情况下阻塞。还有什么可以做的?

1 个答案:

答案 0 :(得分:1)

  

请注意,关闭文件并不是一个好主意,并且外部无法访问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, "10606216\n10606217\n10606218\n10606"..., 65536) = 65536
write(1, "7\n10613498\n10613499\n10613500\n106"..., 65536) = 65536
write(1, "779\n10620780\n10620781\n10620782\n1"..., 65536) = 65536
write(1, "\n15827311\n15827312\n15827313\n1582"..., 65536) = -1 EBADF (Bad file descriptor)
write(1, "\n15834593\n15834594\n15834595\n1583"..., 65536) = -1 EBADF (Bad file descriptor)
write(1, "\n15841875\n15841876\n15841877\n1584"..., 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