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