CommandLine: add Usage message, simplify bool args
authorPeter D. Barnes, Jr. <barnes26@llnl.gov>
Fri, 14 Jun 2013 13:54:39 -0700
changeset 9829 0828b3ad8057
parent 9828 ed3f8c08289e
child 9830 f9f0769a40a1
CommandLine: add Usage message, simplify bool args Accept obvious bool arguments: --arg --arg=t --arg=true Get program name from argv[0] Example program Doxygenate
src/core/examples/command-line-example.cc
src/core/examples/wscript
src/core/model/command-line.cc
src/core/model/command-line.h
src/core/test/command-line-test-suite.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/examples/command-line-example.cc	Fri Jun 14 13:54:39 2013 -0700
@@ -0,0 +1,48 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include <string>
+
+#include "ns3/core-module.h"
+
+using namespace ns3;
+
+int main (int argc, char *argv[])
+{
+
+  int         val1 = 1;
+  bool        val2 = false;
+  std::string val3 = "";
+  
+  CommandLine cmd;
+  cmd.Usage ("CommandLine example program.\n"
+             "\n"
+             "This little program demonstrates how to use CommandLine.");
+  cmd.AddValue ("val1", "an int argument",          val1);
+  cmd.AddValue ("val2", "a bool argument",          val2);
+  cmd.AddValue ("val3", "a string argument",        val3);
+  cmd.Parse (argc, argv);
+
+  std::cout << "val1:\t" << val1 << std::endl;
+  std::cout << "val2:\t" << val2 << std::endl;
+  std::cout << "val3:\t\"" << val3 << "\"" << std::endl;
+
+  return 0;
+}
--- a/src/core/examples/wscript	Fri Jun 14 08:08:29 2013 -0700
+++ b/src/core/examples/wscript	Fri Jun 14 13:54:39 2013 -0700
@@ -29,6 +29,10 @@
                                  ['core'])
     obj.source = 'sample-random-variable-stream.cc'
 
+    obj = bld.create_ns3_program('command-line-example',
+                                 ['core'])
+    obj.source = 'command-line-example.cc'
+
     if bld.env['ENABLE_THREADING'] and bld.env["ENABLE_REAL_TIME"]:
         obj = bld.create_ns3_program('main-test-sync', ['network'])
         obj.source = 'main-test-sync.cc'
--- a/src/core/model/command-line.cc	Fri Jun 14 08:08:29 2013 -0700
+++ b/src/core/model/command-line.cc	Fri Jun 14 13:54:39 2013 -0700
@@ -18,12 +18,15 @@
  * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 
-#include <cstdlib> // for exit
+#include <algorithm>  // for transform
+#include <cctype>     // for tolower
+#include <cstdlib>    // for exit
 
 #include "command-line.h"
 #include "log.h"
 #include "config.h"
 #include "global-value.h"
+#include "system-path.h"
 #include "type-id.h"
 #include "string.h"
 
@@ -62,6 +65,8 @@
     {
       m_items.push_back (*i);
     }
+  m_usage = cmd.m_usage;
+  m_name  = cmd.m_name;
 }
 void
 CommandLine::Clear (void)
@@ -73,6 +78,20 @@
       delete *i;
     }
   m_items.clear ();
+  m_usage = "";
+  m_name  = "";
+}
+
+void
+CommandLine::Usage (const std::string usage)
+{
+  m_usage = usage;
+}
+
+std::string
+CommandLine::GetName () const
+{
+  return m_name;
 }
 
 CommandLine::Item::~Item ()
@@ -81,10 +100,12 @@
 }
 
 void
