Add helper for generic C++ command-line modules
authorTeemu Murtola <teemu.murtola@gmail.com>
Tue, 9 Dec 2014 16:54:25 +0000 (18:54 +0200)
committerGerrit Code Review <gerrit@gerrit.gromacs.org>
Sun, 28 Dec 2014 20:21:47 +0000 (21:21 +0100)
Add a helper class (gmx::CommandLineOptionsModuleInterface) that makes
it easier to implement proper C++ command-line modules for the wrapper
binary.  The module only needs to implement the interface instead of
gmx::CommandLineModuleInterface, and the helper class then takes care of
command-line parsing and help, based on options initialized by the
module in initOptions().  This removes the need to duplicate
command-line parsing and help code into each module.

Change-Id: I3e213ce530532bd3f60e34fd261fe06797d10326

docs/doxygen/lib/wrapperbinary.md
docs/doxygen/user/usinglibrary.md
src/gromacs/commandline.h
src/gromacs/commandline/CMakeLists.txt
src/gromacs/commandline/cmdlineinit.cpp
src/gromacs/commandline/cmdlineinit.h
src/gromacs/commandline/cmdlinemodule.h
src/gromacs/commandline/cmdlineoptionsmodule.cpp [new file with mode: 0644]
src/gromacs/commandline/cmdlineoptionsmodule.h [new file with mode: 0644]
src/testutils/cmdlinetest.cpp
src/testutils/cmdlinetest.h

index 52bf20e40faefcc7a528a6c1970d094a2453d381..d40623c0bd840e36bb26cf4d453ffab6ad4c27c9 100644 (file)
@@ -25,7 +25,23 @@ tasks:
 The %main() method also catches all exceptions, and if one is caught, prints an
 error message and terminates the program cleanly.
 
