Sort includes outside src/gromacs
[alexxy/gromacs.git] / src / testutils / testfilemanager.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013,2014, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*! \internal \file
36  * \brief
37  * Implements gmx::test::TestFileManager.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \ingroup module_testutils
41  */
42 #include "gmxpre.h"
43
44 #include "testfilemanager.h"
45
46 #include <cstdio>
47
48 #include <algorithm>
49 #include <set>
50 #include <string>
51
52 #include <gtest/gtest.h>
53
54 #include "gromacs/options/basicoptions.h"
55 #include "gromacs/options/options.h"
56 #include "gromacs/utility/gmxassert.h"
57 #include "gromacs/utility/path.h"
58
59 #include "testutils/testoptions.h"
60
61 namespace gmx
62 {
63 namespace test
64 {
65
66 /********************************************************************
67  * TestFileManager::Impl
68  */
69
70 /*! \internal \brief
71  * Private implementation class for TestFileManager.
72  *
73  * \ingroup module_testutils
74  */
75 class TestFileManager::Impl
76 {
77     public:
78         //! Global test input data path set with setDataInputDirectory().
79         static const char *s_inputDirectory;
80
81         //! Global temporary output directory for tests, set with setGlobalOutputTempDirectory().
82         static const char *s_globalOutputTempDirectory;
83
84         //! Container type for names of temporary files.
85         typedef std::set<std::string> FileNameList;
86
87         /*! \brief Constructor
88          *
89          * \param path Value for the outputTempDirectory, typically
90          * set by default from s_globalOutputTempDirectory */
91         explicit Impl(const char *path)
92             : outputTempDirectory_(path)
93         {
94             GMX_RELEASE_ASSERT(Directory::exists(outputTempDirectory_),
95                                "Directory for tests' temporary files does not exist");
96         }
97
98         /*! \brief
99          * Try to remove all temporary files.
100          *
101          * Does not throw; errors (e.g., missing files) are silently ignored.
102          */
103         void removeFiles();
104
105         //! List of unique paths returned by getTemporaryFilePath().
106         FileNameList            files_;
107
108         /*! \brief Temporary output directory local to the current
109          * test, set by a test with setOutputTempDirectory() if the
110          * global default is inappropriate. */
111         std::string outputTempDirectory_;
112 };
113
114 const char *TestFileManager::Impl::s_inputDirectory            = NULL;
115 const char *TestFileManager::Impl::s_globalOutputTempDirectory = NULL;
116 /** Controls whether TestFileManager should delete temporary files
117     after the test finishes. */
118 static bool g_bDeleteFilesAfterTest = true;
119
120 //! \cond
121 GMX_TEST_OPTIONS(TestFileManagerOptions, options)
122 {
123     options->addOption(BooleanOption("delete-temporary-files")
124                            .store(&g_bDeleteFilesAfterTest)
125                            .description("At the end of each test case, delete temporary and output files"));
126 }
127 //! \endcond
128
129 void TestFileManager::Impl::removeFiles()
130 {
131     FileNameList::const_iterator i;
132     for (i = files_.begin(); i != files_.end(); ++i)
133     {
134         std::remove(i->c_str());
135     }
136     files_.clear();
137 }
138
139 /********************************************************************
140  * TestFileManager
141  */
142
143 TestFileManager::TestFileManager()
144     : impl_(new Impl(Impl::s_globalOutputTempDirectory))
145 {
146 }
147
148 TestFileManager::~TestFileManager()
149 {
150     if (g_bDeleteFilesAfterTest)
151     {
152         impl_->removeFiles();
153     }
154 }
155
156 std::string TestFileManager::getTemporaryFilePath(const char *suffix)
157 {
158     /* Configure a temporary directory from CMake, so that temporary
159      * output from a test goes to a location relevant to that
160      * test. Currently, files whose names are returned by this method
161      * get cleaned up (by default) at the end of all tests.
162      */
163     std::string filename =
164         Path::join(getOutputTempDirectory(),
165                    getTestSpecificFileName(suffix));
166     impl_->files_.insert(filename);
167     return filename;
168 }
169
170 std::string TestFileManager::getTemporaryFilePath(const std::string &suffix)
171 {
172     return getTemporaryFilePath(suffix.c_str());
173 }
174
175 std::string TestFileManager::getTestSpecificFileNameRoot()
176 {
177     const ::testing::TestInfo *test_info =
178             ::testing::UnitTest::GetInstance()->current_test_info();
179     std::string                filenameRoot = std::string(test_info->test_case_name())
180         + "_" + test_info->name();
181     std::replace(filenameRoot.begin(), filenameRoot.end(), '/', '_');
182     return filenameRoot;
183 }
184
185 std::string TestFileManager::getTestSpecificFileName(const char *suffix)
186 {
187     std::string filename = getTestSpecificFileNameRoot();
188     if (suffix[0] != '.')
189     {
190         filename.append("_");
191     }
192     filename.append(suffix);
193     return filename;
194 }
195
196 std::string TestFileManager::getInputFilePath(const char *filename)
197 {
198     return Path::join(getInputDataDirectory(), filename);
199 }
200
201 const char *TestFileManager::getInputDataDirectory()
202 {
203     GMX_RELEASE_ASSERT(Impl::s_inputDirectory != NULL, "Path for test input files is not set");
204     return Impl::s_inputDirectory;
205 }
206
207 const char *TestFileManager::getGlobalOutputTempDirectory()
208 {
209     GMX_RELEASE_ASSERT(Impl::s_globalOutputTempDirectory != NULL, "Global path for temporary output files from tests is not set");
210     return Impl::s_globalOutputTempDirectory;
211 }
212
213 const char *TestFileManager::getOutputTempDirectory() const
214 {
215     return impl_->outputTempDirectory_.c_str();
216 }
217
218 void TestFileManager::setInputDataDirectory(const char *path)
219 {
220     // There is no need to protect this by a mutex, as this is called in early
221     // initialization of the tests.
222     GMX_RELEASE_ASSERT(Directory::exists(path),
223                        "Test data directory does not exist");
224     Impl::s_inputDirectory = path;
225 }
226
227 void TestFileManager::setGlobalOutputTempDirectory(const char *path)
228 {
229     // There is no need to protect this by a mutex, as this is called in early
230     // initialization of the tests.
231     GMX_RELEASE_ASSERT(Directory::exists(path),
232                        "Directory for tests' temporary files does not exist");
233     Impl::s_globalOutputTempDirectory = path;
234 }
235
236 void TestFileManager::setOutputTempDirectory(const std::string &path)
237 {
238     // There could be a need to protect this with a mutex, since it is
239     // intended to be used in test fixtures, not just during setup.
240     GMX_RELEASE_ASSERT(Directory::exists(path),
241                        "Directory for tests' temporary files does not exist");
242     impl_->outputTempDirectory_ = path;
243 }
244
245 } // namespace test
246 } // namespace gmx