-CommandLine::Parse (int iargc, char *argv[]) const
+CommandLine::Parse (int iargc, char *argv[])
 {
   NS_LOG_FUNCTION (this << iargc << argv);
 
+  m_name = SystemPath::Split (argv[0]).back ();
+  
   int argc = iargc;
   for (argc--, argv++; argc > 0; argc--, argv++)
     {
@@ -129,20 +150,34 @@
 {
   NS_LOG_FUNCTION (this);
 
-  std::cout << "--PrintHelp: Print this help message." << std::endl;
-  std::cout << "--PrintGroups: Print the list of groups." << std::endl;
-  std::cout << "--PrintTypeIds: Print all TypeIds." << std::endl;
-  std::cout << "--PrintGroup=[group]: Print all TypeIds of group." << std::endl;
-  std::cout << "--PrintAttributes=[typeid]: Print all attributes of typeid." << std::endl;
-  std::cout << "--PrintGlobals: Print the list of globals." << std::endl;
+  std::cout << m_name << " [Program Arguments] [General Arguments]" << std::endl;
+  
+  if (m_usage.length ())
+    {
+      std::cout << std::endl;
+      std::cout << m_usage << std::endl;
+    }
+  
   if (!m_items.empty ())
     {
-      std::cout << "User Arguments:" << std::endl;
+      std::cout << std::endl;
+      std::cout << "Program Arguments:" << std::endl;
       for (Items::const_iterator i = m_items.begin (); i != m_items.end (); ++i)
         {
-          std::cout << "    --" << (*i)->m_name << ": " << (*i)->m_help << std::endl;
+          std::cout << "    --" << (*i)->m_name << ":\t" << (*i)->m_help << std::endl;
         }
     }
+
+  std::cout << std::endl;
+  std::cout
+    << "General Arguments:\n"
+    << "    --PrintHelp:                 Print this help message.\n"
+    << "    --PrintGroups:               Print the list of groups.\n"
+    << "    --PrintTypeIds:              Print all TypeIds.\n"
+    << "    --PrintGroup=[group]:        Print all TypeIds of group.\n"
+    << "    --PrintAttributes=[typeid]:  Print all attributes of typeid.\n"
+    << "    --PrintGlobals:              Print the list of globals.\n"
+    << std::endl;
 }
 
 void
@@ -191,7 +226,7 @@
       TypeId tid = TypeId::GetRegistered (i);
       if (tid.GetGroupName () == group)
         {
-          std::cout << "    --PrintAttributes=" <<tid.GetName ()<<std::endl;
+          std::cout << "    --PrintGroup=" <<tid.GetName ()<<std::endl;
         }
     }
 }
@@ -204,7 +239,7 @@
   for (uint32_t i = 0; i < TypeId::GetRegisteredN (); ++i)
     {
       TypeId tid = TypeId::GetRegistered (i);
-      std::cout << "    --PrintAttributes=" <<tid.GetName ()<<std::endl;
+      std::cout << "    --PrintTypeIds=" <<tid.GetName ()<<std::endl;
     }
 }
 
@@ -238,7 +273,7 @@
     }
   for (std::list<std::string>::const_iterator k = groups.begin (); k != groups.end (); ++k)
     {
-      std::cout << "    --PrintGroup="<<*k<<std::endl;
+      std::cout << "    --PrintGroups="<<*k<<std::endl;
     }
 }
 
@@ -248,7 +283,7 @@
   NS_LOG_FUNCTION (this << name << value);
 
   NS_LOG_DEBUG ("Handle arg name="<<name<<" value="<<value);
-  if (name == "PrintHelp")
+  if (name == "PrintHelp" || name == "help")
     {
       // method below never returns.
       PrintHelp ();
@@ -332,4 +367,25 @@
   m_items.push_back (item);
 }
 
+template <>
+bool
+CommandLineHelper::UserItemParse<bool> (const std::string value, bool & val)
+{
+  std::string src = value;
+  std::transform(src.begin(), src.end(), src.begin(), ::tolower);
+  
+  if ( (value.length () == 0) || (value == "true") || (value == "t"))
+    {
+      val = true;
+      return true;
+    }
+  else
+    {
+      std::istringstream iss;
+      iss.str (value);
+      iss >> val;
+      return !iss.bad () && !iss.fail ();
+    }
+}
+
 } // namespace ns3
