Remove some boost::scoped_ptr uses
[gromacs/AngularHB.git] / src / testutils / cmdlinetest.h
blob0cd37a10b3b1ef9bfd1eb4d5bffa93d155acd302
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2012,2013,2014,2015, 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 ConstArrayRef.
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 ITextBlockMatcherSettings;
67 class TestFileManager;
68 class TestReferenceChecker;
70 /*! \libinternal \brief
71 * Helper class for tests that need to construct command lines.
73 * This class helps in writing tests for command-line handling.
74 * The constructor method takes an array of const char pointers, specifying the
75 * command-line arguments, each as one array element. It is also possible to
76 * construct the command line by adding individual arguments with append() and
77 * addOption().
78 * The argc() and argv() methods can then be used to obtain `argc` and `argv`
79 * (non-const char pointers) arrays for passing into methods that expect these.
81 * Note that although the interface allows passing the argc and argv pointers
82 * to methods that modify them (typically as \p f(&argc(), argv())), currently
83 * the CommandLine object is not in a consistent state internally if the
84 * parameters are actually modified. Reading the command line is possible
85 * afterwards, but modification is not.
87 * If you need to construct command lines that refer to files on the file
88 * system, see CommandLineTestHelper and CommandLineTestBase for additional
89 * convenience utilities.
91 * All constructors and methods that modify this class may throw an
92 * std::bad_alloc. Const methods and accessors do not throw.
94 * \inlibraryapi
95 * \ingroup module_testutils
97 class CommandLine
99 public:
100 //! Initializes an empty command-line object.
101 CommandLine();
102 /*! \brief
103 * Initializes a command-line object from an array.
105 * \param[in] cmdline Array of command-line arguments.
107 * \p cmdline should include the binary name as the first element if
108 * that is desired in the output.
110 * This constructor is not explicit to make it possible to create a
111 * CommandLine object directly from a C array.
113 CommandLine(const ConstArrayRef<const char *> &cmdline);
114 //! Creates a deep copy of a command-line object.
115 CommandLine(const CommandLine &other);
116 ~CommandLine();
118 /*! \brief
119 * Initializes a command-line object in-place from an array.
121 * \param[in] cmdline Array of command-line arguments.
123 * \p cmdline should include the binary name as the first element if
124 * that is desired in the output.
126 * This function does the same as the constructor that takes a
127 * ConstArrayRef. Any earlier contents of the object are discarded.
129 * Strong exception safety.
131 void initFromArray(const ConstArrayRef<const char *> &cmdline);
133 /*! \brief
134 * Appends an argument to the command line.
136 * \param[in] arg Argument to append.
138 * Strong exception safety.
140 void append(const char *arg);
141 //! Convenience overload taking a std::string.
142 void append(const std::string &arg) { append(arg.c_str()); }
143 /*! \brief
144 * Adds an option-value pair to the command line.
146 * \param[in] name Name of the option to append, which
147 * should start with "-".
148 * \param[in] value Value of the argument to append.
150 void addOption(const char *name, const char *value);
151 //! Convenience overload taking a std::string.
152 void addOption(const char *name, const std::string &value);
153 //! Overload taking an int.
154 void addOption(const char *name, int value);
155 //! Overload taking a double.
156 void addOption(const char *name, double value);
157 /*! \brief
158 * Appends all arguments from \p args to the command line.
160 * If the first argument of \p args does not start with a `-`, it is
161 * skipped.
163 void merge(const CommandLine &args);
165 //! Returns argc for passing into C-style command-line handling.
166 int &argc();
167 //! Returns argv for passing into C-style command-line handling.
168 char **argv();
169 //! Returns argc for passing into C-style command-line handling.
170 int argc() const;
171 //! Returns argv for passing into C-style command-line handling.
172 const char *const *argv() const;
173 //! Returns a single argument.
174 const char *arg(int i) const;
176 //! Returns the command line formatted as a single string.
177 std::string toString() const;
179 private:
180 class Impl;
182 PrivateImplPointer<Impl> impl_;
185 /*! \libinternal \brief
186 * Helper class for tests that construct command lines that need to reference
187 * existing files.
189 * This class provides helper methods for:
191 * 1. Adding input files to a CommandLine instance by generating them from a
192 * string provided in the test (setInputFileContents()).
193 * 2. Adding output files to a CommandLine instance (setOutputFile()).
194 * 3. Checking the contents of some of the output files using
195 * TestReferenceData (setOutputFile() and checkOutputFiles()).
196 * 4. Static methods for easily executing command-line modules
197 * (various overloads of runModule()).
199 * All files created during the test are cleaned up at the end of the test.
201 * All methods can throw std::bad_alloc.
203 * \see TestFileManager
204 * \inlibraryapi
205 * \ingroup module_testutils
207 class CommandLineTestHelper
209 public:
210 /*! \brief
211 * Runs a command-line program that implements ICommandLineModule.
213 * \param[in,out] module Module to run.
214 * The function does not take ownership.
215 * \param[in,out] commandLine Command line parameters to pass.
216 * This is only modified if \p module modifies it.
217 * \returns The return value of the module.
218 * \throws unspecified Any exception thrown by the module.
220 static int
221 runModuleDirect(ICommandLineModule *module, CommandLine *commandLine);
222 /*! \brief
223 * Runs a command-line program that implements
224 * ICommandLineOptionsModule.
226 * \param[in,out] module Module to run.
227 * \param[in,out] commandLine Command line parameters to pass.
228 * This is only modified if \p module modifies it.
229 * \returns The return value of the module.
230 * \throws unspecified Any exception thrown by the module.
232 static int
233 runModuleDirect(std::unique_ptr<ICommandLineOptionsModule> module,
234 CommandLine *commandLine);
235 /*! \brief
236 * Runs a command-line program that implements
237 * ICommandLineOptionsModule.
239 * \param[in] factory Factory method for the module to run.
240 * \param[in,out] commandLine Command line parameters to pass.
241 * This is only modified if the module modifies it.
242 * \returns The return value of the module.
243 * \throws unspecified Any exception thrown by the factory or the
244 * module.
246 static int
247 runModuleFactory(std::function<std::unique_ptr<ICommandLineOptionsModule>()> factory,
248 CommandLine *commandLine);
250 /*! \brief
251 * Initializes an instance.
253 * \param fileManager File manager to use for generating temporary
254 * file names and to track temporary files.
256 explicit CommandLineTestHelper(TestFileManager *fileManager);
257 ~CommandLineTestHelper();
259 /*! \brief
260 * Generates and sets an input file.
262 * \param[in,out] args CommandLine to which to add the option.
263 * \param[in] option Option to set.
264 * \param[in] extension Extension for the file to create.
265 * \param[in] contents Text to write to the input file.
267 * Creates a temporary file with contents from \p contents, and adds
268 * \p option to \p args with a value that points to the generated file.
270 void setInputFileContents(CommandLine *args, const char *option,
271 const char *extension,
272 const std::string &contents);
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 (each array
282 * entry on its own line), and adds \p option to \p args with a value
283 * that points to the generated file.
285 void setInputFileContents(CommandLine *args, const char *option,
286 const char *extension,
287 const ConstArrayRef<const char *> &contents);
288 /*! \brief
289 * Sets an output file parameter and adds it to the set of tested files.
291 * \param[in,out] args CommandLine to which to add the option.
292 * \param[in] option Option to set.
293 * \param[in] filename Name of the output file.
294 * \param[in] matcher Specifies how the contents of the file are
295 * tested.
297 * This method does the following:
298 * - Adds \p option to \p args to point a temporary file name
299 * constructed from \p filename.
300 * - Makes checkOutputFiles() to check the contents of the file
301 * against reference data, using \p matcher.
302 * - Marks the temporary file for removal at test teardown.
304 * \p filename is given to TestTemporaryFileManager to make a unique
305 * filename for the temporary file.
306 * If \p filename starts with a dot, a unique number is prefixed (such
307 * that it is possible to create multiple files with the same extension
308 * by just specifying the extension for every call of setOutputFile()).
310 * If the output file is needed to trigger some computation, or is
311 * unconditionally produced by the code under test, but the contents
312 * are not interesting for the test, use NoTextMatch as the matcher.
314 void setOutputFile(CommandLine *args, const char *option,
315 const char *filename,
316 const ITextBlockMatcherSettings &matcher);
318 /*! \brief
319 * Checks output files added with setOutputFile() against reference
320 * data.
322 * \param checker Reference data root location where the reference
323 * data is stored.
325 * The file contents are tested verbatim, using direct string
326 * comparison. The text can be found verbatim in the reference data
327 * XML files for manual inspection.
329 * Generates non-fatal test failures if some output file contents do
330 * not match the reference data.
332 void checkOutputFiles(TestReferenceChecker checker) const;
334 private:
335 class Impl;
337 PrivateImplPointer<Impl> impl_;
340 /*! \libinternal \brief
341 * Test fixture for tests that call a single command-line program with
342 * input/output files.
344 * This class provides a convenient package for using CommandLineTestHelper in
345 * a test that do not need special customization. It takes care of creating
346 * the other necessary objects (like TestFileManager, TestReferenceData, and
347 * CommandLine) and wrapping the methods from CommandLineTestHelper such that
348 * extra parameters are not needed. Additionally, it provides setInputFile()
349 * as a convenience function for adding a fixed input file, pointing to a file
350 * that resides in the source tree.
352 * \see CommandLineTestHelper
353 * \inlibraryapi
354 * \ingroup module_testutils
356 class CommandLineTestBase : public ::testing::Test
358 public:
359 CommandLineTestBase();
360 ~CommandLineTestBase();
362 /*! \brief
363 * Sets an input file.
365 * \param[in] option Option to set.
366 * \param[in] filename Name of the input file.
368 * \see TestFileManager::getInputFilePath()
370 void setInputFile(const char *option, const char *filename);
371 /*! \brief
372 * Generates and sets an input file.
374 * \see CommandLineTestHelper::setInputFileContents()
376 void setInputFileContents(const char *option,
377 const char *extension,
378 const std::string &contents);
379 /*! \brief
380 * Generates and sets an input file.
382 * \see CommandLineTestHelper::setInputFileContents()
384 void setInputFileContents(const char *option,
385 const char *extension,
386 const ConstArrayRef<const char *> &contents);
387 /*! \brief
388 * Sets an output file parameter and adds it to the set of tested files.
390 * \see CommandLineTestHelper::setOutputFile()
392 void setOutputFile(const char *option, const char *filename,
393 const ITextBlockMatcherSettings &matcher);
395 /*! \brief
396 * Returns the internal CommandLine object used to construct the
397 * command line for the test.
399 * Derived test fixtures can use this to add additional options, and
400 * to access the final command line to do the actual call that is being
401 * tested.
403 * Does not throw.
405 CommandLine &commandLine();
406 /*! \brief
407 * Returns the internal TestFileManager object used to manage the
408 * files.
410 * Derived test fixtures can use this to manage files in cases the
411 * canned methods are not sufficient.
413 * Does not throw.
415 TestFileManager &fileManager();
416 /*! \brief
417 * Returns the root reference data checker.
419 * Derived test fixtures can use this to check other things than output
420 * file contents.
422 TestReferenceChecker rootChecker();
424 /*! \brief
425 * Checks the output of writeHelp() against reference data.
427 void testWriteHelp(ICommandLineModule *module);
428 /*! \brief
429 * Checks output files added with setOutputFile() against reference
430 * data.
432 * \see CommandLineTestHelper::checkOutputFiles()
434 void checkOutputFiles();
436 private:
437 class Impl;
439 PrivateImplPointer<Impl> impl_;
442 } // namespace test
443 } // namespace gmx
445 #endif