-Command line manager
+Command line modules
+====================
+
+All modules within the wrapper binary are implemented as classes that implement
+the gmx::CommandLineModuleInterface interface.  There is generally some helper
+class in between:
+ * General C++ modules typically use gmx::Options for their command-line
+   handling.  Instead of each module implementing parsing and help separately
+   with identical code, they implement gmx::CommandLineOptionsModuleInterface
+   instead.  The framework then provides a bridge class that contains the
+   common code and wraps gmx::CommandLineOptionsModuleInterface into a
+   gmx::CommandLineModuleInterface.
+ * For C++ trajectory analysis modules, there is a general implementation for
+   running the gmx::TrajectoryAnalysisModule subclasses in cmdlinerunner.cpp.
+ * For old C-style %main() functions, see \ref section_wrapperbinary_cmain.
+
+Command line manager {#section_wrapperbinary_manager}
 ====================
 
 The core of the wrapper binary is the gmx::CommandLineModuleManager::run()
@@ -110,7 +126,7 @@ separate CMake script that is run by `make html` to add headers and footers to
 these partial HTML files.
 The final HTML help is produced in `share/html/final/`.
 
-Handling C %main() functions
+Handling C %main() functions {#section_wrapperbinary_cmain}
 ----------------------------
 
 Many pre-5.0 modules are still implemented as a function with a C %main()
index 8afcb715dfd441f245c40a85ba2ae9c54239e985..e8c3bdf3a6d429f3b43e4e7e1774835d025d9406 100644 (file)
@@ -18,11 +18,13 @@ low-level functions.
    the facilities provided by \ref module_commandline.  There are a few
    different alternatives, depending on how much control you want to give
    \Gromacs:
-    - For C++ code, you can implement gmx::CommandLineModuleInterface, and
-      use gmx::runCommandLineModule() to execute it.  This requires using some
-      additional \Gromacs classes (in particular, for implementing
-      gmx::CommandLineModuleInterface::writeHelp(), if you want to support the
-      `-h` option).
+    - For C++ code, you can implement gmx::CommandLineOptionsModuleInterface and
+      use gmx::runCommandLineModule() to execute it.  This interface assumes
+      the use of the gmx::Options mechanism for declaring command-line options
+      (see \ref module_options).
+      For a lower-level interface, gmx::CommandLineModuleInterface can be used,
+      but this requires you to implement `-h` output and command-line parsing
+      yourself (possibly using classes that \Gromacs provides).
     - For C code, you can use gmx_run_cmain() to wrap an existing C main
       method.  The only constraint on the provided main method is that it
       should use parse_common_args() for argument processing.
index eeba8f3ab33773a709346eed965afe1ce33555e5..2b1c2df26f50f6d4814de56aa54d84186b84caa0 100644 (file)
@@ -47,7 +47,8 @@
  *  - Helper classes/functions for implementing the %main() function.
  *    See \ref page_usinglibrary for an overview of those available for user
  *    programs.  These are declared in cmdlineinit.h
- *    (gmx::CommandLineModuleInterface is declared in cmdlinemodule.h).
+ *    (gmx::CommandLineModuleInterface is declared in cmdlinemodule.h and
+ *    gmx::CommandLineOptionsInterface in cmdlineoptionsmodule.h).
  *    \if libapi
  *
  *    Additionally, for internal \Gromacs use, gmx::CommandLineModuleManager
@@ -81,6 +82,7 @@
 #include "gromacs/commandline/cmdlinehelpwriter.h"
 #include "gromacs/commandline/cmdlineinit.h"
 #include "gromacs/commandline/cmdlinemodule.h"
+#include "gromacs/commandline/cmdlineoptionsmodule.h"
 #include "gromacs/commandline/cmdlineparser.h"
 #include "gromacs/commandline/pargs.h"
 
index 08eeb550c770bc39e1e85af9ac17d2633e25208b..f247402c525e2ca36a126782bae31e7cdf609304 100644 (file)
@@ -39,6 +39,7 @@ gmx_install_headers(
     cmdlinehelpwriter.h
     cmdlineinit.h
     cmdlinemodule.h
+    cmdlineoptionsmodule.h
     cmdlineparser.h
     cmdlineprogramcontext.h
     pargs.h
index 003ad846c901535989875ef5900e9af1d69eeafd..a7d23b3755474c70d2e7b63da645fe94b6fc5179 100644 (file)
@@ -50,6 +50,7 @@
 #include <boost/scoped_ptr.hpp>
 
 #include "gromacs/commandline/cmdlinemodulemanager.h"
+#include "gromacs/commandline/cmdlineoptionsmodule.h"
 #include "gromacs/commandline/cmdlineprogramcontext.h"
 #include "gromacs/legacyheaders/network.h"
 #include "gromacs/legacyheaders/types/commrec.h"
@@ -150,7 +151,15 @@ int processExceptionAtExitForCommandLine(const std::exception &ex)
 int runCommandLineModule(int argc, char *argv[],
                          CommandLineModuleInterface *module)
 {
-    return gmx::CommandLineModuleManager::runAsMainSingleModule(argc, argv, module);
+    return CommandLineModuleManager::runAsMainSingleModule(argc, argv, module);
+}
+
+int runCommandLineModule(int argc, char *argv[],
+                         const char *name, const char *description,
+                         CommandLineOptionsModuleInterface *(*factory)())
+{
+    return CommandLineOptionsModuleInterface::runAsMain(
+            argc, argv, name, description, factory);
 }
 
 } // namespace gmx
index 0f95039cbcfb45f12afa13be5fc9f80391efa498..e1fb961a358216638e5efb43201a4f160d9d80d9 100644 (file)
@@ -53,6 +53,7 @@ namespace gmx
 {
 
 class CommandLineModuleInterface;
+class CommandLineOptionsModuleInterface;
 
 /*! \brief
  * Initializes the \Gromacs library for command-line use.
@@ -137,6 +138,44 @@ int processExceptionAtExitForCommandLine(const std::exception &ex);
  */
 int runCommandLineModule(int argc, char *argv[],
                          CommandLineModuleInterface *module);
+/*! \brief
+ * Implements a main() method that runs a single module.
+ *
+ * \param     argc        \c argc passed to main().
+ * \param     argv        \c argv passed to main().
+ * \param[in] name        Name for the module.
+ * \param[in] description Short description for the module.
+ * \param     factory Factory method that creates the module to run.
+ *
+ * This method allows for uniform behavior for binaries that only
+ * contain a single module without duplicating any of the
+ * implementation from CommandLineModuleManager (startup headers,
+ * common options etc.).
+ *
+ * Usage:
+ * \code
+   class CustomCommandLineOptionsModule : public CommandLineOptionsModuleInterface
+   {
+       // <...>
+   };
+
+   static CommandLineOptionsModuleInterface *create()
+   {
+       return new CustomCommandLineOptionsModule();
+   }
+
+   int main(int argc, char *argv[])
+   {
+       return gmx::runCommandLineModule(
+               argc, argv, "mymodule", "short description", &create);
+   }
+   \endcode
+ *
+ * Does not throw.  All exceptions are caught and handled internally.
+ */
+int runCommandLineModule(int argc, char *argv[],
+                         const char *name, const char *description,
+                         CommandLineOptionsModuleInterface *(*factory)());
 
 } // namespace gmx
 
index d8fb3b5e4f84ccf89187bf57ab1dd41023bb15ee..f4252f1a1aa9e6c8b4266d48c737e2acdab62e52 100644 (file)
@@ -85,6 +85,7 @@ class CommandLineModuleSettings
  * Module that can be run from command line using CommandLineModuleManager.
  *
  * \see CommandLineModuleManager
+ * \see CommandLineOptionsModule
  *
  * \inpublicapi
  * \ingroup module_commandline
@@ -104,6 +105,8 @@ class CommandLineModuleInterface
          *
          * This will be called before run(), and can be used to adjust
          * initialization that the runner does.
+         *
+         * This method is currently not called when writing the help.
          */
         virtual void init(CommandLineModuleSettings *settings) = 0;
         /*! \brief
diff --git a/src/gromacs/commandline/cmdlineoptionsmodule.cpp b/src/gromacs/commandline/cmdlineoptionsmodule.cpp
new file mode 100644 (file)
index 0000000..7ea4c25
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2014, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ * \brief
+ * Implements supporting routines for gmx::CommandLineOptionsModuleInterface.
+ *
+ * \author Teemu Murtola <teemu.murtola@gmail.com>
+ * \ingroup module_commandline
+ */
+#include "gmxpre.h"
+
+#include "cmdlineoptionsmodule.h"
+
+#include <boost/scoped_ptr.hpp>
+
+#include "gromacs/commandline/cmdlinehelpwriter.h"
+#include "gromacs/commandline/cmdlinemodulemanager.h"
+#include "gromacs/commandline/cmdlineparser.h"
+#include "gromacs/options/filenameoptionmanager.h"
+#include "gromacs/options/options.h"
+#include "gromacs/utility/gmxassert.h"
+
+namespace gmx
+{
+
+namespace
+{
+
+/********************************************************************
+ * CommandLineOptionsModule
+ */
+
+class CommandLineOptionsModule : public CommandLineModuleInterface
+{
+    public:
+        //! Shorthand for the factory function pointer type.
+        typedef CommandLineOptionsModuleInterface::FactoryMethod FactoryMethod;
+
+        CommandLineOptionsModule(const char *name, const char *description,
+                                 FactoryMethod factory)
+            : name_(name), description_(description), factory_(factory)
+        {
+        }
+        virtual const char *name() const { return name_; }
+        virtual const char *shortDescription() const { return description_; }
+
+        virtual void init(CommandLineModuleSettings *settings);
+        virtual int run(int argc, char *argv[]);
+        virtual void writeHelp(const CommandLineHelpContext &context) const;
+
+    private:
+        void parseOptions(int argc, char *argv[]);
+
+        const char    *name_;
+        const char    *description_;
+        FactoryMethod  factory_;
+        boost::scoped_ptr<CommandLineOptionsModuleInterface> module_;
+};
+
+void CommandLineOptionsModule::init(CommandLineModuleSettings *settings)
+{
+    module_.reset(factory_());
+    module_->init(settings);
+}
+
+int CommandLineOptionsModule::run(int argc, char *argv[])
+{
+    GMX_RELEASE_ASSERT(module_, "init() has not been called");
+    parseOptions(argc, argv);
+    return module_->run();
+}
+
+void CommandLineOptionsModule::writeHelp(const CommandLineHelpContext &context) const
+{
+    boost::scoped_ptr<CommandLineOptionsModuleInterface> module(factory_());
+    Options options(name(), shortDescription());
+    module->initOptions(&options);
+    CommandLineHelpWriter(options)
+        .setShowDescriptions(true)
+        .writeHelp(context);
+}
+
+void CommandLineOptionsModule::parseOptions(int argc, char *argv[])
+{
+    FileNameOptionManager fileoptManager;
+    Options               options(name_, description_);
+
+    options.addManager(&fileoptManager);
+
+    module_->initOptions(&options);
+    {
+        CommandLineParser parser(&options);
+        parser.parse(&argc, argv);
+        options.finish();
+    }
+    module_->optionsFinished(&options);
+}
+
+}   // namespace
+
+/********************************************************************
+ * CommandLineOptionsModuleInterface
+ */
+
+CommandLineOptionsModuleInterface::~CommandLineOptionsModuleInterface()
+{
+}
+
+// static
+CommandLineModuleInterface *
+CommandLineOptionsModuleInterface::createModule(
+        const char *name, const char *description, FactoryMethod factory)
+{
+    return new CommandLineOptionsModule(name, description, factory);
+}
+
+// static
+int CommandLineOptionsModuleInterface::runAsMain(
+        int argc, char *argv[], const char *name, const char *description,
+        FactoryMethod factory)
+{
+    CommandLineOptionsModule module(name, description, factory);
+    return CommandLineModuleManager::runAsMainSingleModule(argc, argv, &module);
+}
+
+// static
+void CommandLineOptionsModuleInterface::registerModule(
+        CommandLineModuleManager *manager, const char *name,
+        const char *description, FactoryMethod factory)
+{
+    CommandLineModulePointer module(createModule(name, description, factory));
+    manager->addModule(move(module));
+}
+
+} // namespace gmx
diff --git a/src/gromacs/commandline/cmdlineoptionsmodule.h b/src/gromacs/commandline/cmdlineoptionsmodule.h
new file mode 100644 (file)
index 0000000..5958806
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2014, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \file
+ * \brief
+ * Declares gmx::CommandLineOptionsModuleInterface and supporting routines.
+ *
+ * \author Teemu Murtola <teemu.murtola@gmail.com>
+ * \inpublicapi
+ * \ingroup module_commandline
+ */
+#ifndef GMX_COMMANDLINE_CMDLINEOPTIONSMODULE_H
+#define GMX_COMMANDLINE_CMDLINEOPTIONSMODULE_H
+
+#include "gromacs/commandline/cmdlinemodule.h"
+
+namespace gmx
+{
+
+class CommandLineModuleInterface;
+class CommandLineModuleManager;
+class Options;
+
+/*! \brief
+ * Module that can be run from a command line and uses gmx::Options for
+ * argument processing.
+ *
+ * This class provides a higher-level interface on top of
+ * gmx::CommandLineModuleInterface for cases where gmx::Options will be used
+ * for declaring the command-line arguments.  The module only needs to declare
+ * the options it uses, and the framework takes care of command-line parsing
+ * and help output.  The module typically consists of the following parts:
+ *  - init() allows for some interaction between the module and the framework
+ *    when running the module; see CommandLineModuleInterface::init().  If no
+ *    such customization is necessary, an empty implementation is sufficient.
+ *  - initOptions() is called both for running the module and for printing help
+ *    for the module, and it should add the options that the module
+ *    understands.  Values provided for the options are typically stored in
+ *    member variables.
+ *  - optionsFinished() can be implemented in case additional processing is
+ *    needed (e.g., checking whether an option was set by the user).
+ *  - run() is called when running the module, after command-line options have
+ *    been parsed and their values stored in the corresponding member
+ *    variables.
+ *
+ * registerModule(), runAsMain(), or createModule() can be used to use modules
+ * of this type in all contexts where a gmx::CommandLineModuleInterface is
+ * expected.  These methods create a gmx::CommandLineModuleInterface
+ * implementation that contains the common code needed to parse command-line
+ * options and write help, based on the information provided from the methods
+ * in this class.
+ *
+ * \inpublicapi
+ * \ingroup module_commandline
+ */
+class CommandLineOptionsModuleInterface
+{
+    public:
+        /*! \brief
+         * Function pointer to a factory method that returns an interface of
+         * this type.
+         *
+         * \returns Module to run (should be allocated with `new`).
+         * \throws  std::bad_alloc if out of memory.
+         *
+         * The caller takes responsibility to `delete` the returned pointer.
+         */
+        typedef CommandLineOptionsModuleInterface *(*FactoryMethod)();
+
+        /*! \brief
+         * Creates a CommandLineModuleInterface to run the specified module.
+         *
+         * \param[in] name        Name for the module.
+         * \param[in] description Short description for the module.
+         * \param[in] factory     Factory that returns the module to run.
+         * \returns CommandLineModuleInterface object that runs the module
+         *     returned by \p factory.  Caller must `delete` the object.
+         * \throws  std::bad_alloc if out of memory.
+         *
+         * This is mainly used by unit tests that want to bypass
+         * CommandLineModuleManager.
+         */
+        static CommandLineModuleInterface *
+        createModule(const char *name, const char *description,
+                     FactoryMethod factory);
+        /*! \brief
+         * Implements a main() method that runs a single module.
+         *
+         * \param     argc    \c argc passed to main().
+         * \param     argv    \c argv passed to main().
+         * \param[in] name        Name for the module.
+         * \param[in] description Short description for the module.
+         * \param[in] factory     Factory that returns the module to run.
+         *
+         * This method allows for uniform behavior for binaries that only
+         * contain a single module without duplicating any of the
+         * implementation from CommandLineModuleManager (startup headers,
+         * common options etc.).
+         *
+         * \see runCommandLineModule()
+         */
+        static int
+        runAsMain(int argc, char *argv[], const char *name,
+                  const char *description, FactoryMethod factory);
+        /*! \brief
+         * Registers a module of a certain type to this manager.
+         *
+         * \param     manager     Manager to register to.
+         * \param[in] name        Name for the module.
+         * \param[in] description Short description for the module.
+         * \param[in] factory     Factory that returns the module to register.
+         * \throws  std::bad_alloc if out of memory.
+         *
+         * This method internally creates a CommandLineModuleInterface module
+         * with the given \p name and \p description, and adds that to
+         * \p manager.  When run or asked to write the help, the module calls
+         * \p factory to get the actual module, and forwards the necessary
+         * calls.
+         */
+        static void
+        registerModule(CommandLineModuleManager *manager,
+                       const char *name, const char *description,
+                       FactoryMethod factory);
+
+        virtual ~CommandLineOptionsModuleInterface();
+
+        //! \copydoc gmx::CommandLineModuleInterface::init()
+        virtual void init(CommandLineModuleSettings *settings) = 0;
+        /*! \brief
+         * Initializes command-line arguments understood by the module.
+         *
+         * \param[in,out] options  Options object to add the options to.
+         *
+         * When running the module, this method is called after init().
+         * When printing help, there is no call to init(), and this is the only
+         * method called.
+         * In both cases, the implementation should add options understood by
+         * the module to \p options.  Output values from options should be
+         * stored in member variables.
+         */
+        virtual void initOptions(Options *options)             = 0;
+        /*! \brief
+         * Called after all option values have been set.
+         *
+         * \param[in,out] options  Options object in which options are stored.
+         *
+         * When running the module, this method is called after all
+         * command-line arguments have been parsed, but while the Options
+         * object still exists.
+         *
+         * If the module needs to call, e.g., Options::isSet(), this is the
+         * place to do that.
+         */
+        virtual void optionsFinished(Options *options)         = 0;
+
+        /*! \brief
+         * Runs the module.
+         *
+         * \throws   unspecified  May throw exceptions to indicate errors.
+         * \returns  Exit code for the program.
+         * \retval   0 on successful termination.
+         *
+         * This method is called after optionsFinished() when running the
+         * module, and should do all the processing for the module.
+         */
+        virtual int run() = 0;
+};
+
+} // namespace gmx
+
+#endif
index 026c9c4516fd2e859ca0d6fa6f36dbba5037074b..3d5a956fca8c09fd79a121b81dddc618572cb3f8 100644 (file)
@@ -50,6 +50,9 @@
 #include <sstream>
 #include <vector>
 
+#include <boost/scoped_ptr.hpp>
+
+#include "gromacs/commandline/cmdlineoptionsmodule.h"
 #include "gromacs/commandline/cmdlineprogramcontext.h"
 #include "gromacs/utility/arrayref.h"
 #include "gromacs/utility/file.h"
@@ -258,6 +261,26 @@ class CommandLineTestHelper::Impl
  * CommandLineTestHelper
  */
 
+// static
+int CommandLineTestHelper::runModule(
+        CommandLineModuleInterface *module, CommandLine *commandLine)
+{
+    CommandLineModuleSettings settings;
+    module->init(&settings);
+    return module->run(commandLine->argc(), commandLine->argv());
+}
+
+// static
+int CommandLineTestHelper::runModule(
+        CommandLineOptionsModuleInterface::FactoryMethod  factory,
+        CommandLine                                      *commandLine)
+{
+    // The name and description are not used in the tests, so they can be NULL.
+    boost::scoped_ptr<CommandLineModuleInterface> module(
+            CommandLineOptionsModuleInterface::createModule(NULL, NULL, factory));
+    return runModule(module.get(), commandLine);
+}
+
 CommandLineTestHelper::CommandLineTestHelper(TestFileManager *fileManager)
     : impl_(new Impl(fileManager))
 {
index 6de20d85f97f4ddae3304b76c88fa90251b046a4..519911f16e75b342f3a0444a0bf1335c3c8777ec 100644 (file)
 
 namespace gmx
 {
+
+class CommandLineModuleInterface;
+class CommandLineOptionsModuleInterface;
+
 namespace test
 {
 
@@ -187,6 +191,8 @@ class CommandLine
  *      setOutputFileNoTest()).
  *   3. Checking the contents of some of the output files using
  *      TestReferenceData (setOutputFile() and checkOutputFiles()).
+ *   4. Static methods for easily executing command-line modules
+ *      (various overloads of runModule()).
  *
  * All files created during the test are cleaned up at the end of the test.
  *
@@ -199,6 +205,33 @@ class CommandLine
 class CommandLineTestHelper
 {
     public:
+        /*! \brief
+         * Runs a command-line program that implements CommandLineModuleInterface.
+         *
+         * \param[in,out] module       Module to run.
+         *     The function does not take ownership.
+         * \param[in,out] commandLine  Command line parameters to pass.
+         *     This is only modified if \p module modifies it.
+         * \returns The return value of the module.
+         * \throws  unspecified  Any exception thrown by the module.
+         */
+        static int
+        runModule(CommandLineModuleInterface *module, CommandLine *commandLine);
+        /*! \brief
+         * Runs a command-line program that implements
+         * CommandLineOptionsModuleInterface.
+         *
+         * \param[in] factory          Factory method for the module to run.
+         * \param[in,out] commandLine  Command line parameters to pass.
+         *     This is only modified if the module modifies it.
+         * \returns The return value of the module.
+         * \throws  unspecified  Any exception thrown by the factory or the
+         *     module.
+         */
+        static int
+        runModule(CommandLineOptionsModuleInterface *(*factory)(),
+                  CommandLine                      *commandLine);
+
         /*! \brief
          * Initializes an instance.
          *