--- a/src/core/model/command-line.h	Fri Jun 14 08:08:29 2013 -0700
+++ b/src/core/model/command-line.h	Fri Jun 14 13:54:39 2013 -0700
@@ -29,35 +29,121 @@
 namespace ns3 {
 
 /**
- * \brief parse command-line arguments
  * \ingroup core
+ * \defgroup commandline Command Line Parsing
+ *
+ * A uniform way to specify program documentation,
+ * allowed command line arguments and help strings,
+ * and set any attribute or global value, all from
+ * the command line directly.
+ *
+ * The main entry point is CommandLine
+ */
+/**
+ * \ingroup commandline
+ * \brief Parse command-line arguments
  *
  * Instances of this class can be used to parse command-line 
- * arguments: users can register new arguments with
- * CommandLine::AddValue but the most important functionality
- * provided by this class is that it can be used to set the
+ * arguments: programs can register new arguments with
+ * CommandLine::AddValue.
+ *
+ * In addition, this class can be used to set the
  * 'initial value' of every attribute in the system with the
- * \verbatim
+ * \code
  *   --TypeIdName::AttributeName=value
- * \endverbatim
- * syntax and it can be used to set the value of every GlobalValue
+ * \endcode
+ * syntax, and it can be used to set the value of every GlobalValue
  * in the system with the
- * \verbatim
+ * \code
  *   --GlobalValueName=value
- * \endverbatim
+ * \endcode
  * syntax.
+ *
+ * A simple example is in \c src/core/example/command-line-example.cc
+ * The heart of that example is this code:
+ *
+ * \code
+ *   int         val1 = 1;
+ *  bool        val2 = false;
+ *  std::string val3 = "";
+ *  
+ *  CommandLine cmd;
+ *  cmd.Usage ("CommandLine example program.\n"
+ *             "\n"
+ *             "This little program demonstrates how to use CommandLine.");
+ *  cmd.AddValue ("val1", "an int argument",          val1);
+ *  cmd.AddValue ("val2", "a bool argument",          val2);
+ *  cmd.AddValue ("val3", "a string argument",          val3);
+ *  cmd.Parse (argc, argv);
+ * \endcode
+ *
+ * Here is the output from a few runs of that program:
+ *
+ * \code
+ *   $ ./waf --run="command-line-example"
+ *   val1:   1
+ *   val2:   0
+ *   val3:   ""
+ *
+ *   $ ./waf --run="command-line-example --val1=2 --val2 --val3=Hello"
+ *   val1:   2
+ *   val2:   1
+ *   val3:   "Hello"
+ *   
+ *   $ ./waf --run="command-line-example --help"
+ *   ns3-dev-command-line-example-debug [Program Arguments] [General Arguments]
+ *   
+ *   CommandLine example program.
+ *   
+ *   This little program demonstrates how to use CommandLine.
+ *   
+ *   Program Arguments:
+ *       --val1:     an int argument
+ *       --val2:     a bool argument
+ *       --val3:     a string argument
+ *   
+ *   General Arguments:
+ *       --PrintHelp:                 Print this help message.
+ *       --PrintGroups:               Print the list of groups.
+ *       --PrintTypeIds:              Print all TypeIds.
+ *       --PrintGroup=[group]:        Print all TypeIds of group.
+ *       --PrintAttributes=[typeid]:  Print all attributes of typeid.
+ *       --PrintGlobals:              Print the list of globals.
+ * \endcode
  */
 class CommandLine
 {
 public:
+  /** Constructor */
   CommandLine ();
+  /**
+   * Copy constructor
+   *
+   * \param cmd the CommandLine to copy from
+   */
   CommandLine (const CommandLine &cmd);
+  /**
+   * Assignment
+   *
+   * \param cmd the CommandLine to assign from
+   * \return the CommandLine
+   */
   CommandLine &operator = (const CommandLine &cmd);
+  /** Destructor */
   ~CommandLine ();
 
   /**
-   * \param name the name of the user-supplied argument
-   * \param help some help text used by --PrintHelp
+   * Supply the program usage and documentation.
+   *
+   * \param usage Program usage message to write with help.
+   */
+  void Usage (const std::string usage);
+  
+  /**
+   * Add a program argument, assigning to POD
+   *
+   * \param name the name of the program-supplied argument
+   * \param help the help text used by \c \-\-PrintHelp
    * \param value a reference to the variable where the
    *        value parsed will be stored (if no value
    *        is parsed, this variable is not modified).
@@ -69,16 +155,20 @@
 
 
   /**
-   * \param name the name of the user-supplied argument
-   * \param help some help text used by --PrintHelp
-   * \param callback a callback function that will be invoked to parse
-   * and collect the value.  This normally used by language bindings.
+   * Add a program argument, using a Callback to parse the value
+   *
+   * \param name the name of the program-supplied argument
+   * \param help the help text used by \c \-\-PrintHelp
+   * \param callback a Callback function that will be invoked to parse
+   * and collect the value.  This is normally used by language bindings.
    */
   void AddValue (const std::string &name,
                  const std::string &help,
                  Callback<bool, std::string> callback);
 
   /**
+   * Parse the program arguments
+   *
    * \param argc the 'argc' variable: number of arguments (including the
    *        main program name as first element).
    * \param argv the 'argv' variable: a null-terminated array of strings,
@@ -86,45 +176,145 @@
    * 
    * Obviously, this method will parse the input command-line arguments and
    * will attempt to handle them all.
+   *
+   * As a side effect, this method saves the program basename, which
+   * can be retrieved by GetName().
    */
-  void Parse (int argc, char *argv[]) const;
+  void Parse (int argc, char *argv[]);
+
+  /**
+   * Get the program name
+   *
+   * \return the program name.  Only valid after calling Parse()
+   */
+  std::string GetName () const;
+
 private:
+
+  /**
+   * \ingroup commandline
+   * \brief The argument base class
+   */
   class Item 
   {
-public:
-    std::string m_name;
-    std::string m_help;
-    virtual ~Item ();
+  public:
+    std::string m_name;       /**< Argument label:  \c \-\--m_name=... */
+    std::string m_help;       /**< Argument help string */
+    virtual ~Item ();         /**< Destructor */
+    /**
+     * Parse from a string.
+     *
+     * \param value the string representation
+     * \return true if parsing the value succeeded
+     */
     virtual bool Parse (std::string value) = 0;
   };
+
+  /**
+   * \ingroup commandline
+   *\brief An argument Item assigning to POD
+   */
   template <typename T>
   class UserItem : public Item
   {
-public:
+  public:
+    /**
+     * Parse from a string.
+     *
+     * \param value the string representation
+     * \return true if parsing the value succeeded
+     */
     virtual bool Parse (std::string value);
-    T *m_valuePtr;
+    T *m_valuePtr;            /**< Pointer to the POD location */
   };
+
+  /**
+   * \ingroup commandline
+   * \brief An argument Item using a Callback to parse the input
+   */
   class CallbackItem : public Item
   {
-public:
+  public:
+    /**
+     * Parse from a string.
+     *
+     * \param value the string representation
+     * \return true if parsing the value succeeded
+     */
     virtual bool Parse (std::string value);
-    Callback<bool, std::string> m_callback;
+    Callback<bool, std::string> m_callback;  /**< The Callback */
   };
 
+  /**
+   * Match name against the program or general arguments,
+   * and dispatch to the appropriate handler.
+   *
+   * \param name the argument name
+   * \param value the command line value
+   */
   void HandleArgument (std::string name, std::string value) const;
+  /**
+   * Handler for \c \-\-PrintHelp and \c \-\-help:  print Usage(), argument names, and help strings
+   */
   void PrintHelp (void) const;
+  /** Handler for \c \-\-PrintGlobals:  print all global variables and values */
   void PrintGlobals (void) const;
+  /**
+   * Handler for \c \-\-PrintAttributes:  print the attributes for a given type.
+   *
+   * \param type the TypeId whose Attributes should be displayed
+   */
   void PrintAttributes (std::string type) const;
+  /**
+   * Handler for \c \-\-PrintGroup:  print all types belonging to a given group.
+   *
+   * \param group the name of the TypeId group to display
+   */
   void PrintGroup (std::string group) const;
+  /** Handler for \c \-\-PrintTypeIds:  print all TypeId names. */
   void PrintTypeIds (void) const;
+  /** Handler for \c \-\-PrintGroups:  print all TypeId group names */
   void PrintGroups (void) const;
+  /**
+   * Copy constructor
+   *
+   * \param cmd CommandLine to copy
+   */
   void Copy (const CommandLine &cmd);
+  /** Remove all arguments, Usage(), name */
   void Clear (void);
 
-  typedef std::list<Item *> Items;
-  Items m_items;
-};
+  typedef std::list<Item *> Items;      /**< Argument list container */
+  Items m_items;                        /**< The list of arguments */
+  std::string m_usage;                  /**< The Usage string */
+  std::string m_name;                   /**< The program name */
+};  // class CommandLine
+
+/**
+ * \ingroup commandline
+ * Helpers for CommandLine
+ */
+namespace CommandLineHelper {
 
+  /**
+   * \ingroup commandline
+   * \brief Helper to specialize UserItem on bool
+   *
+   * \param value the argument name
+   * \param val the argument location
+   * \return true if parsing was successful
+   * @{
+   */
+  template <typename T>
+  bool UserItemParse (const std::string value, T & val);
+  template <>
+  bool UserItemParse<bool> (const std::string value, bool & val);
+  /**@}*/
+
+}  // namespace CommandLineHelper
+    
+  
+  
 } // namespace ns3
 
 namespace ns3 {
@@ -143,12 +333,19 @@
 }
 
 template <typename T>
