Helper class for command-line utility tests.
authorTeemu Murtola <teemu.murtola@gmail.com>
Mon, 7 May 2012 06:55:12 +0000 (09:55 +0300)
committerTeemu Murtola <teemu.murtola@gmail.com>
Mon, 7 May 2012 07:37:59 +0000 (10:37 +0300)
Split functionality for converting const char * arrays into
(argc, argv) from CommandLineParserTest into a separate utility class.
Allows using the functionality in other unit tests as well.

Change-Id: I2034c497799811b1d8ed7907e8ed9395bbb0363d

src/gromacs/commandline/tests/CMakeLists.txt
src/gromacs/commandline/tests/cmdlineparser.cpp
src/gromacs/commandline/tests/cmdlinetest.cpp [new file with mode: 0644]
src/gromacs/commandline/tests/cmdlinetest.h [new file with mode: 0644]

index db11bf5fd281baf2d6a659f7496fbcbe4e0e1d12..007275c3ece97a1ea19a655234892dd1fe2dd2ae 100644 (file)
@@ -1,4 +1,6 @@
 if (TESTUTILS_HAVE_REFDATA)
     add_gtest_test(CommandLineUnitTests commandline-test
-                   cmdlinehelpwriter.cpp cmdlineparser.cpp)
+                   cmdlinehelpwriter.cpp
+                   cmdlineparser.cpp
+                   cmdlinetest.cpp)
 endif ()
index f33c46a129481b8bd288ab490c5efb56354ea2f8..6aa1228b7f8f89fc5474dbb9aabce4ce0aa46780 100644 (file)
@@ -38,8 +38,6 @@
  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
  * \ingroup module_commandline
  */
-#include <cstdlib>
-#include <cstring>
 #include <vector>
 
 #include <gtest/gtest.h>
@@ -48,6 +46,8 @@
 #include "gromacs/options/basicoptions.h"
 #include "gromacs/options/options.h"
 
