Free topology in non-DD simulations
[gromacs.git] / src / testutils / cmdlinetest.h
blob4febb0d70e645ff95f8a431d37c66067be9c7577
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2012,2013,2014,2015,2016,2017,2018, 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.
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.
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.
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.
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.
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.
35 /*! \libinternal \file
36 * \brief
37 * Declares utilities testing command-line programs.
39 * \author Teemu Murtola <teemu.murtola@gmail.com>
40 * \inlibraryapi
41 * \ingroup module_testutils
43 #ifndef GMX_TESTUTILS_CMDLINETEST_H
44 #define GMX_TESTUTILS_CMDLINETEST_H
46 #include <functional>
47 #include <memory>
48 #include <string>
50 #include <gtest/gtest.h>
52 // arrayref.h is not strictly necessary for this header, but nearly all
53 // callers will need it to use the constructor that takes ArrayRef.
54 #include "gromacs/utility/arrayref.h"
55 #include "gromacs/utility/classhelpers.h"
57 namespace gmx
60 class ICommandLineModule;
61 class ICommandLineOptionsModule;
63 namespace test
66 class FloatingPointTolerance;
67 class IFileMatcherSettings;
68 class ITextBlockMatcherSettings;
69 class TestFileManager;
70 class TestReferenceChecker;
72 /*! \libinternal \brief
73 * Helper class for tests that need to construct command lines.
75 * This class helps in writing tests for command-line handling.
76 * The constructor method takes an array of const char pointers, specifying the
77 * command-line arguments, each as one array element. It is also possible to
78 * construct the command line by adding individual arguments with append() and
79 * addOption().
80 * The argc() and argv() methods can then be used to obtain `argc` and `argv`
81 * (non-const char pointers) arrays for passing into methods that expect these.
83 * Note that although the interface allows passing the argc and argv pointers
84 * to methods that modify them (typically as \p f(&argc(), argv())), currently
85 * the CommandLine object is not in a consistent state internally if the
86 * parameters are actually modified. Reading the command line is possible
87 * afterwards, but modification is not.
89 * If you need to construct command lines that refer to files on the file
90 * system, see CommandLineTestHelper and CommandLineTestBase for additional
91 * convenience utilities.
93 * All constructors and methods that modify this class may throw an
94 * std::bad_alloc. Const methods and accessors do not throw.
96 * \inlibraryapi
97 * \ingroup module_testutils
99 class CommandLine
101 public:
102 //! Initializes an empty command-line object.
103 CommandLine();
104 /*! \brief
105 * Initializes a command-line object from an array.
107 * \param[in] cmdline Array of command-line arguments.
109 * \p cmdline should include the binary name as the first element if
110 * that is desired in the output.
112 * This constructor is not explicit to make it possible to create a
113 * CommandLine object directly from a C array.
115 CommandLine(const ArrayRef<const char *const> &cmdline);
116 //! \copydoc CommandLine(const ArrayRef<const char *const> &)
117 CommandLine(const ArrayRef<const std::string> &cmdline);
118 //! Creates a deep copy of a command-line object.
119 CommandLine(const CommandLine &other);
120 ~CommandLine();
122 /*! \brief
123 * Initializes a command-line object in-place from an array.
125 * \param[in] cmdline Array of command-line arguments.
127 * \p cmdline should include the binary name as the first element if
128 * that is desired in the output.
130 * This function does the same as the constructor that takes a
131 * ArrayRef. Any earlier contents of the object are discarded.
133 * Strong exception safety.
135 void initFromArray(const ArrayRef<const char *const> &cmdline);
137 /*! \brief
138 * Appends an argument to the command line.
140 * \param[in] arg Argument to append.
142 * Strong exception safety.
144 void append(const char *arg);
145 //! Convenience overload taking a std::string.
146 void append(const std::string &arg) { append(arg.c_str()); }
147 /*! \brief
148 * Adds an option to the command line, typically a boolean.
150 * \param[in] name Name of the option to append, which
151 * should start with "-".
153 void addOption(const char *name);
154 /*! \brief
155 * Adds an option-value pair to the command line.
157 * \param[in] name Name of the option to append, which
158 * should start with "-".
159 * \param[in] value Value of the argument to append.
161 void addOption(const char *name, const char *value);
162 //! Convenience overload taking a std::string.
163 void addOption(const char *name, const std::string &value);
164 //! Overload taking an int.
165 void addOption(const char *name, int value);
166 //! Overload taking a double.
167 void addOption(const char *name, double value);
168 /*! \brief
169 * Appends all arguments from \p args to the command line.
171 * If the first argument of \p args does not start with a `-`, it is
172 * skipped, assuming it is a gmx module name and thus useless.
174 void merge(const CommandLine &args);
176 //! Returns argc for passing into C-style command-line handling.
177 int &argc();
178 //! Returns argv for passing into C-style command-line handling.
179 char **argv();
180 //! Returns argc for passing into C-style command-line handling.
181 int argc() const;
182 //! Returns argv for passing into C-style command-line handling.
183 const char *const *argv() const;
184 //! Returns a single argument.
185 const char *arg(int i) const;
187 //! Returns the command line formatted as a single string.
188 std::string toString() const;
190 //! Whether the command line contains the given option.
191 bool contains(const char *name) const;
193 private:
194 class Impl;
196 PrivateImplPointer<Impl> impl_;
199 /*! \libinternal \brief
200 * Helper class for tests that construct command lines that need to reference
201 * existing files.
203 * This class provides helper methods for:
205 * 1. Adding input files to a CommandLine instance by generating them from a
206 * string provided in the test (setInputFileContents()).
207 * 2. Adding output files to a CommandLine instance (setOutputFile()).
208 * 3. Checking the contents of some of the output files using
209 * TestReferenceData (setOutputFile() and checkOutputFiles()).
210 * 4. Static methods for easily executing command-line modules
211 * (various overloads of runModule()).
213 * All files created during the test are cleaned up at the end of the test.
215 * All methods can throw std::bad_alloc.
217 * \see TestFileManager
218 * \inlibraryapi
219 * \ingroup module_testutils
221 class CommandLineTestHelper
223 public:
224 /*! \brief
225 * Runs a command-line program that implements ICommandLineModule.
227 * \param[in,out] module Module to run.
228 * The function does not take ownership.
229 * \param[in,out] commandLine Command line parameters to pass.
230 * This is only modified if \p module modifies it.
231 * \returns The return value of the module.
232 * \throws unspecified Any exception thrown by the module.
234 static int
235 runModuleDirect(ICommandLineModule *module, CommandLine *commandLine);
236 /*! \brief
237 * Runs a command-line program that implements
238 * ICommandLineOptionsModule.
240 * \param[in,out] module Module to run.
241 * \param[in,out] commandLine Command line parameters to pass.
242 * This is only modified if \p module modifies it.
243 * \returns The return value of the module.
244 * \throws unspecified Any exception thrown by the module.
246 static int
247 runModuleDirect(std::unique_ptr<ICommandLineOptionsModule> module,
248 CommandLine *commandLine);
249 /*! \brief
250 * Runs a command-line program that implements
251 * ICommandLineOptionsModule.
253 * \param[in] factory Factory method for the module to run.
254 * \param[in,out] commandLine Command line parameters to pass.
255 * This is only modified if the module modifies it.
256 * \returns The return value of the module.
257 * \throws unspecified Any exception thrown by the factory or the
258 * module.
260 static int
261 runModuleFactory(const std::function<std::unique_ptr<ICommandLineOptionsModule>()> &factory,
262 CommandLine *commandLine);
264 /*! \brief
265 * Initializes an instance.
267 * \param fileManager File manager to use for generating temporary
268 * file names and to track temporary files.
270 explicit CommandLineTestHelper(TestFileManager *fileManager);
271 ~CommandLineTestHelper();
273 /*! \brief
274 * Generates and sets an input file.
276 * \param[in,out] args CommandLine to which to add the option.
277 * \param[in] option Option to set.
278 * \param[in] extension Extension for the file to create.
279 * \param[in] contents Text to write to the input file.
281 * Creates a temporary file with contents from \p contents, and adds
282 * \p option to \p args with a value that points to the generated file.
284 void setInputFileContents(CommandLine *args, const char *option,
285 const char *extension,
286 const std::string &contents);
287 /*! \brief
288 * Generates and sets an input file.
290 * \param[in,out] args CommandLine to which to add the option.
291 * \param[in] option Option to set.
292 * \param[in] extension Extension for the file to create.
293 * \param[in] contents Text to write to the input file.
295 * Creates a temporary file with contents from \p contents (each array
296 * entry on its own line), and adds \p option to \p args with a value
297 * that points to the generated file.
299 void setInputFileContents(CommandLine *args, const char *option,
300 const char *extension,
301 const ArrayRef<const char *const> &contents);
302 /*! \brief
303 * Sets an output file parameter and adds it to the set of tested files.
305 * \param[in,out] args CommandLine to which to add the option.
306 * \param[in] option Option to set.
307 * \param[in] filename Name of the output file.
308 * \param[in] matcher Specifies how the contents of the file are
309 * tested.
311 * This method does the following:
312 * - Adds \p option to \p args to point a temporary file name
313 * constructed from \p filename.
314 * - Makes checkOutputFiles() to check the contents of the file
315 * against reference data, using \p matcher.
316 * - Marks the temporary file for removal at test teardown.
318 * \p filename is given to TestTemporaryFileManager to make a unique
319 * filename for the temporary file.
320 * If \p filename starts with a dot, a unique number is prefixed (such
321 * that it is possible to create multiple files with the same extension
322 * by just specifying the extension for every call of setOutputFile()).
324 * If the output file is needed to trigger some computation, or is
325 * unconditionally produced by the code under test, but the contents
326 * are not interesting for the test, use NoContentsMatch as the matcher.
327 * Note that the existence of the output file is still verified.
329 void setOutputFile(CommandLine *args, const char *option,
330 const char *filename,
331 const ITextBlockMatcherSettings &matcher);
332 //! \copydoc setOutputFile(CommandLine *, const char *, const char *, const ITextBlockMatcherSettings &)
333 void setOutputFile(CommandLine *args, const char *option,
334 const char *filename,
335 const IFileMatcherSettings &matcher);
337 /*! \brief
338 * Checks output files added with setOutputFile() against reference
339 * data.
341 * \param checker Reference data root location where the reference
342 * data is stored.
344 * The file contents are tested verbatim, using direct string
345 * comparison. The text can be found verbatim in the reference data
346 * XML files for manual inspection.
348 * Generates non-fatal test failures if some output file contents do
349 * not match the reference data.
351 void checkOutputFiles(TestReferenceChecker checker) const;
353 private:
354 class Impl;
356 PrivateImplPointer<Impl> impl_;
359 /*! \libinternal \brief
360 * Test fixture for tests that call a single command-line program with
361 * input/output files.
363 * This class provides a convenient package for using CommandLineTestHelper in
364 * a test that do not need special customization. It takes care of creating
365 * the other necessary objects (like TestFileManager, TestReferenceData, and
366 * CommandLine) and wrapping the methods from CommandLineTestHelper such that
367 * extra parameters are not needed. Additionally, it provides setInputFile()
368 * as a convenience function for adding a fixed input file, pointing to a file
369 * that resides in the source tree.
371 * \see CommandLineTestHelper
372 * \inlibraryapi
373 * \ingroup module_testutils
375 class CommandLineTestBase : public ::testing::Test
377 public:
378 CommandLineTestBase();
379 ~CommandLineTestBase() override;
381 /*! \brief
382 * Sets an input file.
384 * \param[in] option Option to set.
385 * \param[in] filename Name of the input file.
387 * \see TestFileManager::getInputFilePath()
389 void setInputFile(const char *option, const char *filename);
390 //! \copydoc setInputFile(const char *, const char *);
391 void setInputFile(const char *option, const std::string &filename);
392 /*! \brief
393 * Sets an input file that may be modified. The file is copied to a
394 * temporary file, which is used as the test input
396 * \param[in] option Option to set.
397 * \param[in] filename Name of the input file.
400 void setModifiableInputFile(const char *option, const char *filename);
401 //! \copydoc setModifiableInputFile(const char *, const char *);
402 void setModifiableInputFile(const char *option, const std::string &filename);
403 /*! \brief
404 * Generates and sets an input file.
406 * \see CommandLineTestHelper::setInputFileContents()
408 void setInputFileContents(const char *option,
409 const char *extension,
410 const std::string &contents);
411 /*! \brief
412 * Generates and sets an input file.
414 * \see CommandLineTestHelper::setInputFileContents()
416 void setInputFileContents(const char *option,
417 const char *extension,
418 const ArrayRef<const char *const> &contents);
419 /*! \brief
420 * Sets an output file parameter and adds it to the set of tested files.
422 * \see CommandLineTestHelper::setOutputFile()
424 void setOutputFile(const char *option, const char *filename,
425 const ITextBlockMatcherSettings &matcher);
426 /*! \brief
427 * Sets an output file parameter and adds it to the set of tested files.
429 * \see CommandLineTestHelper::setOutputFile()
431 void setOutputFile(const char *option, const char *filename,
432 const IFileMatcherSettings &matcher);
433 /*! \brief
434 * Sets a file parameter that is used for input and modified as output. The input file
435 * is copied to a temporary file that is used as input and can be modified.
437 void setInputAndOutputFile(const char *option, const char *filename,
438 const ITextBlockMatcherSettings &matcher);
439 //! \copydoc setInputAndOutputFile(const char *, const char *, const ITextBlockMatcherSettings&);
440 void setInputAndOutputFile(const char *option, const char *filename,
441 const IFileMatcherSettings &matcher);
443 /*! \brief
444 * Returns the internal CommandLine object used to construct the
445 * command line for the test.
447 * Derived test fixtures can use this to add additional options, and
448 * to access the final command line to do the actual call that is being
449 * tested.
451 * Does not throw.
453 CommandLine &commandLine();
454 /*! \brief
455 * Returns the internal TestFileManager object used to manage the
456 * files.
458 * Derived test fixtures can use this to manage files in cases the
459 * canned methods are not sufficient.
461 * Does not throw.
463 TestFileManager &fileManager();
464 /*! \brief
465 * Returns the root reference data checker.
467 * Derived test fixtures can use this to check other things than output
468 * file contents.
470 TestReferenceChecker rootChecker();
471 /*! \brief
472 * Sets the tolerance for floating-point comparisons.
474 * All following floating-point comparisons using the checker will use
475 * the new tolerance.
477 * Does not throw.
479 void setDefaultTolerance(const FloatingPointTolerance &tolerance);
480 /*! \brief
481 * Checks the output of writeHelp() against reference data.
483 void testWriteHelp(ICommandLineModule *module);
484 /*! \brief
485 * Checks output files added with setOutputFile() against reference
486 * data.
488 * \see CommandLineTestHelper::checkOutputFiles()
490 void checkOutputFiles();
492 private:
493 class Impl;
495 PrivateImplPointer<Impl> impl_;
498 } // namespace test
499 } // namespace gmx
501 #endif