-bool 
+bool
 CommandLine::UserItem<T>::Parse (std::string value)
 {
+  return CommandLineHelper::UserItemParse<T> (value, *m_valuePtr);
+}
+
+template <typename T>
+bool
+CommandLineHelper::UserItemParse (const std::string value, T & val)
+{
   std::istringstream iss;
   iss.str (value);
-  iss >> (*m_valuePtr);
+  iss >> val;
   return !iss.bad () && !iss.fail ();
 }
 
--- a/src/core/test/command-line-test-suite.cc	Fri Jun 14 08:08:29 2013 -0700
+++ b/src/core/test/command-line-test-suite.cc	Fri Jun 14 13:54:39 2013 -0700
@@ -29,16 +29,28 @@
 
 using namespace ns3;
 
-// ===========================================================================
-// A test base class that drives Command Line parsing
-// ===========================================================================
+/*************************************************************************//**
+ * A test base class that drives Command Line parsing
+ ****************************************************************************/
 class CommandLineTestCaseBase : public TestCase
 {
 public:
+  /**
+   * Constructor
+   *
+   * \param description purpose of this TestCase
+   */
   CommandLineTestCaseBase (std::string description);
+  /** Destructor */
   virtual ~CommandLineTestCaseBase () {}
 
-  void Parse (const CommandLine &cmd, int n, ...);
+  /**
+   * Excercise the CommandLine with the provided arguments
+   *
+   * \param cmd the configured CommandLine
+   * \param n the number of arguments
+   */
+  void Parse (CommandLine &cmd, int n, ...);
 };
 
 CommandLineTestCaseBase::CommandLineTestCaseBase (std::string description)
