5

I am developing a lib for a Linux project that stores files using boost::serialization. Because the files might be very large (1-50 GiB) and the program might fail writing them at some point (we are talking about thousands of them) I want to use a simple backup system to recover the files if they are not valid.

I have to test this using QtTests (the Qt unit test suite), but I could add additional libs if neccessary. The question is now how to test the backup system. In theory the test needs to let the ofstream ofs add invalid data after a given amount of data.

Here is the source code of the function in question. I am already testing the saving process itself, only the backup system could only be tested by hand.

The code (glued together and shortened to one method):

void DataStore::storeNodeData(TrajectoryDataSet data) {
   string path = getDataFileName(data);
   string oldPath = getDataFileName(data).append(".old");

   if (access(path.c_str(), F_OK) == 0 &&
      access(oldPath.c_str(), F_OK) != 0) {
      if (rename(path.c_str(), oldPath.c_str()) != 0) {
         throw FileSystemException("Unable to rename file to '.old'.");
      }
   }

   bool broken = false;
   ofstream ofs(path);
   boost::archive::text_oarchive oa(ofs);
   oa << data;
   if (!ofs.good())
      broken = true;
   ofs.close();

   //File verification
   TrajectoryDataSet fData;
   ifstream ifs(path);
   boost::archive::text_iarchive ia(ifs);
   ia >> fData;
   ifs.close();
   if (fData != data)
      broken = true;

   if (broken) {
      rename(oldPath.c_str(), path.c_str());
      throw FileSystemException("Unable write valid file.");
   } else if (access(oldPath.c_str(), F_OK) != -1 &&
      unlink(oldPath.c_str()) != 0)
      throw FileSystemException("Unable to delete backup file.");
}
2
  • Are you asking about unit-testing the code snippet ? how do you want to test the successful file writing- simply write it to disk ? this is not unit-testing.
    – Rsf
    Aug 17, 2018 at 12:44
  • @Rfs I want to test the parts of the code triggered by broken = true; and if possible by an return value of -1 (!= 0) for rename and unlink. In general the error handling of the method.
    – msebas
    Aug 19, 2018 at 10:25

1 Answer 1

1

How would you test it manually? Then wonder can I automate this later?

One scenario is that the disk it is writing to is unmounted for a short while, this probably result in some sort of error:

  • Thread the test and in parallel unmount the file system on which the data gets written.

This will result in a end-2-end test, needing a filesystem, data-files, setup time and probably is slow.

Now I can come-up with more scenarios, but I think you want to be able to inject a mock of ofs and let its good() method return false just for this test, afterwards verify your recovery system worked. E.g. decoupling and unit-testing.

2
  • I test it by hand using the debugger to stop the process, then modify the file by hand and let the program continue. My problem is actually the process of injecting a mock, because ofstream is inheriting the relevant methods from basic_ostream as non virtual methods.
    – msebas
    Aug 27, 2018 at 9:53
  • OK, after a bit of research I think there is no way to mock ofstream without an additional wrapper class used by my code. Instead I mocked the file using posix pipes (mkfifo), which is problematic because of POSIX SIGPIPE, which might occur and result in tests that are possibly hard to control. But they are testing what I want.
    – msebas
    Aug 27, 2018 at 16:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.