Handle erroneous command line args better
authorMark Abraham <mark.j.abraham@gmail.com>
Wed, 3 Jan 2018 10:35:38 +0000 (11:35 +0100)
committerMark Abraham <mark.j.abraham@gmail.com>
Wed, 10 Jan 2018 08:47:19 +0000 (09:47 +0100)
Some gmx modules need to be able to accept non-option arguments, and
some should not. Introduced enough functionality to support such
behaviour, while giving useful error messages in cases where the
command line is merely missing hyphens (which can happen e.g. when
people copy-paste from inconveniently built PDF files for tutorials).
Increased test coverage of relevant cases.

Removed some useless command-line argument strings from test cases
that never needed them.

Also tested some behaviours of handling string options, and renamed
some test input strings to reflect the intent.

Fixes #2153

Change-Id: Icec02ea86a57a8b129a621121518036b9f032078

src/gromacs/commandline/cmdlinehelpmodule.cpp
src/gromacs/commandline/cmdlinemodulemanager.cpp
src/gromacs/commandline/cmdlineparser.cpp
src/gromacs/commandline/cmdlineparser.h
src/gromacs/commandline/pargs.cpp
src/gromacs/commandline/tests/cmdlinemodulemanager.cpp
src/gromacs/commandline/tests/cmdlineparser.cpp
src/gromacs/commandline/tests/pargs.cpp
src/gromacs/energyanalysis/tests/legacyenergy.cpp
src/gromacs/gmxana/tests/gmx_traj.cpp
src/gromacs/gmxana/tests/gmx_trjconv.cpp

index d8795362e8dea2b3816c46314d38b487b70b84de..ccbde0f2535bf865df78481cc67c9bd7b840064f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012,2013,2014,2015,2016,2017, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016,2017,2018, 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.
@@ -953,7 +953,7 @@ int CommandLineHelpModule::run(int argc, char *argv[])
     Options           options;
     options.addOption(StringOption("export").store(&exportFormat)
                           .enumValue(exportFormats));
