Extend TestFileManager
authorMark Abraham <mark.j.abraham@gmail.com>
Mon, 27 Jan 2014 19:43:04 +0000 (20:43 +0100)
committerMark Abraham <mark.j.abraham@gmail.com>
Tue, 18 Feb 2014 14:12:05 +0000 (15:12 +0100)
A test fixture may wish to change the output temporary directory, and
should be able to do so without perturbing the global state from which
the test TestFileManager object is initialized.

The only client of this feature (the setup code) is updated
accordingly.

Minor fixes to existing documentation.

Change-Id: I7ba7a82964c05f12de107710655b6320d42ae99c

src/testutils/testfilemanager.cpp
src/testutils/testfilemanager.h
src/testutils/testoptions.cpp

index 0a7027ec5f1427dc61152080c24586779ce1d407..3d6f251975ce593ded162aa801f6b8b7b85816a6 100644 (file)
@@ -75,12 +75,23 @@ class TestFileManager::Impl
         //! Global test input data path set with setDataInputDirectory().
         static const char *s_inputDirectory;
 
-        //! Global temporary output directory for tests, set with setOutputTempDirectory().
-        static const char *s_outputTempDirectory;
+        //! Global temporary output directory for tests, set with setGlobalOutputTempDirectory().
+        static const char *s_globalOutputTempDirectory;
 
         //! Container type for names of temporary files.
         typedef std::set<std::string> FileNameList;
 
+        /*! \brief Constructor
+         *
+         * \param path Value for the outputTempDirectory, typically
+         * set by default from s_globalOutputTempDirectory */
+        explicit Impl(const char *path)
+            : outputTempDirectory_(path)
+        {
+            GMX_RELEASE_ASSERT(Directory::exists(outputTempDirectory_),
+                               "Directory for tests' temporary files does not exist");
+        }
+
         /*! \brief
          * Try to remove all temporary files.
          *
@@ -90,10 +101,15 @@ class TestFileManager::Impl
 
         //! List of unique paths returned by getTemporaryFilePath().
         FileNameList            files_;
+
+        /*! \brief Temporary output directory local to the current
+         * test, set by a test with setOutputTempDirectory() if the
+         * global default is inappropriate. */
+        std::string outputTempDirectory_;
 };
 
-const char *TestFileManager::Impl::s_inputDirectory      = NULL;
-const char *TestFileManager::Impl::s_outputTempDirectory = NULL;
+const char *TestFileManager::Impl::s_inputDirectory            = NULL;
+const char *TestFileManager::Impl::s_globalOutputTempDirectory = NULL;
 /** Controls whether TestFileManager should delete temporary files
     after the test finishes. */
 static bool g_bDeleteFilesAfterTest = true;
@@ -122,7 +138,7 @@ void TestFileManager::Impl::removeFiles()
  */
 
 TestFileManager::TestFileManager()
-    : impl_(new Impl())
+    : impl_(new Impl(Impl::s_globalOutputTempDirectory))
 {
 }
 
@@ -174,10 +190,15 @@ const char *TestFileManager::getInputDataDirectory()
     return Impl::s_inputDirectory;
 }
 
-const char *TestFileManager::getOutputTempDirectory()
+const char *TestFileManager::getGlobalOutputTempDirectory()
+{
+    GMX_RELEASE_ASSERT(Impl::s_globalOutputTempDirectory != NULL, "Global path for temporary output files from tests is not set");
+    return Impl::s_globalOutputTempDirectory;
+}
+
+const char *TestFileManager::getOutputTempDirectory() const
 {
-    GMX_RELEASE_ASSERT(Impl::s_outputTempDirectory != NULL, "Path for temporary output files from tests is not set");
-    return Impl::s_outputTempDirectory;
+    return impl_->outputTempDirectory_.c_str();
 }
 
 void TestFileManager::setInputDataDirectory(const char *path)
@@ -189,13 +210,22 @@ void TestFileManager::setInputDataDirectory(const char *path)
     Impl::s_inputDirectory = path;
 }
 
-void TestFileManager::setOutputTempDirectory(const char *path)
+void TestFileManager::setGlobalOutputTempDirectory(const char *path)
 {
     // There is no need to protect this by a mutex, as this is called in early
     // initialization of the tests.
     GMX_RELEASE_ASSERT(Directory::exists(path),
                        "Directory for tests' temporary files does not exist");
-    Impl::s_outputTempDirectory = path;
+    Impl::s_globalOutputTempDirectory = path;
+}
+
+void TestFileManager::setOutputTempDirectory(const std::string &path)
+{
+    // There could be a need to protect this with a mutex, since it is
+    // intended to be used in test fixtures, not just during setup.
+    GMX_RELEASE_ASSERT(Directory::exists(path),
+                       "Directory for tests' temporary files does not exist");
+    impl_->outputTempDirectory_ = path;
 }
 
 } // namespace test