@@ -47,7 +59,7 @@
 }
 
 void
-CommandLineTestCaseBase::Parse (const CommandLine &cmd, int n, ...)
+CommandLineTestCaseBase::Parse (CommandLine &cmd, int n, ...)
 {
   char **args = new char* [n+1];
   args[0] = (char *) "Test";
@@ -66,17 +78,17 @@
   delete [] args;
 }
 
-// ===========================================================================
-// Test boolean Command Line processing
-// ===========================================================================
+/*************************************************************************//**
+ * Test boolean Command Line processing
+ ****************************************************************************/
 class CommandLineBooleanTestCase : public CommandLineTestCaseBase
 {
 public:
-  CommandLineBooleanTestCase ();
-  virtual ~CommandLineBooleanTestCase () {}
+  CommandLineBooleanTestCase ();             /**< Constructor */
+  virtual ~CommandLineBooleanTestCase () {}  /**< Destructor */
 
 private:
-  virtual void DoRun (void);
+  virtual void DoRun (void);                 /**< Run the test */
 
 };
 
@@ -97,20 +109,29 @@
   NS_TEST_ASSERT_MSG_EQ (myBool, false, "Command parser did not correctly set a boolean value to false");
 
   Parse (cmd, 1, "--my-bool=1");
-  NS_TEST_ASSERT_MSG_EQ (myBool, true, "Command parser did not correctly set a boolean value to true");
+  NS_TEST_ASSERT_MSG_EQ (myBool, true, "Command parser did not correctly set a boolean value to true, given integer argument");
+
+  Parse (cmd, 1, "--my-bool");
+  NS_TEST_ASSERT_MSG_EQ (myBool, true, "Command parser did not correctly set a boolean value to true, given no argument");
+
+  Parse (cmd, 1, "--my-bool=t");
+  NS_TEST_ASSERT_MSG_EQ (myBool, true, "Command parser did not correctly set a boolean value to true, given 't' argument");
+
+  Parse (cmd, 1, "--my-bool=true");
+  NS_TEST_ASSERT_MSG_EQ (myBool, true, "Command parser did not correctly set a boolean value to true, given \"true\" argument");
 }
 