-    CommandLineParser(&options).parse(&argc, argv);
+    CommandLineParser(&options).allowPositionalArguments(true).parse(&argc, argv);
     if (!exportFormat.empty())
     {
         ModificationCheckingFileOutputRedirector redirector(impl_->outputRedirector_);
index 45a06cef72e12ea7262b91396d1791fce2a71711..1a0f3eafcd76e00283815928b025b84d0db48d05 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012,2013,2014,2015,2016,2017, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016,2017,2018, 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.
@@ -366,20 +366,25 @@ CommandLineModuleManager::Impl::processCommonOptions(
     {
         // If not in single-module mode, process options to the wrapper binary.
         // TODO: Ideally, this could be done by CommandLineParser.
-        int argcForWrapper = 1;
-        while (argcForWrapper < *argc && (*argv)[argcForWrapper][0] == '-')
+
+        // Find the module name (if any) in the arg list
+        int indexOfModuleName = 1;
+        while (indexOfModuleName < *argc && (*argv)[indexOfModuleName][0] == '-')
         {
-            ++argcForWrapper;
+            ++indexOfModuleName;
         }
-        if (argcForWrapper > 1)
+        if (indexOfModuleName > 1)
         {
+            // Process options that are provided to the wrapper
+            // binary. These precede the module name, if one exists.
+            int argcForWrapper = indexOfModuleName;
             CommandLineParser(optionsHolder->options())
                 .parse(&argcForWrapper, *argv);
         }
         // If no action requested and there is a module specified, process it.
-        if (argcForWrapper < *argc && !optionsHolder->shouldIgnoreActualModule())
+        if (indexOfModuleName < *argc && !optionsHolder->shouldIgnoreActualModule())
         {
-            const char *moduleName = (*argv)[argcForWrapper];
+            const char *moduleName = (*argv)[indexOfModuleName];
             CommandLineModuleMap::const_iterator moduleIter
                 = findModuleByName(moduleName);
             if (moduleIter == modules_.end())
@@ -389,8 +394,8 @@ CommandLineModuleManager::Impl::processCommonOptions(
                 GMX_THROW(InvalidInputError(message));
             }
             module = moduleIter->second.get();
-            *argc -= argcForWrapper;
-            *argv += argcForWrapper;
+            *argc -= indexOfModuleName;
+            *argv += indexOfModuleName;
             // After this point, argc and argv are the same independent of
             // which path is taken: (*argv)[0] is the module name.
         }
@@ -405,6 +410,7 @@ CommandLineModuleManager::Impl::processCommonOptions(
         // TODO: It could be nicer to only recognize -h/-hidden if module is not
         // null.
         CommandLineParser(optionsHolder->options())
+            .allowPositionalArguments(true)
             .skipUnknown(true).parse(argc, *argv);
     }
     if (!optionsHolder->finishOptions())
index 91b48717e4904a1021597664893c8087737714c8..b3902c00e354fd0b0a825131014f35725fe54682 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2017, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2015,2017,2018, 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.
@@ -84,10 +84,15 @@ class CommandLineParser::Impl
         OptionsAssigner         assigner_;
         //! Whether to allow and skip unknown options.
         bool                    bSkipUnknown_;
+        /*! \brief Whether to allow positional arguments
+         *
+         * These are not options (no leading hyphen), and come before
+         * all options. */
+        bool                    bAllowPositionalArguments_;
 };
 
 CommandLineParser::Impl::Impl(Options *options)
-    : assigner_(options), bSkipUnknown_(false)
+    : assigner_(options), bSkipUnknown_(false), bAllowPositionalArguments_(false)
 {
     assigner_.setAcceptBooleanNoPrefix(true);
 }
@@ -134,15 +139,50 @@ CommandLineParser &CommandLineParser::skipUnknown(bool bEnabled)
     return *this;
 }
 
+CommandLineParser &CommandLineParser::allowPositionalArguments(bool bEnabled)
+{
+    impl_->bAllowPositionalArguments_ = bEnabled;
+    return *this;
+}
+
 void CommandLineParser::parse(int *argc, char *argv[])
 {
     ExceptionInitializer errors("Invalid command-line options");
     std::string          currentContext;
     bool                 bInOption = false;
 
+    // Note that this function gets called multiple times in typical
+    // cases of calling gmx. Command lines like "gmx -hidden mdrun -h"
+    // work because the first call has argv[0] == "gmx" and skips
+    // unknown things, and the second has argv[0] == "mdrun".
+    int i = 1, newi = 1;
+
+    // First, process any permitted leading positional arguments.
+    for (; i < *argc; ++i)
+    {
+        const char *const arg        = argv[i];
+        if (impl_->toOptionName(arg) != nullptr)
+        {
+            // If we find an option, no more positional arguments
+            // can be handled.
+            break;
+        }
+
+        if (!impl_->bAllowPositionalArguments_)
+        {
+            GMX_THROW(InvalidInputError
+                          ("Positional argument '" + std::string(arg) + "' cannot be accepted. "
+                          "Perhaps you forgot to put a hyphen before an option name."));
+        }
+        // argv[i] is not an option, so preserve it in the argument list
+        // by incrementing newi. There's no need to copy argv contents
+        // because they cannot have changed yet.
+        ++newi;
+    }
+
+    // Now handle the option arguments.
     impl_->assigner_.start();
-    int newi = 1;
-    for (int i = 1; i < *argc; ++i)
+    for (; i < *argc; ++i)
     {
         const char *const arg        = argv[i];
         const char *const optionName = impl_->toOptionName(arg);
@@ -202,19 +242,20 @@ void CommandLineParser::parse(int *argc, char *argv[])
                 errors.addCurrentExceptionAsNested();
             }
         }
-        // Remove recognized options if applicable.
+        // Retain unrecognized options if applicable.
         if (!bInOption && impl_->bSkipUnknown_)
         {
             argv[newi] = argv[i];
             ++newi;
         }
     }
-    // Update the argc count if argv was modified.
+    // Update the args if argv was modified.
     if (impl_->bSkipUnknown_)
     {
         *argc      = newi;
         argv[newi] = nullptr;
     }