index 62c3314824f2810f17a2caa30c9368dbf418b561..ea88776e4b3fbd3359116a3234ef17cc99374a8e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012,2013, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -67,7 +67,7 @@ namespace test
 {
 
 /*! \libinternal \brief
- * Helper for tests that need output files.
+ * Helper for tests that need input and 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
@@ -77,10 +77,18 @@ namespace test
  * getTemporaryFilePath()) at test teardown (i.e., when the
  * TestFileManager is destructed).
  *
- * Functions getInputFilePath() and getInputDataDirectory() provide means to
+ * In addition, class-level static accessors provide means to
  * access data files that are located in the test source directory.
- * This is used to provide input files for the tests, and also to store test
- * reference data persistently (see TestReferenceData).
+ * This is used to provide input files for the tests, and also to
+ * store test reference data persistently (see TestReferenceData).
+ *
+ * Note that setInputDataDirectory() and
+ * setGlobalOutputTempDirectory() must be called in setup code, before
+ * creating any objects of this class that are used for accessing the
+ * paths for these respective directories. Code in tests should avoid
+ * calling setGlobalOutputTempDirectory(), and instead instantiate an
+ * object and use setOutputTempDirectory(), so that the global state
+ * is not changed.
  *
  * \inlibraryapi
  * \ingroup module_testutils
@@ -112,6 +120,27 @@ class TestFileManager
          */
         std::string getTemporaryFilePath(const char *suffix);
 
+        /*! \brief Returns the path to the output temporary directory
+         * for tests which use this TestFileManager object.
+         *
+         * \returns Path to output temporary directory
+         */
+        const char *getOutputTempDirectory() const;
+
+        /*! \brief Sets the output temporary directory for tests which
+         * use this TestFileManager object.
+         *
+         * \param[in] path  Path at which test should write temporary files
+         *
+         * \p path must name an existing directory. An internal copy
+         * of path is made. The caller is responsible for holding a
+         * valid mutex on the object before calling this member
+         * function.
+         */
+        void setOutputTempDirectory(const std::string &path);
+
+        // static functions follow
+
         /*! \brief
          * Creates a file name for use within a single unit test.
          *
@@ -143,13 +172,6 @@ class TestFileManager
          */
         static const char *getInputDataDirectory();
 
-        /*! \brief
-         * Returns the path to the test output temporary directory.
-         *
-         * \returns Path to output temporary directory for the test executable.
-         */
-        static const char *getOutputTempDirectory();
-
         /*! \brief
          * Sets the test input directory.
          *
@@ -162,17 +184,26 @@ class TestFileManager
          */
         static void setInputDataDirectory(const char *path);
 
-        /*! \brief
-         * Sets the test output temporary directory.
+        /*! \brief Returns the path to the global test output
+         * temporary directory for future TestFileManager objects.
          *
-         * \param[in] path  Path at which test should write temporary files
+         * \returns Path to default output temporary directory for the test executable.
+         */
+        static const char *getGlobalOutputTempDirectory();
+
+        /*! \brief Sets the default global test output temporary
+         * directory for future TestFileManager objects.
+         *
+         * \param[in] path  Path at which tests should write temporary files
          *
          * \p path must name an existing directory.
          *
-         * This function is automatically called by unittest_main.cpp through
-         * initTestUtils().
+         * This function is automatically called by unittest_main.cpp
+         * through initTestUtils(). Test fixtures should call
+         * setOutputTempDirectory(), rather than change the global
+         * state.
          */
-        static void setOutputTempDirectory(const char *path);
+        static void setGlobalOutputTempDirectory(const char *path);
 
     private:
         class Impl;
index cf7f3bcee94680cba33d39f431304d2c0a18885b..0b5e1c895175866ca9ce0504c7fd31883a796eec 100644 (file)
@@ -153,7 +153,7 @@ void initTestUtils(const char *dataPath, const char *tempPath, int *argc, char *
         }
         if (tempPath != NULL)
         {
-            TestFileManager::setOutputTempDirectory(tempPath);
+            TestFileManager::setGlobalOutputTempDirectory(tempPath);
         }
         bool    bHelp = false;
         Options options(NULL, NULL);