-// ===========================================================================
-// Test int Command Line processing
-// ===========================================================================
+/*************************************************************************//**
+ * Test int Command Line processing
+ ****************************************************************************/
 class CommandLineIntTestCase : public CommandLineTestCaseBase
 {
 public:
-  CommandLineIntTestCase ();
-  virtual ~CommandLineIntTestCase () {}
-
-private:
-  virtual void DoRun (void);
+  CommandLineIntTestCase ();                 /**< Constructor */ 
+  virtual ~CommandLineIntTestCase () {}      /**< Destructor */  
+                                                                 
+private:                                                         
+  virtual void DoRun (void);                 /**< Run the test */
 
 };
 
@@ -138,17 +159,17 @@
   NS_TEST_ASSERT_MSG_EQ (myInt32, +2, "Command parser did not correctly set an integer value to +2");
 }
 
-// ===========================================================================
-// Test unsigned int Command Line processing
-// ===========================================================================
+/*************************************************************************//**
+ * Test unsigned int Command Line processing
+ ****************************************************************************/
 class CommandLineUnsignedIntTestCase : public CommandLineTestCaseBase
 {
 public:
-  CommandLineUnsignedIntTestCase ();
-  virtual ~CommandLineUnsignedIntTestCase () {}
-
-private:
-  virtual void DoRun (void);
+  CommandLineUnsignedIntTestCase ();              /**< Constructor */ 
+  virtual ~CommandLineUnsignedIntTestCase () {}   /**< Destructor */  
+                                                                      
+private:                                                              
+  virtual void DoRun (void);                      /**< Run the test */
 
 };
 
@@ -173,17 +194,17 @@
   NS_TEST_ASSERT_MSG_EQ (myUint32, 9, "Command parser did not correctly set an unsigned integer value to 9");
 }
 
-// ===========================================================================
-// Test string Command Line processing
-// ===========================================================================
+/*************************************************************************//**
+ * Test string Command Line processing
+ ****************************************************************************/
 class CommandLineStringTestCase : public CommandLineTestCaseBase
 {
 public:
-  CommandLineStringTestCase ();
-  virtual ~CommandLineStringTestCase () {}
-
-private:
-  virtual void DoRun (void);
+  CommandLineStringTestCase ();              /**< Constructor */ 
+  virtual ~CommandLineStringTestCase () {}   /**< Destructor */  
+                                                                 
+private:                                                         
+  virtual void DoRun (void);                 /**< Run the test */
 
 };
 
@@ -208,13 +229,13 @@
   NS_TEST_ASSERT_MSG_EQ (myStr, "XX", "Command parser did not correctly set an string value to \"XX\"");
 }
 
-// ===========================================================================
-// The Test Suite that glues all of the Test Cases together.
-// ===========================================================================
+/*************************************************************************//**
+ * The Test Suite that glues all of the Test Cases together.
+ ****************************************************************************/
 class CommandLineTestSuite : public TestSuite
 {
 public:
-  CommandLineTestSuite ();
+  CommandLineTestSuite ();                   /**< Constructor */
 };
 
 CommandLineTestSuite::CommandLineTestSuite ()
@@ -226,4 +247,4 @@
   AddTestCase (new CommandLineStringTestCase, TestCase::QUICK);
 }
 
-static CommandLineTestSuite CommandLineTestSuite;
+static CommandLineTestSuite CommandLineTestSuite; /**< Test instance */