+
     // Finish the last option.
     if (bInOption)
     {
index 7f90b1a2dc6475415e3871be89b46d0f49568323..3f6f15b9e5e61dd179333d315172b417a2509b52 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012,2013,2014,2016, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2016,2018, 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.
@@ -98,18 +98,44 @@ class CommandLineParser
          */
         CommandLineParser &skipUnknown(bool bEnabled);
 
+        /*! \brief
+         * Makes the parser accept positional arguments
+         *
+         * \param[in] bEnabled  Whether to skip and keep positional arguments.
+         * \returns   *this
+         *
+         * Arguments that are not options (ie. no leading hyphen), and
+         * which come before all options are acceptable if this has
+         * been enabled. If so, these arguments are left in \c argc
+         * and \c argv in parse().
+         *
+         * The default is false: unknown leading arguments result in
+         * exceptions and \c argc and \c argv are not modified.
+         *
+         * Does not throw.
+         */
+        CommandLineParser &allowPositionalArguments(bool bEnabled);
+
         /*! \brief
          * Parses the command line.
          *
          * \throws  std::bad_alloc if out of memory.
          * \throws  InvalidInputError if any errors were detected in the input.
          *
-         * All command-line arguments are parsed, and an aggregate exception
-         * with all the detected errors is thrown in the end.
+         * All command-line arguments are parsed, and an aggregate
+         * exception with all the detected errors (including unknown
+         * options, where applicable) is thrown in the end.
+         *
+         * If skipUnknown() was not called, or last called with a
+         * false value, the input arguments are not modified. If
+         * skipUnknown() was last called with a true value, only
+         * unknown options will be retained in \c argc and \c argv.
+         *
+         * All positional arguments are retained in the argument list,
+         * but such arguments must precede all options.
+         *
+         * \c argv[0] is never modified.
          *
-         * If skipUnknown() is false, the input parameters are not modified.
-         * If skipUnknown() is true, recognized options and their values are
-         * removed from the argument list.  \c argv[0] is never modified.
          */
         void parse(int *argc, char *argv[]);
 
index c0b321d7114a5539808b371b6a9c1523579f22f7..66d049a155416f6baf5da29db06e9679706507ab 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017,2018, 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.
@@ -585,7 +585,9 @@ gmx_bool parse_common_args(int *argc, char *argv[], unsigned long Flags,
         }
 
         /* Now parse all the command-line options */
-        gmx::CommandLineParser(&options).skipUnknown(isFlagSet(PCA_NOEXIT_ON_ARGS))
+        gmx::CommandLineParser(&options)
+            .skipUnknown(isFlagSet(PCA_NOEXIT_ON_ARGS))
+            .allowPositionalArguments(isFlagSet(PCA_NOEXIT_ON_ARGS))
             .parse(argc, argv);
         behaviors.optionsFinishing();
         options.finish();
index 6e619dc68dcc772c38bde66cc91b705070d5bd03..6558a8da8a8e3d02ff0387e08847550a044033c9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012,2013,2014,2015,2017, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017,2018, 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.
@@ -96,6 +96,23 @@ TEST_F(CommandLineModuleManagerTest, RunsModuleHelp)
     ASSERT_EQ(0, rc);
 }
 
+TEST_F(CommandLineModuleManagerTest, RunsModuleHelpAfterQuiet)
+{
+    const char *const cmdline[] = {
+        "test", "-quiet", "help", "module"
+    };
+    CommandLine       args(cmdline);
+    initManager(args, "test");
+    MockModule       &mod1 = addModule("module", "First module");
+    addModule("other", "Second module");
+    using ::testing::_;
+    EXPECT_CALL(mod1, writeHelp(_));
+    mod1.setExpectedDisplayName("test module");
+    int rc = 0;
+    ASSERT_NO_THROW_GMX(rc = manager().run(args.argc(), args.argv()));
+    ASSERT_EQ(0, rc);
+}
+
 TEST_F(CommandLineModuleManagerTest, RunsModuleHelpWithDashH)
 {
     const char *const cmdline[] = {
index a1ad8871a06b5dd1053f44e23034fe67038634c5..643379f9ff23c0f50fb067ee1bb2d01a2f67ca20 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012,2013,2014,2016,2017, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2016,2017,2018, 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.
@@ -73,6 +73,7 @@ class CommandLineParserTest : public ::testing::Test
         std::vector<double>     dvalues_;
         int                     ivalue1p_;
         int                     ivalue12_;
+        std::string             stringValue_;
 };
 
 CommandLineParserTest::CommandLineParserTest()
@@ -81,11 +82,13 @@ CommandLineParserTest::CommandLineParserTest()
     using gmx::BooleanOption;
     using gmx::IntegerOption;
     using gmx::DoubleOption;
+    using gmx::StringOption;
     options_.addOption(BooleanOption("flag").store(&flag_));
     options_.addOption(IntegerOption("mvi").storeVector(&ivalues_).multiValue());
     options_.addOption(DoubleOption("mvd").storeVector(&dvalues_).allowMultiple());
     options_.addOption(IntegerOption("1p").store(&ivalue1p_));
     options_.addOption(IntegerOption("12").store(&ivalue12_));
+    options_.addOption(StringOption("str").store(&stringValue_));
 }
 
 TEST_F(CommandLineParserTest, HandlesSingleValues)
