正确的方法来测试文件夹的可读性/可写性

时间:2012-09-24 13:02:39

标签: c++ linux unit-testing

我编写了一个函数来测试文件夹的可读性/可写性。

对于单元测试,我需要生成不同的情况:

  • 包含可读写文件的文件夹
  • 包含可读文件(不可写)的文件夹
  • 文件夹不可写且不可读。

这是我来到的功能的代码,到目前为止:

void FileUtils::checkPath(std::string path, bool &readable, bool &writable)
{
   namespace bf = boost::filesystem;
   std::string filePath = path + "/test.txt";

   // remove a possibly existing test file
   remove(filePath.c_str());

   // check that the path exists
   if(!bf::is_directory(path))
   {
      readable = writable = false;
      return;
   }

   // try to write in the location
   std::ofstream outfile (filePath.c_str());
   outfile << "I can write!" << std::endl;
   outfile.close();

   if(!outfile.fail() && !outfile.bad())
   {
      writable = true;
   }

   // look for a file to read
   std::ifstream::pos_type size;
   char * memblock;
   for (bf::recursive_directory_iterator it(path); it != bf::recursive_directory_iterator(); ++it)
   {
      if (!is_directory(*it))
      {
         std::string sFilePath = it->path().string();
         std::ifstream file(sFilePath.c_str(), std::ios::in|std::ios::binary|std::ios::ate);
         if (file.is_open())
         {
           size = file.tellg();
           if(size > 0)
           {
              memblock = new char [1];
              file.seekg (0, std::ios::beg);
              file.read (memblock, 1);
              file.close();
              delete[] memblock;
              if(!file.fail() && !file.bad())
              {
                 readable = true;
              }
              break;
           }
         }
         else
         {
            // there is a non readable file in the folder
            // readable = false;
            break;
         }
      }
   }

   // delete the test file
   remove(filePath.c_str());
}

现在进行测试(使用Google测试完成):

TEST_F(FileUtilsTest, shouldCheckPath)
{
   // given an existing folder
   namespace fs = boost::filesystem;
   fs::create_directory("/tmp/to_be_deleted");

   bool readable = false, writable = false;

   FileUtils::checkPath("/tmp/to_be_deleted",readable, writable);

   fs::boost::filesystem::remove_all("/tmp/to_be_deleted");

   EXPECT_TRUE(readable && writable);
}

当我走得更远时,我会为其他案例增加更多。

现在游戏开放提出更好的解决方案: - )

2 个答案:

答案 0 :(得分:5)

检查权限的万无一失的方法是逐字检查文件模式。在目录权限的情况下,“可读”和“可写”的含义可能会令人惊讶:

  • 读取 - 允许您列出目录的内容
  • 写入 - 允许您创建,重命名,删除目录中的文件,实质上是修改内容列表(也需要执行)
  • 执行 - 允许您访问(读取和写入)和更改目录中文件的属性

因此,如果您的目录只设置了执行位,您仍然可以读取和写入其中的文件。通过关闭执行位,可以禁用对文件的访问。就所包含的文件而言,您可以从目录权限中找出最多的是:

  • --xr-x:现有文件可以读取和写入
  • -wxrwx:可以读取和写入现有文件,可以创建,重命名和删除文件
  • 否则:您根本无权访问这些文件

要确定文件是否可读但不可写(反之亦然),您需要检查文件本身的权限。该目录只能告诉您是否可以访问这些文件。

您可以使用stat() access() (请参阅BЈовић的评论)来查找文件或目录的权限。既然你已经使用了boost,你也可以使用boost::filesystem::status()来简单地包装stat()。

答案 1 :(得分:0)

为了便于携带和正确,测试文件/目录的可读性/可写性的唯一方法是从/向它读/写。权限模型可能非常复杂且不可移植(例如ACL),因此您无法简单地检查父目录的权限。此外,检查,然后尝试写入是竞争条件,因为权限可能在检查和写入之间发生变化。

如果你想要的是一个概率高,写入将成功,例如,如果你让用户为你的应用程序选择一个临时文件夹,只需尝试编写一个文件,然后删除它后。这可以让您知道在用户选择时目录是可写的。

为了保持健壮,总是假设文件系统操作将失败并进行设计,以便在它们执行时,会发生逻辑而不是崩溃。特别是,设计一个系统,以便用户可以找出权限错误的位置 - 因为有很多方法可以设置权限错误,有用的错误信息会有很长的路要走。