From c5dd4d37155da2efeac3a33bec65b11267fa5d78 Mon Sep 17 00:00:00 2001
From: Edward d'Auvergne <edward@nmr-relax.com>
Date: Wed, 7 Aug 2019 11:21:42 +0200
Subject: [PATCH] TestSuite: Simplification of the command line option
 processing.

Most of the code has been shifted into separate functions.  This will allow for
its reuse when environmental variable support is added.
---
 test_suite/testSuite.cxx | 326 +++++++++++++++++++++------------------
 1 file changed, 180 insertions(+), 146 deletions(-)

diff --git a/test_suite/testSuite.cxx b/test_suite/testSuite.cxx
index a941f0dca..d33bd3fc2 100644
--- a/test_suite/testSuite.cxx
+++ b/test_suite/testSuite.cxx
@@ -29,6 +29,177 @@
 using namespace std;
 
 
+// The help message.
+void helpPrintout(std::ostream &stream) {
+    stream << "Usage: run_test_suite [options]" << std::endl << std::endl;
+    stream << "Options:" << std::endl;
+    stream << "  -h, --help            show this help message and exit." << std::endl;
+    stream << std::endl;
+    stream << "  Test selection options:" << std::endl;
+    stream << "    -s, --system-tests  execute the system/functional tests." << std::endl;
+    stream << "    -u, --unit-tests    execute the unit tests." << std::endl;
+    stream << "    -g, --gui-tests     execute the GUI tests." << std::endl;
+    stream << "    -m, --simgear-tests execute the simgear tests." << std::endl;
+    stream << "    -f, --fgdata-tests  execute the FGData tests." << std::endl;
+    stream << std::endl;
+    stream << "    The -s, -u, -g, and -m options accept an optional argument to perform a" << std::endl;
+    stream << "    subset of all tests.  This argument should either be the name of a test" << std::endl;
+    stream << "    suite or the full name of an individual test." << std::endl;
+    stream << std::endl;
+    stream << "    Full test names consist of the test suite name, the separator '::' and then" << std::endl;
+    stream << "    the individual test name.  The test names can revealed with the verbose" << std::endl;
+    stream << "    option." << std::endl;
+    stream << std::endl;
+    stream << "  Logging options:" << std::endl;
+    stream << "    --log-level={bulk,debug,info,warn,alert,popup,dev_warn,dev_alert}" << std::endl;
+    stream << "                        specify the minimum logging level to output" << std::endl;
+    stream << "    --log-class=[none, terrain, astro, flight, input, gl, view, cockpit," << std::endl;
+    stream << "                 general, math, event, aircraft, autopilot, io, clipper," << std::endl;
+    stream << "                 network, atc, nasal, instrumentation, systems, ai, environment," << std::endl;
+    stream << "                 sound, navaid, gui, terrasync, particles, headless, osg," << std::endl;
+    stream << "                 undefined, all]" << std::endl;
+    stream << "                        select the logging class(es) to output" << std::endl;
+    stream << "    --log-split         output the different non-interleaved log streams" << std::endl;
+    stream << "                        sequentially" << std::endl;
+    stream << std::endl;
+    stream << "  Verbosity options:" << std::endl;
+    stream << "    -t, --timings       verbose output including names and timings for all" << std::endl;
+    stream << "                        tests." << std::endl;
+    stream << "    -c, --ctest         simplified output suitable for running via CTest." << std::endl;
+    stream << "    -d, --debug         disable IO capture for debugging (super verbose output)." << std::endl;
+    stream << "    --no-summary        disable the final summary printout." << std::endl;
+    stream << std::endl;
+    stream << "  FG options:" << std::endl;
+    stream << "    --fg-root           the path to FGData" << std::endl;
+    stream.flush();
+}
+
+
+// Convert the log class comma separated string list into a simgear debug class value.
+sgDebugClass processLogClass(std::string classList, bool &failure) {
+    // Declarations.
+    std::string logClassItem, val;
+    unsigned int logClass=0;
+
+    // Convert the command line value into a string array.
+    std::replace(classList.begin(), classList.end(), ',', ' ');
+    std::vector<std::string> logClasses;
+    stringstream temp(classList);
+    while (temp >> val)
+        logClasses.push_back(val);
+
+    // Build up the value.
+    for (auto const& logClassItem: logClasses)
+        if (logClassItem == "none")
+            logClass |= SG_NONE;
+        else if (logClassItem == "terrain")
+            logClass |= SG_TERRAIN;
+        else if (logClassItem == "astro")
+            logClass |= SG_ASTRO;
+        else if (logClassItem == "flight")
+            logClass |= SG_FLIGHT;
+        else if (logClassItem == "input")
+            logClass |= SG_INPUT;
+        else if (logClassItem == "gl")
+            logClass |= SG_GL;
+        else if (logClassItem == "view")
+            logClass |= SG_VIEW;
+        else if (logClassItem == "cockpit")
+            logClass |= SG_COCKPIT;
+        else if (logClassItem == "general")
+            logClass |= SG_GENERAL;
+        else if (logClassItem == "math")
+            logClass |= SG_MATH;
+        else if (logClassItem == "event")
+            logClass |= SG_EVENT;
+        else if (logClassItem == "aircraft")
+            logClass |= SG_AIRCRAFT;
+        else if (logClassItem == "autopilot")
+            logClass |= SG_AUTOPILOT;
+        else if (logClassItem == "io")
+            logClass |= SG_IO;
+        else if (logClassItem == "clipper")
+            logClass |= SG_CLIPPER;
+        else if (logClassItem == "network")
+            logClass |= SG_NETWORK;
+        else if (logClassItem == "atc")
+            logClass |= SG_ATC;
+        else if (logClassItem == "nasal")
+            logClass |= SG_NASAL;
+        else if (logClassItem == "instrumentation")
+            logClass |= SG_INSTR;
+        else if (logClassItem == "systems")
+            logClass |= SG_SYSTEMS;
+        else if (logClassItem == "ai")
+            logClass |= SG_AI;
+        else if (logClassItem == "environment")
+            logClass |= SG_ENVIRONMENT;
+        else if (logClassItem == "sound")
+            logClass |= SG_SOUND;
+        else if (logClassItem == "navaid")
+            logClass |= SG_NAVAID;
+        else if (logClassItem == "gui")
+            logClass |= SG_GUI;
+        else if (logClassItem == "terrasync")
+            logClass |= SG_TERRASYNC;
+        else if (logClassItem == "particles")
+            logClass |= SG_PARTICLES;
+        else if (logClassItem == "headless")
+            logClass |= SG_HEADLESS;
+        else if (logClassItem == "osg")
+            logClass |= SG_OSG;
+        else if (logClassItem == "undefined")
+            logClass |= SG_UNDEFD;
+        else if (logClassItem == "all")
+            logClass |= SG_ALL;
+        else {
+            std::cout << "The log class \"" << logClassItem << "\" must be one of:" << std::endl;
+            std::cout << "    {none, terrain, astro, flight, input, gl, view, cockpit, general, math," << std::endl;
+            std::cout << "    event, aircraft, autopilot, io, clipper, network, atc, nasal," << std::endl;
+            std::cout << "    instrumentation, systems, ai, environment, sound, navaid, gui, terrasync," << std::endl;
+            std::cout << "    particles, headless, osg, undefined, all}" << std::endl << std::endl;
+            std::cout.flush();
+            failure = true;
+        }
+
+    // Return a simgear debug class.
+    return sgDebugClass(logClass);
+}
+
+
+// Convert the log priority string into a simgear debug priority value.
+sgDebugPriority processLogPriority(std::string logLevel, bool &failure) {
+    // Declarations.
+    sgDebugPriority logPriority=SG_INFO;
+
+    // Conversion.
+    if (logLevel == "bulk")
+        logPriority = SG_BULK;
+    else if (logLevel == "debug")
+        logPriority = SG_DEBUG;
+    else if (logLevel == "info")
+        logPriority = SG_INFO;
+    else if (logLevel == "warn")
+        logPriority = SG_WARN;
+    else if (logLevel == "alert")
+        logPriority = SG_ALERT;
+    else if (logLevel == "popup")
+        logPriority = SG_POPUP;
+    else if (logLevel == "dev_warn")
+        logPriority = SG_DEV_WARN;
+    else if (logLevel == "dev_alert")
+        logPriority = SG_DEV_ALERT;
+    else {
+        std::cout << "The log level setting of \"" << logLevel << "\" must be one of {bulk,debug,info,warn,alert,popup,dev_warn,dev_alert}.\n\n";
+        std::cout.flush();
+        failure = true;
+    }
+
+    // Return the simgear debug priority.
+    return logPriority;
+}
+
+
 // Print out a summary of the relax test suite.
 void summary(CppUnit::OStream &stream, int system_result, int unit_result, int gui_result, int simgear_result, int fgdata_result)
 {
@@ -94,12 +265,13 @@ int main(int argc, char **argv)
     bool        logSplit=false;
     bool        timings=false, ctest_output=false, debug=false, printSummary=true, help=false;
     char        *subset_system=NULL, *subset_unit=NULL, *subset_gui=NULL, *subset_simgear=NULL, *subset_fgdata=NULL;
+    bool        failure=false;
     char        firstchar;
-    std::string arg, delim, fgRoot, logClassVal, logClassItem, logLevel, val;
+    std::string arg, delim, fgRoot, logClassVal, logLevel;
     size_t      delimPos;
 
     // The default logging class and priority to show.
-    unsigned int    logClass=SG_ALL;
+    sgDebugClass    logClass=SG_ALL;
     sgDebugPriority logPriority=SG_INFO;
 
     // Argument parsing.
@@ -146,116 +318,18 @@ int main(int argc, char **argv)
             logClass = SG_NONE;
             delimPos = arg.find('=');
             logClassVal = arg.substr(delimPos + 1);
-
-            // Convert the command line value into a string array.
-            std::replace(logClassVal.begin(), logClassVal.end(), ',', ' ');
-            std::vector<std::string> logClasses;
-            stringstream temp(logClassVal);
-            while (temp >> val)
-                logClasses.push_back(val);
-
-            // Build up the value.
-            for (auto const& logClassItem: logClasses)
-                if (logClassItem == "none")
-                    logClass |= SG_NONE;
-                else if (logClassItem == "terrain")
-                    logClass |= SG_TERRAIN;
-                else if (logClassItem == "astro")
-                    logClass |= SG_ASTRO;
-                else if (logClassItem == "flight")
-                    logClass |= SG_FLIGHT;
-                else if (logClassItem == "input")
-                    logClass |= SG_INPUT;
-                else if (logClassItem == "gl")
-                    logClass |= SG_GL;
-                else if (logClassItem == "view")
-                    logClass |= SG_VIEW;
-                else if (logClassItem == "cockpit")
-                    logClass |= SG_COCKPIT;
-                else if (logClassItem == "general")
-                    logClass |= SG_GENERAL;
-                else if (logClassItem == "math")
-                    logClass |= SG_MATH;
-                else if (logClassItem == "event")
-                    logClass |= SG_EVENT;
-                else if (logClassItem == "aircraft")
-                    logClass |= SG_AIRCRAFT;
-                else if (logClassItem == "autopilot")
-                    logClass |= SG_AUTOPILOT;
-                else if (logClassItem == "io")
-                    logClass |= SG_IO;
-                else if (logClassItem == "clipper")
-                    logClass |= SG_CLIPPER;
-                else if (logClassItem == "network")
-                    logClass |= SG_NETWORK;
-                else if (logClassItem == "atc")
-                    logClass |= SG_ATC;
-                else if (logClassItem == "nasal")
-                    logClass |= SG_NASAL;
-                else if (logClassItem == "instrumentation")
-                    logClass |= SG_INSTR;
-                else if (logClassItem == "systems")
-                    logClass |= SG_SYSTEMS;
-                else if (logClassItem == "ai")
-                    logClass |= SG_AI;
-                else if (logClassItem == "environment")
-                    logClass |= SG_ENVIRONMENT;
-                else if (logClassItem == "sound")
-                    logClass |= SG_SOUND;
-                else if (logClassItem == "navaid")
-                    logClass |= SG_NAVAID;
-                else if (logClassItem == "gui")
-                    logClass |= SG_GUI;
-                else if (logClassItem == "terrasync")
-                    logClass |= SG_TERRASYNC;
-                else if (logClassItem == "particles")
-                    logClass |= SG_PARTICLES;
-                else if (logClassItem == "headless")
-                    logClass |= SG_HEADLESS;
-                else if (logClassItem == "osg")
-                    logClass |= SG_OSG;
-                else if (logClassItem == "undefined")
-                    logClass |= SG_UNDEFD;
-                else if (logClassItem == "all")
-                    logClass |= SG_ALL;
-                else {
-                    std::cout << "The log class \"" << logClassItem << "\" must be one of:" << std::endl;
-                    std::cout << "    {none, terrain, astro, flight, input, gl, view, cockpit, general, math," << std::endl;
-                    std::cout << "    event, aircraft, autopilot, io, clipper, network, atc, nasal," << std::endl;
-                    std::cout << "    instrumentation, systems, ai, environment, sound, navaid, gui, terrasync," << std::endl;
-                    std::cout << "    particles, headless, osg, undefined, all}" << std::endl << std::endl;
-                    std::cout.flush();
-                    return 1;
-                }
+            logClass = processLogClass(logClassVal, failure);
+            if (failure)
+                return 1;
 
         // Log level.
         } else if (arg.find( "--log-level" ) == 0) {
             // Process the command line level.
             delimPos = arg.find('=');
             logLevel = arg.substr(delimPos + 1);
-
-            // Convert.
-            if (logLevel == "bulk")
-                logPriority = SG_BULK;
-            else if (logLevel == "debug")
-                logPriority = SG_DEBUG;
-            else if (logLevel == "info")
-                logPriority = SG_INFO;
-            else if (logLevel == "warn")
-                logPriority = SG_WARN;
-            else if (logLevel == "alert")
-                logPriority = SG_ALERT;
-            else if (logLevel == "popup")
-                logPriority = SG_POPUP;
-            else if (logLevel == "dev_warn")
-                logPriority = SG_DEV_WARN;
-            else if (logLevel == "dev_alert")
-                logPriority = SG_DEV_ALERT;
-            else {
-                std::cout << "The log level setting of \"" << logLevel << "\" must be one of {bulk,debug,info,warn,alert,popup,dev_warn,dev_alert}.\n\n";
-                std::cout.flush();
+            logPriority = processLogPriority(logLevel, failure);
+            if (failure)
                 return 1;
-            }
 
         // Log splitting.
         } else if (arg == "--log-split") {
@@ -290,47 +364,7 @@ int main(int argc, char **argv)
 
     // Help.
     if (help) {
-        std::cout << "Usage: run_test_suite [options]" << std::endl << std::endl;
-        std::cout << "Options:" << std::endl;
-        std::cout << "  -h, --help            show this help message and exit." << std::endl;
-        std::cout << std::endl;
-        std::cout << "  Test selection options:" << std::endl;
-        std::cout << "    -s, --system-tests  execute the system/functional tests." << std::endl;
-        std::cout << "    -u, --unit-tests    execute the unit tests." << std::endl;
-        std::cout << "    -g, --gui-tests     execute the GUI tests." << std::endl;
-        std::cout << "    -m, --simgear-tests execute the simgear tests." << std::endl;
-        std::cout << "    -f, --fgdata-tests  execute the FGData tests." << std::endl;
-        std::cout << std::endl;
-        std::cout << "    The -s, -u, -g, and -m options accept an optional argument to perform a" << std::endl;
-        std::cout << "    subset of all tests.  This argument should either be the name of a test" << std::endl;
-        std::cout << "    suite or the full name of an individual test." << std::endl;
-        std::cout << std::endl;
-        std::cout << "    Full test names consist of the test suite name, the separator '::' and then" << std::endl;
-        std::cout << "    the individual test name.  The test names can revealed with the verbose" << std::endl;
-        std::cout << "    option." << std::endl;
-        std::cout << std::endl;
-        std::cout << "  Logging options:" << std::endl;
-        std::cout << "    --log-level={bulk,debug,info,warn,alert,popup,dev_warn,dev_alert}" << std::endl;
-        std::cout << "                        specify the minimum logging level to output" << std::endl;
-        std::cout << "    --log-class=[none, terrain, astro, flight, input, gl, view, cockpit," << std::endl;
-        std::cout << "                 general, math, event, aircraft, autopilot, io, clipper," << std::endl;
-        std::cout << "                 network, atc, nasal, instrumentation, systems, ai, environment," << std::endl;
-        std::cout << "                 sound, navaid, gui, terrasync, particles, headless, osg," << std::endl;
-        std::cout << "                 undefined, all]" << std::endl;
-        std::cout << "                        select the logging class(es) to output" << std::endl;
-        std::cout << "    --log-split         output the different non-interleaved log streams" << std::endl;
-        std::cout << "                        sequentially" << std::endl;
-        std::cout << std::endl;
-        std::cout << "  Verbosity options:" << std::endl;
-        std::cout << "    -t, --timings       verbose output including names and timings for all" << std::endl;
-        std::cout << "                        tests." << std::endl;
-        std::cout << "    -c, --ctest         simplified output suitable for running via CTest." << std::endl;
-        std::cout << "    -d, --debug         disable IO capture for debugging (super verbose output)." << std::endl;
-        std::cout << "    --no-summary        disable the final summary printout." << std::endl;
-        std::cout << std::endl;
-        std::cout << "  FG options:" << std::endl;
-        std::cout << "    --fg-root           the path to FGData" << std::endl;
-        std::cout.flush();
+        helpPrintout(std::cout);
         return 0;
     }