Utility class for temporary unit testing files.
authorTeemu Murtola <teemu.murtola@gmail.com>
Wed, 16 May 2012 17:32:04 +0000 (20:32 +0300)
committerTeemu Murtola <teemu.murtola@gmail.com>
Thu, 17 May 2012 04:59:45 +0000 (07:59 +0300)
Added a utility class for constructing unique names for per-test
temporary files and for automatically removing them at test teardown.

Change-Id: I4ddf4a39d399518b8764be0af41bb423269e245c

src/gromacs/commandline/tests/cmdlinehelpwriter.cpp
src/testutils/datapath.cpp
src/testutils/datapath.h

index 0aceb2139601972b12699defc1eba233e2ff60a8..a7bccea301275d2e257a33424bebd2114cb4bce3 100644 (file)
@@ -55,6 +55,7 @@
 #include "gromacs/selection/selectioncollection.h"
 #include "gromacs/utility/file.h"
 
+#include "testutils/datapath.h"
 #include "testutils/stringtest.h"
 
 namespace
@@ -63,35 +64,19 @@ namespace
 class CommandLineHelpWriterTest : public ::gmx::test::StringTestBase
 {
     public:
-        CommandLineHelpWriterTest();
-        ~CommandLineHelpWriterTest();
-
         void checkHelp(gmx::CommandLineHelpWriter *writer);
 
-        std::string                     helpfile_;
+        gmx::test::TestTemporaryFileManager tempFiles_;
 };
 
-CommandLineHelpWriterTest::CommandLineHelpWriterTest()
-{
-    const ::testing::TestInfo *test_info =
-        ::testing::UnitTest::GetInstance()->current_test_info();
-    // TODO: Make a common helper method, which would also specify directory
-    helpfile_ = std::string(test_info->test_case_name())
-        + "_" + test_info->name() + ".txt";
-}
-
-CommandLineHelpWriterTest::~CommandLineHelpWriterTest()
-{
-    std::remove(helpfile_.c_str());
-}
-
 void CommandLineHelpWriterTest::checkHelp(gmx::CommandLineHelpWriter *writer)
 {
-    gmx::File file(helpfile_, "w");
+    std::string filename = tempFiles_.getTemporaryFilePath("helptext.txt");
+    gmx::File file(filename, "w");
     writer->writeHelp(&file);
     file.close();
 
-    checkFileContents(helpfile_, "HelpText");
+    checkFileContents(filename, "HelpText");
 }
 
 
index c72aa32c1d8d1c4f9ca271c17fc12febf951893e..55172e4a3673dd69a552627863cd407ab0dd5688 100644 (file)
  */
 /*! \internal \file
  * \brief
- * Implements functions in datapath.h.
+ * Implements functions and classes in datapath.h.
  *
  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
  * \ingroup module_testutils
  */
 #include "datapath.h"
 
+#include <cstdio>
+
+#include <set>
+#include <string>
+
+#include <gtest/gtest.h>
+
 #include "gromacs/utility/gmxassert.h"
 #include "gromacs/utility/path.h"
 
@@ -65,5 +72,71 @@ void setTestDataPath(const char *path)
     g_testDataPath = path;
 }
 
+/********************************************************************
+ * TestTemporaryFileManager::Impl
+ */
+
+/*! \internal \brief
+ * Private implementation class for TestTemporaryFileManager.
+ *
+ * \ingroup module_testutils
+ */
+class TestTemporaryFileManager::Impl
+{
+    public:
+        //! Container type for names of temporary files.
+        typedef std::set<std::string> FileNameList;
+
+        /*! \brief
+         * Try to remove all temporary files.
+         *
+         * Does not throw; errors (e.g., missing files) are silently ignored.
+         */
+        void removeFiles();
+
+        //! List of unique paths returned by getTemporaryFilePath().
+        FileNameList            files_;
+};
+
+void TestTemporaryFileManager::Impl::removeFiles()
+{
+    FileNameList::const_iterator i;
+    for (i = files_.begin(); i != files_.end(); ++i)
+    {
+        std::remove(i->c_str());
+    }
+    files_.clear();
+}
+
+/********************************************************************
+ * TestTemporaryFileManager
+ */
+
+TestTemporaryFileManager::TestTemporaryFileManager()
+    : impl_(new Impl)
+{
+}
+
+TestTemporaryFileManager::~TestTemporaryFileManager()
+{
+    impl_->removeFiles();
+}
+
+std::string TestTemporaryFileManager::getTemporaryFilePath(const char *suffix)
+{
+    const ::testing::TestInfo *test_info =
+        ::testing::UnitTest::GetInstance()->current_test_info();
+    // TODO: Add the path of the test binary
+    std::string filename = std::string(test_info->test_case_name())
+        + "_" + test_info->name();
+    if (suffix[0] != '.')
+    {
+        filename.append("_");
+    }
+    filename.append(suffix);
+    impl_->files_.insert(filename);
+    return filename;
+}
+
 } // namespace test
 } // namespace gmx
index a996e07ab51b5b34751040c6440bf3d2474c18df..a2a5a4645d085d8f087ecdb8fccf8775dd5c90fc 100644 (file)
  */
 /*! \libinternal \file
  * \brief
- * Functions for accessing test input files.
+ * Functions for constructing file names for test files.
  *
- * Functions in this header provide methods to access data files that are
- * located in the test source directory.  This is typically used to provide
- * input files for the tests.
+ * Functions getTestFilePath() and getTestDataPath() provide means to access
+ * data files that are located in the test source directory.  This is typically
+ * used to provide input files for the tests.
+ *
+ * For temporary files used within a single test (typically in testing code
+ * that writes into files), gmx::test::TestTemporaryFileManager is provided.
  *
  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
  * \inlibraryapi
@@ -53,6 +56,8 @@
 
 #include <string>
 
+#include "gromacs/utility/common.h"
+
 namespace gmx
 {
 /*! \libinternal \brief
@@ -99,6 +104,52 @@ const char *getTestDataPath();
  */
 void setTestDataPath(const char *path);
 
+/*! \libinternal \brief
+ * Helper for tests that need temporary output files.
+ *
+ * To be used as a member in a test fixture class, this class provides
+ * getTemporaryFilePath() method that returns a path for creating file names
+ * for temporary files.  The returned path contains the name of the running
+ * test, making it unique across tests.  Additionally, this class takes care of
+ * removing any temporary files (i.e., all paths returned by
+ * getTemporaryFilePath()) at test teardown (i.e., when the
+ * TestTemporaryFileManager is desctructed).
+ *
+ * \inlibraryapi
+ * \ingroup module_testutils
+ */
+class TestTemporaryFileManager
+{
+    public:
+        TestTemporaryFileManager();
+        /*! \brief
+         * Frees internal storage and deletes any accessed file paths.
+         *
+         * Any errors (e.g., missing files) encountered while deleting the
+         * files are ignored.
+         */
+        ~TestTemporaryFileManager();
+
+        /*! \brief
+         * Creates a name for a temporary file within a single unit test.
+         *
+         * \param[in] suffix  Suffix to add to the file name (should contain an
+         *      extension if one is desired).
+         * \returns   Temporary file name that includes the test name and
+         *      \p suffix.
+         *
+         * This method should only be called from within a Google Test test.
+         * Two calls with the same \p suffix return the same string within the
+         * same test.
+         */
+        std::string getTemporaryFilePath(const char *suffix);
+
+    private:
+        class Impl;
+
+        PrivateImplPointer<Impl> impl_;
+};
+
 } // namespace test
 } // namespace gmx