+#include "cmdlinetest.h"
+
 namespace
 {
 
@@ -55,23 +55,17 @@ class CommandLineParserTest : public ::testing::Test
 {
     public:
         CommandLineParserTest();
-        ~CommandLineParserTest();
-
-        void createArguments(const char *cmdline[]);
 
         gmx::Options            _options;
         gmx::CommandLineParser  _parser;
         bool                    _flag;
         std::vector<int>        _ivalues;
         std::vector<double>     _dvalues;
-        int                     _argc;
-        char                  **_argv;
 };
 
 CommandLineParserTest::CommandLineParserTest()
     : _options(NULL, NULL), _parser(&_options),
-      _flag(false),
-      _argc(0), _argv(NULL)
+      _flag(false)
 {
     using gmx::BooleanOption;
     using gmx::IntegerOption;
@@ -81,37 +75,13 @@ CommandLineParserTest::CommandLineParserTest()
     _options.addOption(DoubleOption("mvd").storeVector(&_dvalues).allowMultiple());
 }
 
-CommandLineParserTest::~CommandLineParserTest()
-{
-    if (_argv != NULL)
-    {
-        for (int i = 0; i < _argc; ++i)
-        {
-            free(_argv[i]);
-        }
-    }
-    delete [] _argv;
-}
-
-void CommandLineParserTest::createArguments(const char *cmdline[])
-{
-    _argc = 0;
-    while (cmdline[_argc] != NULL) ++_argc;
-    ++_argc;
-
-    _argv = new char *[_argc];
-    _argv[0] = strdup("test");
-    for (int i = 1; i < _argc; ++i)
-    {
-        _argv[i] = strdup(cmdline[i - 1]);
-    }
-}
-
 TEST_F(CommandLineParserTest, HandlesSingleValues)
 {
-    const char *cmdline[] = {"-flag", "yes", "-mvi", "2", "-mvd", "2.7", NULL};
-    createArguments(cmdline);
-    ASSERT_NO_THROW(_parser.parse(&_argc, _argv));
+    const char *const cmdline[] = {
+        "test", "-flag", "yes", "-mvi", "2", "-mvd", "2.7"
+    };
+    gmx::test::CommandLine args(cmdline);
+    ASSERT_NO_THROW(_parser.parse(&args.argc(), args.argv()));
     ASSERT_NO_THROW(_options.finish());
 
     EXPECT_TRUE(_flag);
@@ -123,9 +93,11 @@ TEST_F(CommandLineParserTest, HandlesSingleValues)
 
 TEST_F(CommandLineParserTest, HandlesNegativeNumbers)
 {
-    const char *cmdline[] = {"-mvi", "1", "-2", "-mvd", "-2.7", NULL};
-    createArguments(cmdline);
-    ASSERT_NO_THROW(_parser.parse(&_argc, _argv));
+    const char *const cmdline[] = {
+        "test", "-mvi", "1", "-2", "-mvd", "-2.7"
+    };
+    gmx::test::CommandLine args(cmdline);
+    ASSERT_NO_THROW(_parser.parse(&args.argc(), args.argv()));
     ASSERT_NO_THROW(_options.finish());
 
     ASSERT_EQ(2U, _ivalues.size());
diff --git a/src/gromacs/commandline/tests/cmdlinetest.cpp b/src/gromacs/commandline/tests/cmdlinetest.cpp
new file mode 100644 (file)
index 0000000..eea26e8
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, 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 www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::test::CommandLineTestBase.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_commandline
+ */
+#include "cmdlinetest.h"
+
+#include <cstdlib>
+#include <cstring>
+
+namespace gmx
+{
+namespace test
+{
+
+CommandLine::~CommandLine()
+{
+    for (int i = 0; i < argc_; ++i)
+    {
+        free(argv_[i]);
+    }
+    delete [] argv_;
+}
+
+void CommandLine::initCommandLine(const char *const cmdline[], size_t count)
+{
+    argv_ = new char *[count];
+    for (size_t i = 0; i < count; ++i)
+    {
+        argv_[i] = strdup(cmdline[i]);
+        // TODO: Check for failure;
+    }
+    argc_ = static_cast<int>(count);
+}
+
+} // namespace test
+} // namespace gmx
diff --git a/src/gromacs/commandline/tests/cmdlinetest.h b/src/gromacs/commandline/tests/cmdlinetest.h
new file mode 100644 (file)
index 0000000..42aff01
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, 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 www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares gmx::test::CommandLine.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_commandline
+ */
+#ifndef GMX_COMMANDLINE_TESTS_CMDLINETEST_H
+#define GMX_COMMANDLINE_TESTS_CMDLINETEST_H
+
+#include <cstddef>
+
+namespace gmx
+{
+namespace test
+{
+
+/*! \internal \brief
+ * Helper class for tests that check command-line handling.
+ *
+ * This class helps in writing tests for command-line handling.
+ * The constructor takes an array of const char pointers, specifying the
+ * command-line arguments, each as one array element.
+ * The argc() and argv() methods can then be used to obtain the argc and argv
+ * (non-const char pointers) arrays for passing into methods that expect these.
+ *
+ * Note that although the interface allows passing the argc and argv pointers
+ * to methods that modify them (typically as \p f(&argc(), argv())), currently
+ * memory leaks occur if the parameters are actually modified.
+ * Currently, the C++ methods with this signature do not modify their
+ * parameters, so this is not yet a problem.
+ *
+ * \ingroup module_commandline
+ */
+class CommandLine
+{
+    public:
+        /*! \brief
+         * Initializes a command-line object.
+         *
+         * \param[in] cmdline  Array of command-line arguments.
+         * \tparam    count Deduced number of elements in \p cmdline.
+         * \throws    std::bad_alloc if out of memory.
+         *
+         * \p cmdline should include the binary name as the first element if
+         * that is desired in the output.
+         */
+        template <size_t count>
+        explicit CommandLine(const char *const (&cmdline)[count])
+        {
+            initCommandLine(cmdline, count);
+        }
+        ~CommandLine();
+
+        //! Returns argc for passing into C-style command-line handling.
+        int &argc() { return argc_; }
+        //! Returns argv for passing into C-style command-line handling.
+        char **argv() { return argv_; }
+
+    private:
+        //! Internal helper method used to implement the constructor.
+        void initCommandLine(const char *const cmdline[], size_t count);
+
+        int                     argc_;
+        char                  **argv_;
+};
+
+} // namespace test
+} // namespace gmx
+
+#endif