2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2012,2013,2014,2015,2016,2017, 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
37 * Declares utilities testing command-line programs.
39 * \author Teemu Murtola <teemu.murtola@gmail.com>
41 * \ingroup module_testutils
43 #ifndef GMX_TESTUTILS_CMDLINETEST_H
44 #define GMX_TESTUTILS_CMDLINETEST_H
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 ConstArrayRef.
54 #include "gromacs/utility/arrayref.h"
55 #include "gromacs/utility/classhelpers.h"
60 class ICommandLineModule
;
61 class ICommandLineOptionsModule
;
66 class IFileMatcherSettings
;
67 class ITextBlockMatcherSettings
;
68 class TestFileManager
;
69 class TestReferenceChecker
;
71 /*! \libinternal \brief
72 * Helper class for tests that need to construct command lines.
74 * This class helps in writing tests for command-line handling.
75 * The constructor method takes an array of const char pointers, specifying the
76 * command-line arguments, each as one array element. It is also possible to
77 * construct the command line by adding individual arguments with append() and
79 * The argc() and argv() methods can then be used to obtain `argc` and `argv`
80 * (non-const char pointers) arrays for passing into methods that expect these.
82 * Note that although the interface allows passing the argc and argv pointers
83 * to methods that modify them (typically as \p f(&argc(), argv())), currently
84 * the CommandLine object is not in a consistent state internally if the
85 * parameters are actually modified. Reading the command line is possible
86 * afterwards, but modification is not.
88 * If you need to construct command lines that refer to files on the file
89 * system, see CommandLineTestHelper and CommandLineTestBase for additional
90 * convenience utilities.
92 * All constructors and methods that modify this class may throw an
93 * std::bad_alloc. Const methods and accessors do not throw.
96 * \ingroup module_testutils
101 //! Initializes an empty command-line object.
104 * Initializes a command-line object from an array.
106 * \param[in] cmdline Array of command-line arguments.
108 * \p cmdline should include the binary name as the first element if
109 * that is desired in the output.
111 * This constructor is not explicit to make it possible to create a
112 * CommandLine object directly from a C array.
114 CommandLine(const ConstArrayRef
<const char *> &cmdline
);
115 //! Creates a deep copy of a command-line object.
116 CommandLine(const CommandLine
&other
);
120 * Initializes a command-line object in-place from an array.
122 * \param[in] cmdline Array of command-line arguments.
124 * \p cmdline should include the binary name as the first element if
125 * that is desired in the output.
127 * This function does the same as the constructor that takes a
128 * ConstArrayRef. Any earlier contents of the object are discarded.
130 * Strong exception safety.
132 void initFromArray(const ConstArrayRef
<const char *> &cmdline
);
135 * Appends an argument to the command line.
137 * \param[in] arg Argument to append.
139 * Strong exception safety.
141 void append(const char *arg
);
142 //! Convenience overload taking a std::string.
143 void append(const std::string
&arg
) { append(arg
.c_str()); }
145 * Adds an option to the command line, typically a boolean.
147 * \param[in] name Name of the option to append, which
148 * should start with "-".
150 void addOption(const char *name
);
152 * Adds an option-value pair to the command line.
154 * \param[in] name Name of the option to append, which
155 * should start with "-".
156 * \param[in] value Value of the argument to append.
158 void addOption(const char *name
, const char *value
);
159 //! Convenience overload taking a std::string.
160 void addOption(const char *name
, const std::string
&value
);
161 //! Overload taking an int.
162 void addOption(const char *name
, int value
);
163 //! Overload taking a double.
164 void addOption(const char *name
, double value
);
166 * Appends all arguments from \p args to the command line.
168 * If the first argument of \p args does not start with a `-`, it is
169 * skipped, assuming it is a gmx module name and thus useless.
171 void merge(const CommandLine
&args
);
173 //! Returns argc for passing into C-style command-line handling.
175 //! Returns argv for passing into C-style command-line handling.
177 //! Returns argc for passing into C-style command-line handling.
179 //! Returns argv for passing into C-style command-line handling.
180 const char *const *argv() const;
181 //! Returns a single argument.
182 const char *arg(int i
) const;
184 //! Returns the command line formatted as a single string.
185 std::string
toString() const;
187 //! Whether the command line contains the given option.
188 bool contains(const char *name
) const;
193 PrivateImplPointer
<Impl
> impl_
;
196 /*! \libinternal \brief
197 * Helper class for tests that construct command lines that need to reference
200 * This class provides helper methods for:
202 * 1. Adding input files to a CommandLine instance by generating them from a
203 * string provided in the test (setInputFileContents()).
204 * 2. Adding output files to a CommandLine instance (setOutputFile()).
205 * 3. Checking the contents of some of the output files using
206 * TestReferenceData (setOutputFile() and checkOutputFiles()).
207 * 4. Static methods for easily executing command-line modules
208 * (various overloads of runModule()).
210 * All files created during the test are cleaned up at the end of the test.
212 * All methods can throw std::bad_alloc.
214 * \see TestFileManager
216 * \ingroup module_testutils
218 class CommandLineTestHelper
222 * Runs a command-line program that implements ICommandLineModule.
224 * \param[in,out] module Module to run.
225 * The function does not take ownership.
226 * \param[in,out] commandLine Command line parameters to pass.
227 * This is only modified if \p module modifies it.
228 * \returns The return value of the module.
229 * \throws unspecified Any exception thrown by the module.
232 runModuleDirect(ICommandLineModule
*module
, CommandLine
*commandLine
);
234 * Runs a command-line program that implements
235 * ICommandLineOptionsModule.
237 * \param[in,out] module Module to run.
238 * \param[in,out] commandLine Command line parameters to pass.
239 * This is only modified if \p module modifies it.
240 * \returns The return value of the module.
241 * \throws unspecified Any exception thrown by the module.
244 runModuleDirect(std::unique_ptr
<ICommandLineOptionsModule
> module
,
245 CommandLine
*commandLine
);
247 * Runs a command-line program that implements
248 * ICommandLineOptionsModule.
250 * \param[in] factory Factory method for the module to run.
251 * \param[in,out] commandLine Command line parameters to pass.
252 * This is only modified if the module modifies it.
253 * \returns The return value of the module.
254 * \throws unspecified Any exception thrown by the factory or the
258 runModuleFactory(std::function
<std::unique_ptr
<ICommandLineOptionsModule
>()> factory
,
259 CommandLine
*commandLine
);
262 * Initializes an instance.
264 * \param fileManager File manager to use for generating temporary
265 * file names and to track temporary files.
267 explicit CommandLineTestHelper(TestFileManager
*fileManager
);
268 ~CommandLineTestHelper();
271 * Generates and sets an input file.
273 * \param[in,out] args CommandLine to which to add the option.
274 * \param[in] option Option to set.
275 * \param[in] extension Extension for the file to create.
276 * \param[in] contents Text to write to the input file.
278 * Creates a temporary file with contents from \p contents, and adds
279 * \p option to \p args with a value that points to the generated file.
281 void setInputFileContents(CommandLine
*args
, const char *option
,
282 const char *extension
,
283 const std::string
&contents
);
285 * Generates and sets an input file.
287 * \param[in,out] args CommandLine to which to add the option.
288 * \param[in] option Option to set.
289 * \param[in] extension Extension for the file to create.
290 * \param[in] contents Text to write to the input file.
292 * Creates a temporary file with contents from \p contents (each array
293 * entry on its own line), and adds \p option to \p args with a value
294 * that points to the generated file.
296 void setInputFileContents(CommandLine
*args
, const char *option
,
297 const char *extension
,
298 const ConstArrayRef
<const char *> &contents
);
300 * Sets an output file parameter and adds it to the set of tested files.
302 * \param[in,out] args CommandLine to which to add the option.
303 * \param[in] option Option to set.
304 * \param[in] filename Name of the output file.
305 * \param[in] matcher Specifies how the contents of the file are
308 * This method does the following:
309 * - Adds \p option to \p args to point a temporary file name
310 * constructed from \p filename.
311 * - Makes checkOutputFiles() to check the contents of the file
312 * against reference data, using \p matcher.
313 * - Marks the temporary file for removal at test teardown.
315 * \p filename is given to TestTemporaryFileManager to make a unique
316 * filename for the temporary file.
317 * If \p filename starts with a dot, a unique number is prefixed (such
318 * that it is possible to create multiple files with the same extension
319 * by just specifying the extension for every call of setOutputFile()).
321 * If the output file is needed to trigger some computation, or is
322 * unconditionally produced by the code under test, but the contents
323 * are not interesting for the test, use NoContentsMatch as the matcher.
324 * Note that the existence of the output file is still verified.
326 void setOutputFile(CommandLine
*args
, const char *option
,
327 const char *filename
,
328 const ITextBlockMatcherSettings
&matcher
);
329 //! \copydoc setOutputFile(CommandLine *, const char *, const char *, const ITextBlockMatcherSettings &)
330 void setOutputFile(CommandLine
*args
, const char *option
,
331 const char *filename
,
332 const IFileMatcherSettings
&matcher
);
335 * Checks output files added with setOutputFile() against reference
338 * \param checker Reference data root location where the reference
341 * The file contents are tested verbatim, using direct string
342 * comparison. The text can be found verbatim in the reference data
343 * XML files for manual inspection.
345 * Generates non-fatal test failures if some output file contents do
346 * not match the reference data.
348 void checkOutputFiles(TestReferenceChecker checker
) const;
353 PrivateImplPointer
<Impl
> impl_
;
356 /*! \libinternal \brief
357 * Test fixture for tests that call a single command-line program with
358 * input/output files.
360 * This class provides a convenient package for using CommandLineTestHelper in
361 * a test that do not need special customization. It takes care of creating
362 * the other necessary objects (like TestFileManager, TestReferenceData, and
363 * CommandLine) and wrapping the methods from CommandLineTestHelper such that
364 * extra parameters are not needed. Additionally, it provides setInputFile()
365 * as a convenience function for adding a fixed input file, pointing to a file
366 * that resides in the source tree.
368 * \see CommandLineTestHelper
370 * \ingroup module_testutils
372 class CommandLineTestBase
: public ::testing::Test
375 CommandLineTestBase();
376 ~CommandLineTestBase();
379 * Sets an input file.
381 * \param[in] option Option to set.
382 * \param[in] filename Name of the input file.
384 * \see TestFileManager::getInputFilePath()
386 void setInputFile(const char *option
, const char *filename
);
388 * Generates and sets an input file.
390 * \see CommandLineTestHelper::setInputFileContents()
392 void setInputFileContents(const char *option
,
393 const char *extension
,
394 const std::string
&contents
);
396 * Generates and sets an input file.
398 * \see CommandLineTestHelper::setInputFileContents()
400 void setInputFileContents(const char *option
,
401 const char *extension
,
402 const ConstArrayRef
<const char *> &contents
);
404 * Sets an output file parameter and adds it to the set of tested files.
406 * \see CommandLineTestHelper::setOutputFile()
408 void setOutputFile(const char *option
, const char *filename
,
409 const ITextBlockMatcherSettings
&matcher
);
411 * Sets an output file parameter and adds it to the set of tested files.
413 * \see CommandLineTestHelper::setOutputFile()
415 void setOutputFile(const char *option
, const char *filename
,
416 const IFileMatcherSettings
&matcher
);
419 * Returns the internal CommandLine object used to construct the
420 * command line for the test.
422 * Derived test fixtures can use this to add additional options, and
423 * to access the final command line to do the actual call that is being
428 CommandLine
&commandLine();
430 * Returns the internal TestFileManager object used to manage the
433 * Derived test fixtures can use this to manage files in cases the
434 * canned methods are not sufficient.
438 TestFileManager
&fileManager();
440 * Returns the root reference data checker.
442 * Derived test fixtures can use this to check other things than output
445 TestReferenceChecker
rootChecker();
448 * Checks the output of writeHelp() against reference data.
450 void testWriteHelp(ICommandLineModule
*module
);
452 * Checks output files added with setOutputFile() against reference
455 * \see CommandLineTestHelper::checkOutputFiles()
457 void checkOutputFiles();
462 PrivateImplPointer
<Impl
> impl_
;