@@ -96,6 +99,8 @@ TEST_F(CommandLineParserTest, HandlesSingleValues)
     CommandLine       args(cmdline);
     ASSERT_NO_THROW_GMX(parser_.parse(&args.argc(), args.argv()));
     ASSERT_NO_THROW_GMX(options_.finish());
+    EXPECT_EQ(7, args.argc());
+    EXPECT_STREQ("test", args.arg(0));
 
     EXPECT_TRUE(flag_);
     ASSERT_EQ(1U, ivalues_.size());
@@ -104,6 +109,43 @@ TEST_F(CommandLineParserTest, HandlesSingleValues)
     EXPECT_DOUBLE_EQ(2.7, dvalues_[0]);
 }
 
+TEST_F(CommandLineParserTest, HandlesBooleanWithoutArgument)
+{
+    const char *const cmdline[] = {
+        "test", "-flag"
+    };
+    CommandLine       args(cmdline);
+    ASSERT_NO_THROW_GMX(parser_.parse(&args.argc(), args.argv()));
+    ASSERT_NO_THROW_GMX(options_.finish());
+    EXPECT_EQ(2, args.argc());
+    EXPECT_STREQ("test", args.arg(0));
+
+    EXPECT_TRUE(flag_);
+}
+
+TEST_F(CommandLineParserTest, HandlesBooleanAsNoWithoutArgument)
+{
+    const char *const cmdline[] = {
+        "test", "-noflag"
+    };
+    CommandLine       args(cmdline);
+    ASSERT_NO_THROW_GMX(parser_.parse(&args.argc(), args.argv()));
+    ASSERT_NO_THROW_GMX(options_.finish());
+    EXPECT_EQ(2, args.argc());
+    EXPECT_STREQ("test", args.arg(0));
+
+    EXPECT_FALSE(flag_);
+}
+
+TEST_F(CommandLineParserTest, ThrowsWithBooleanAsNoWithArgument)
+{
+    const char *const cmdline[] = {
+        "test", "-noflag", "no"
+    };
+    CommandLine       args(cmdline);
+    EXPECT_THROW_GMX(parser_.parse(&args.argc(), args.argv()), gmx::InvalidInputError);
+}
+
 TEST_F(CommandLineParserTest, HandlesNegativeNumbers)
 {
     const char *const cmdline[] = {
@@ -112,6 +154,8 @@ TEST_F(CommandLineParserTest, HandlesNegativeNumbers)
     CommandLine       args(cmdline);
     ASSERT_NO_THROW_GMX(parser_.parse(&args.argc(), args.argv()));
     ASSERT_NO_THROW_GMX(options_.finish());
+    EXPECT_EQ(6, args.argc());
+    EXPECT_STREQ("test", args.arg(0));
 
     ASSERT_EQ(2U, ivalues_.size());
     EXPECT_EQ(1, ivalues_[0]);
@@ -120,6 +164,29 @@ TEST_F(CommandLineParserTest, HandlesNegativeNumbers)
     EXPECT_DOUBLE_EQ(-2.7, dvalues_[0]);
 }
 
+TEST_F(CommandLineParserTest, HandlesString)
+{
+    const char *const cmdline[] = {
+        "test", "-str", "text"
+    };
+    CommandLine       args(cmdline);
+    ASSERT_NO_THROW_GMX(parser_.parse(&args.argc(), args.argv()));
+    ASSERT_NO_THROW_GMX(options_.finish());
+    EXPECT_EQ(3, args.argc());
+    EXPECT_STREQ("test", args.arg(0));
+
+    EXPECT_EQ("text", stringValue_);
+}
+
+TEST_F(CommandLineParserTest, RejectsStringWithMultipleValues)
+{
+    const char *const cmdline[] = {
+        "test", "-str", "text", "excess text"
+    };
+    CommandLine       args(cmdline);
+    EXPECT_THROW_GMX(parser_.parse(&args.argc(), args.argv()), gmx::InvalidInputError);
+}
+
 TEST_F(CommandLineParserTest, HandlesDoubleDashOptionPrefix)
 {
     const char *const cmdline[] = {
@@ -128,6 +195,8 @@ TEST_F(CommandLineParserTest, HandlesDoubleDashOptionPrefix)
     CommandLine       args(cmdline);
     ASSERT_NO_THROW_GMX(parser_.parse(&args.argc(), args.argv()));
     ASSERT_NO_THROW_GMX(options_.finish());
+    EXPECT_EQ(6, args.argc());
+    EXPECT_STREQ("test", args.arg(0));
 
     ASSERT_EQ(2U, ivalues_.size());
     EXPECT_EQ(1, ivalues_[0]);
@@ -144,6 +213,8 @@ TEST_F(CommandLineParserTest, HandlesOptionsStartingWithNumbers)
     CommandLine       args(cmdline);
     ASSERT_NO_THROW_GMX(parser_.parse(&args.argc(), args.argv()));
     ASSERT_NO_THROW_GMX(options_.finish());
+    EXPECT_EQ(5, args.argc());
+    EXPECT_STREQ("test", args.arg(0));
 
     EXPECT_EQ(1, ivalue12_);
     EXPECT_EQ(-12, ivalue1p_);
@@ -152,7 +223,7 @@ TEST_F(CommandLineParserTest, HandlesOptionsStartingWithNumbers)
 TEST_F(CommandLineParserTest, HandlesSkipUnknown)
 {
     const char *const cmdline[] = {
-        "test", "-opt1", "-flag", "-opt2", "value", "-mvi", "2", "-mvd", "2.7", "-opt3"
+        "test", "-unknown1", "-flag", "-unknown2", "value", "-mvi", "2", "-mvd", "2.7", "-unknown3"
     };
     CommandLine       args(cmdline);
     parser_.skipUnknown(true);
@@ -161,10 +232,10 @@ TEST_F(CommandLineParserTest, HandlesSkipUnknown)
 
     ASSERT_EQ(5, args.argc());
     EXPECT_STREQ("test", args.arg(0));
-    EXPECT_STREQ("-opt1", args.arg(1));
-    EXPECT_STREQ("-opt2", args.arg(2));
+    EXPECT_STREQ("-unknown1", args.arg(1));
+    EXPECT_STREQ("-unknown2", args.arg(2));
     EXPECT_STREQ("value", args.arg(3));
-    EXPECT_STREQ("-opt3", args.arg(4));
+    EXPECT_STREQ("-unknown3", args.arg(4));
     EXPECT_TRUE(args.arg(5) == nullptr);
 
     EXPECT_TRUE(flag_);
@@ -174,4 +245,44 @@ TEST_F(CommandLineParserTest, HandlesSkipUnknown)
     EXPECT_DOUBLE_EQ(2.7, dvalues_[0]);
 }
 
+TEST_F(CommandLineParserTest, RejectsPositionalArgumentsByDefault)
+{
+    // Ensures that "gmx trjconv f" gets rejected.
+    const char *const cmdline[] = {
+        "test", "module", "positional"
+    };
+    CommandLine       args(cmdline);
+    EXPECT_THROW_GMX(parser_.parse(&args.argc(), args.argv()), gmx::InvalidInputError);
+}
+
+TEST_F(CommandLineParserTest, CanAllowPositionalArguments)
+{
+    // Ensures that "gmx help trjconv" works
+    const char *const cmdline[] = {
+        "test", "module", "positional", "-flag"
+    };
+    CommandLine       args(cmdline);
+    parser_.allowPositionalArguments(true);
+    ASSERT_NO_THROW_GMX(parser_.parse(&args.argc(), args.argv()));
+    ASSERT_NO_THROW_GMX(options_.finish());
+    ASSERT_EQ(4, args.argc());
+    EXPECT_STREQ("test", args.arg(0));
+    EXPECT_STREQ("module", args.arg(1));
+    EXPECT_STREQ("positional", args.arg(2));
+}
+
+TEST_F(CommandLineParserTest, CannotHavePositionalArgumentsAfterOptions)
+{
+    // Even for the options that can't have arbitrary numbers of
+    // values, there's no way to check whether there's been enough
+    // values provided, so we can't have positional arguments after
+    // any options.
+    const char *const cmdline[] = {
+        "test", "module", "-1p", "2", "positional"
+    };
+    CommandLine       args(cmdline);
+    parser_.allowPositionalArguments(true);
+    EXPECT_THROW_GMX(parser_.parse(&args.argc(), args.argv()), gmx::InvalidInputError);
+}
+
 } // namespace
index 00f97fa3967e944d01c6d507625a811656b8eae5..0eb9a17a3e7ae76f08e18494607d917e7a746119 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2013,2014,2015,2016,2017, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017,2018, 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.
@@ -574,6 +574,8 @@ TEST_F(ParseCommonArgsTest, HandlesNonReadNodeWithDefaultFileName)
     done_filenms(nfile(), fnm);
 }
 
+// This is needed e.g. for tune_pme, which passes unknown arguments on
+// to child mdrun processes that it spawns.
 TEST_F(ParseCommonArgsTest, CanKeepUnknownArgs)
 {
     int               ivalue = 0;
index 7162fc1b179d3a77fc0f44419c5be00d172879de..cf7b5e25b164a8581fc626b81fe9528a2a902a40 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2017, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018, 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.
@@ -69,7 +69,6 @@ class DhdlTest : public CommandLineTestBase
         void runTest()
         {
             auto &cmdline = commandLine();
-            cmdline.append("energy");
 
             setInputFile("-s", "dhdl.tpr");
             setInputFile("-f", "dhdl.edr");
@@ -92,7 +91,6 @@ class OriresTest : public CommandLineTestBase
         void runTest(const char *stringForStdin)
         {
             auto &cmdline = commandLine();
-            cmdline.append("energy");
 
             setInputFile("-s", "orires.tpr");
             setInputFile("-f", "orires.edr");
@@ -124,7 +122,6 @@ class EnergyTest : public CommandLineTestBase
         void runTest(const char *stringForStdin)
         {
             auto &cmdline = commandLine();
-            cmdline.append("energy");
 
             setInputFile("-f", "ener.edr");
             setOutputFile("-o", "energy.xvg", XvgMatch());
index 4163bfa3170672b14a3a42238dc66a205eef9916..1f6c2669133c474cc0083dc70225dc0bea5fcad4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2013,2014,2016,2017, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2016,2017,2018, 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.
@@ -58,7 +58,6 @@ class GmxTraj : public gmx::test::CommandLineTestBase,
         void runTest(const char *fileName)
         {
             auto &cmdline = commandLine();
-            cmdline.append("traj");
             setInputFile("-s", "spc2.gro");
             setInputFile("-f", fileName);
             setOutputFile("-ox", "spc2.xvg", gmx::test::NoTextMatch());
index eccd8ccaa47a6dea7a777e89ad45b187f6c19787..795fcdb3ad0fd393097b7846d105b84a41908eb3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2013,2014,2016,2017, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2016,2017,2018, 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.
@@ -58,7 +58,6 @@ class TrjconvWithIndexGroupSubset : public gmx::test::CommandLineTestBase,
         void runTest(const char *fileName)
         {
             auto &cmdline = commandLine();
-            cmdline.append("trjconv");
 
             setInputFile("-s", "spc2.gro");
             setInputFile("-f", fileName);