Sort includes outside src/gromacs
[alexxy/gromacs.git] / src / testutils / testfilemanager.cpp
index fe54697a3e0d68e4a535e19874cbff40fc3947b7..0a2eb0f9e38b05839fad9df8d928b4092ce314a2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012, 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.
@@ -39,6 +39,8 @@
  * \author Teemu Murtola <teemu.murtola@gmail.com>
  * \ingroup module_testutils
  */
+#include "gmxpre.h"
+
 #include "testfilemanager.h"
 
 #include <cstdio>
 
 #include <gtest/gtest.h>
 
+#include "gromacs/options/basicoptions.h"
+#include "gromacs/options/options.h"
 #include "gromacs/utility/gmxassert.h"
 #include "gromacs/utility/path.h"
 
+#include "testutils/testoptions.h"
+
 namespace gmx
 {
 namespace test
@@ -72,9 +78,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 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.
          *
@@ -84,9 +104,27 @@ 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_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;
+
+//! \cond
+GMX_TEST_OPTIONS(TestFileManagerOptions, options)
+{
+    options->addOption(BooleanOption("delete-temporary-files")
+                           .store(&g_bDeleteFilesAfterTest)
+                           .description("At the end of each test case, delete temporary and output files"));
+}
+//! \endcond
 
 void TestFileManager::Impl::removeFiles()
 {
@@ -103,35 +141,55 @@ void TestFileManager::Impl::removeFiles()
  */
 
 TestFileManager::TestFileManager()
-    : impl_(new Impl)
+    : impl_(new Impl(Impl::s_globalOutputTempDirectory))
 {
 }
 
 TestFileManager::~TestFileManager()
 {
-    impl_->removeFiles();
+    if (g_bDeleteFilesAfterTest)
+    {
+        impl_->removeFiles();
+    }
 }
 
 std::string TestFileManager::getTemporaryFilePath(const char *suffix)
 {
-    // TODO: Add the path of the test binary
-    std::string filename = getTestSpecificFileName(suffix);
+    /* Configure a temporary directory from CMake, so that temporary
+     * output from a test goes to a location relevant to that
+     * test. Currently, files whose names are returned by this method
+     * get cleaned up (by default) at the end of all tests.
+     */
+    std::string filename =
+        Path::join(getOutputTempDirectory(),
+                   getTestSpecificFileName(suffix));
     impl_->files_.insert(filename);
     return filename;
 }
 
-std::string TestFileManager::getTestSpecificFileName(const char *suffix)
+std::string TestFileManager::getTemporaryFilePath(const std::string &suffix)
+{
+    return getTemporaryFilePath(suffix.c_str());
+}
+
+std::string TestFileManager::getTestSpecificFileNameRoot()
 {
     const ::testing::TestInfo *test_info =
             ::testing::UnitTest::GetInstance()->current_test_info();
-    std::string                filename = std::string(test_info->test_case_name())
+    std::string                filenameRoot = std::string(test_info->test_case_name())
         + "_" + test_info->name();
+    std::replace(filenameRoot.begin(), filenameRoot.end(), '/', '_');
+    return filenameRoot;
+}
+
+std::string TestFileManager::getTestSpecificFileName(const char *suffix)
+{
+    std::string filename = getTestSpecificFileNameRoot();
     if (suffix[0] != '.')
     {
         filename.append("_");
     }
     filename.append(suffix);
-    std::replace(filename.begin(), filename.end(), '/', '_');
     return filename;
 }
 
@@ -142,10 +200,21 @@ std::string TestFileManager::getInputFilePath(const char *filename)
 
 const char *TestFileManager::getInputDataDirectory()
 {
-    GMX_RELEASE_ASSERT(Impl::s_inputDirectory != NULL, "Test data path not set");
+    GMX_RELEASE_ASSERT(Impl::s_inputDirectory != NULL, "Path for test input files is not set");
     return Impl::s_inputDirectory;
 }
 
+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
+{
+    return impl_->outputTempDirectory_.c_str();
+}
+
 void TestFileManager::setInputDataDirectory(const char *path)
 {
     // There is no need to protect this by a mutex, as this is called in early
@@ -155,5 +224,23 @@ void TestFileManager::setInputDataDirectory(const char *path)
     Impl::s_inputDirectory = 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_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
 } // namespace gmx