From d448b8ceb4d777205b635680f4b88842d3cbd265 Mon Sep 17 00:00:00 2001 From: Edward d'Auvergne Date: Tue, 30 Jul 2019 11:44:09 +0200 Subject: [PATCH 1/7] TestSuite: Command line option processing simplification by using std::string. --- test_suite/testSuite.cxx | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/test_suite/testSuite.cxx b/test_suite/testSuite.cxx index ff3c3db90..b31840d0f 100644 --- a/test_suite/testSuite.cxx +++ b/test_suite/testSuite.cxx @@ -93,34 +93,36 @@ int main(int argc, char **argv) bool verbose=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; char firstchar; - std::string fgRoot; + std::string arg, fgRoot; // Argument parsing. for (int i = 1; i < argc; i++) { firstchar = '\0'; + arg = argv[i]; + if (i < argc-1) firstchar = argv[i+1][0]; // System test. - if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--system-tests") == 0) { + if (arg == "-s" || arg == "--system-tests") { run_system = true; if (firstchar != '-') subset_system = argv[i+1]; // Unit test. - } else if (strcmp(argv[i], "-u") == 0 || strcmp(argv[i], "--unit-tests") == 0) { + } else if (arg == "-u" || arg == "--unit-tests") { run_unit = true; if (firstchar != '-') subset_unit = argv[i+1]; // GUI test. - } else if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "--gui-tests") == 0) { + } else if (arg == "-g" || arg == "--gui-tests") { run_gui = true; if (firstchar != '-') subset_gui = argv[i+1]; // Simgear test. - } else if (strcmp(argv[i], "-m") == 0 || strcmp(argv[i], "--simgear-tests") == 0) { + } else if (arg == "-m" || arg == "--simgear-tests") { run_simgear = true; if (firstchar != '-') subset_simgear = argv[i+1]; @@ -132,27 +134,27 @@ int main(int argc, char **argv) subset_fgdata = argv[i+1]; // Verbose output. - } else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) { + } else if (arg == "-v" || arg == "--verbose") { verbose = true; // CTest suitable output. - } else if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--ctest") == 0) { + } else if (arg == "-c" || arg == "--ctest") { ctest_output = true; // Debug output. - } else if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--debug") == 0) { + } else if (arg == "-d" || arg == "--debug") { debug = true; // No summary output. - } else if (strcmp(argv[i], "--no-summary") == 0) { + } else if (arg == "--no-summary") { printSummary = false; // Help. - } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { + } else if (arg == "-h" || arg == "--help") { help = true; // FGData path. - } else if (strcmp(argv[i], "--fg-root") == 0) { + } else if (arg == "--fg-root") { if (firstchar != '-') fgRoot = argv[i+1]; } From 8b777a74c9d3cfd4e9d65e9c67b4e3cd6f325d95 Mon Sep 17 00:00:00 2001 From: Edward d'Auvergne Date: Tue, 30 Jul 2019 13:19:23 +0200 Subject: [PATCH 2/7] TestSuite: Addition of the --log-level option for setting the logging priority. This option mimics the fgfs option of the same name. However for the test suite option, additionally the SG_POPUP, SG_DEV_WARN and SG_DEV_ALERT priorities are supported. The default test suite output has been modified to only show the interleaved log with the logging priority set to the command line supplied value or defaulting to SG_INFO. --- test_suite/fgCompilerOutputter.cxx | 14 +++++----- test_suite/fgCompilerOutputter.hxx | 4 +-- test_suite/fgTestListener.cxx | 6 ++--- test_suite/fgTestListener.hxx | 3 ++- test_suite/logging.cxx | 36 ++++++++++++++++++------- test_suite/logging.hxx | 13 +++++---- test_suite/testSuite.cxx | 43 +++++++++++++++++++++++++++--- 7 files changed, 89 insertions(+), 30 deletions(-) diff --git a/test_suite/fgCompilerOutputter.cxx b/test_suite/fgCompilerOutputter.cxx index 1c68da69f..27f6c84c1 100644 --- a/test_suite/fgCompilerOutputter.cxx +++ b/test_suite/fgCompilerOutputter.cxx @@ -65,12 +65,12 @@ void fgCompilerOutputter::printFailureDetail(CppUnit::TestFailure *failure) test_io = *test_iter; // SG_LOG IO streams. - fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_BULK priority", test_io.sg_bulk, true); - fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_BULK only priority", test_io.sg_bulk_only); - fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_DEBUG only priority", test_io.sg_debug_only); - fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_INFO only priority", test_io.sg_info_only); - fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_WARN only priority", test_io.sg_warn_only); - fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_ALERT only priority", test_io.sg_alert_only); + fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, "+test_io.log_priority+" priority", test_io.sg_interleaved, true); + //fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_BULK only priority", test_io.sg_bulk_only); + //fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_DEBUG only priority", test_io.sg_debug_only); + //fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_INFO only priority", test_io.sg_info_only); + //fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_WARN only priority", test_io.sg_warn_only); + //fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_ALERT only priority", test_io.sg_alert_only); // Default IO streams. fgCompilerOutputter::printIOStreamMessages("STDOUT and STDERR", test_io.stdio); @@ -96,7 +96,7 @@ void fgCompilerOutputter::printFailureReport() } -void fgCompilerOutputter::printIOStreamMessages(const char *heading, string messages, bool empty) +void fgCompilerOutputter::printIOStreamMessages(string heading, string messages, bool empty) { // Silence. if (!empty && messages.size() == 0) diff --git a/test_suite/fgCompilerOutputter.hxx b/test_suite/fgCompilerOutputter.hxx index 5fd1f0d9b..59dee23b4 100644 --- a/test_suite/fgCompilerOutputter.hxx +++ b/test_suite/fgCompilerOutputter.hxx @@ -81,8 +81,8 @@ class fgCompilerOutputter : public CppUnit::CompilerOutputter bool debug; // Simgear logstream IO printout. - void printIOStreamMessages(const char *heading, std::string messages, bool empty); - void printIOStreamMessages(const char *heading, std::string messages) {printIOStreamMessages(heading, messages, false);} + void printIOStreamMessages(std::string heading, std::string messages, bool empty); + void printIOStreamMessages(std::string heading, std::string messages) {printIOStreamMessages(heading, messages, false);} }; diff --git a/test_suite/fgTestListener.cxx b/test_suite/fgTestListener.cxx index 3803bae7b..307988fd7 100644 --- a/test_suite/fgTestListener.cxx +++ b/test_suite/fgTestListener.cxx @@ -88,7 +88,8 @@ void fgTestListener::endTest(CppUnit::Test *test) // The simgear logstreams. capturedIO &obj = getIOstreams(); - test_io.sg_bulk = obj.sg_bulk.str(); + test_io.log_priority = obj.log_priority; + test_io.sg_interleaved = obj.sg_interleaved.str(); test_io.sg_bulk_only = obj.sg_bulk_only.str(); test_io.sg_debug_only = obj.sg_debug_only.str(); test_io.sg_info_only = obj.sg_info_only.str(); @@ -100,7 +101,6 @@ void fgTestListener::endTest(CppUnit::Test *test) } } - // Override the base class function to capture IO streams. void fgTestListener::startTest(CppUnit::Test *test) { @@ -108,7 +108,7 @@ void fgTestListener::startTest(CppUnit::Test *test) if (!debug) { // Clear the simgear logstream buffers. capturedIO &obj = getIOstreams(); - obj.sg_bulk.str(""); + obj.sg_interleaved.str(""); obj.sg_bulk_only.str(""); obj.sg_debug_only.str(""); obj.sg_info_only.str(""); diff --git a/test_suite/fgTestListener.hxx b/test_suite/fgTestListener.hxx index 6ebae064b..4880b24de 100644 --- a/test_suite/fgTestListener.hxx +++ b/test_suite/fgTestListener.hxx @@ -31,8 +31,9 @@ // Data structure for holding the captured IO for a failed test. struct TestIOCapt { std::string name; + std::string log_priority; std::string stdio; - std::string sg_bulk; + std::string sg_interleaved; std::string sg_bulk_only; std::string sg_debug_only; std::string sg_info_only; diff --git a/test_suite/logging.cxx b/test_suite/logging.cxx index 809fc298f..26a19c573 100644 --- a/test_suite/logging.cxx +++ b/test_suite/logging.cxx @@ -28,21 +28,39 @@ static capturedIO *_iostreams = NULL; // capturedIO constructor. -capturedIO::capturedIO() +capturedIO::capturedIO(sgDebugPriority p) { - callback_bulk = new StreamLogCallback(sg_bulk, SG_ALL, SG_BULK, false); + callback_interleaved = new StreamLogCallback(sg_interleaved, SG_ALL, p, false); callback_bulk_only = new StreamLogCallback(sg_bulk_only, SG_ALL, SG_BULK, true); callback_debug_only = new StreamLogCallback(sg_debug_only, SG_ALL, SG_DEBUG, true); callback_info_only = new StreamLogCallback(sg_info_only, SG_ALL, SG_INFO, true); callback_warn_only = new StreamLogCallback(sg_warn_only, SG_ALL, SG_WARN, true); callback_alert_only = new StreamLogCallback(sg_alert_only, SG_ALL, SG_ALERT, true); + + // Store the priority as a string. + if (p == SG_BULK) + log_priority = "SG_BULK"; + else if (p == SG_DEBUG) + log_priority = "SG_DEBUG"; + else if (p == SG_INFO) + log_priority = "SG_INFO"; + else if (p == SG_WARN) + log_priority = "SG_WARN"; + else if (p == SG_ALERT) + log_priority = "SG_ALERT"; + else if (p == SG_POPUP) + log_priority = "SG_POPUP"; + else if (p == SG_DEV_WARN) + log_priority = "SG_DEV_WARN"; + else if (p == SG_DEV_ALERT) + log_priority = "SG_DEV_ALERT"; } // capturedIO destructor. capturedIO::~capturedIO() { // Destroy the callback objects. - delete callback_bulk; + delete callback_interleaved; delete callback_bulk_only; delete callback_debug_only; delete callback_info_only; @@ -52,11 +70,11 @@ capturedIO::~capturedIO() // Return the global stream capture data structure, creating it if needed. -capturedIO & getIOstreams() +capturedIO & getIOstreams(sgDebugPriority p) { // Initialise the global stream capture data structure, if needed. if (!_iostreams) - _iostreams = new capturedIO(); + _iostreams = new capturedIO(p); // Return a pointer to the global object. return *_iostreams; @@ -64,7 +82,7 @@ capturedIO & getIOstreams() // Set up to capture all the simgear logging priorities as separate streams. -void setupLogging() +void setupLogging(sgDebugPriority p) { // Get the single logstream instance. logstream &log = sglog(); @@ -76,8 +94,8 @@ void setupLogging() osg::setNotifyHandler(new NotifyLogger); // IO capture. - capturedIO &obj = getIOstreams(); - log.addCallback(obj.callback_bulk); + capturedIO &obj = getIOstreams(p); + log.addCallback(obj.callback_interleaved); log.addCallback(obj.callback_bulk_only); log.addCallback(obj.callback_debug_only); log.addCallback(obj.callback_info_only); @@ -94,7 +112,7 @@ void stopLogging() // IO decapture. capturedIO &obj = getIOstreams(); - log.removeCallback(obj.callback_bulk); + log.removeCallback(obj.callback_interleaved); log.removeCallback(obj.callback_bulk_only); log.removeCallback(obj.callback_debug_only); log.removeCallback(obj.callback_info_only); diff --git a/test_suite/logging.hxx b/test_suite/logging.hxx index b7e0b0d27..026e57648 100644 --- a/test_suite/logging.hxx +++ b/test_suite/logging.hxx @@ -62,11 +62,11 @@ class capturedIO { public: // Constructor and destructor. - capturedIO(); + capturedIO(sgDebugPriority); ~capturedIO(); // The IO streams. - std::ostringstream sg_bulk; + std::ostringstream sg_interleaved; std::ostringstream sg_bulk_only; std::ostringstream sg_debug_only; std::ostringstream sg_info_only; @@ -74,20 +74,23 @@ class capturedIO std::ostringstream sg_alert_only; // The callback objects. - StreamLogCallback *callback_bulk; + StreamLogCallback *callback_interleaved; StreamLogCallback *callback_bulk_only; StreamLogCallback *callback_debug_only; StreamLogCallback *callback_info_only; StreamLogCallback *callback_warn_only; StreamLogCallback *callback_alert_only; + + // The logging priority text. + std::string log_priority; }; // Return the global stream capture data structure, creating it if needed. -capturedIO & getIOstreams(); +capturedIO & getIOstreams(sgDebugPriority p=SG_BULK); // Set up to capture all the simgear logging priorities as separate streams. -void setupLogging(); +void setupLogging(sgDebugPriority); // Deactivate all the simgear logging priority IO captures. void stopLogging(); diff --git a/test_suite/testSuite.cxx b/test_suite/testSuite.cxx index b31840d0f..bc8fe6c53 100644 --- a/test_suite/testSuite.cxx +++ b/test_suite/testSuite.cxx @@ -93,7 +93,11 @@ int main(int argc, char **argv) bool verbose=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; char firstchar; - std::string arg, fgRoot; + std::string arg, fgRoot, logLevel; + size_t delimPos; + + // The default logging priority to show. + sgDebugPriority logPriority=SG_INFO; // Argument parsing. for (int i = 1; i < argc; i++) { @@ -133,6 +137,35 @@ int main(int argc, char **argv) if (firstchar != '-') subset_fgdata = argv[i+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(); + return 1; + } + // Verbose output. } else if (arg == "-v" || arg == "--verbose") { verbose = true; @@ -181,6 +214,10 @@ int main(int argc, char **argv) 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 << std::endl; std::cout << " Verbosity options:" << std::endl; std::cout << " -v, --verbose verbose output including names and timings for all" << std::endl; std::cout << " tests." << std::endl; @@ -212,9 +249,9 @@ int main(int argc, char **argv) // Set up logging. sglog().setDeveloperMode(true); if (debug) - sglog().setLogLevels(SG_ALL, SG_BULK); + sglog().setLogLevels(SG_ALL, logPriority); else - setupLogging(); + setupLogging(logPriority); // Execute each of the test suite categories. if (run_system) From b58a63543ea0bf9c5e35e707eadb07dc7e768fd9 Mon Sep 17 00:00:00 2001 From: Edward d'Auvergne Date: Tue, 30 Jul 2019 14:54:45 +0200 Subject: [PATCH 3/7] TestSuite: Implementation of the --log-split command line option. --- test_suite/fgCompilerOutputter.cxx | 18 ++++++++++++------ test_suite/logging.cxx | 22 +++++++++++++++------- test_suite/logging.hxx | 2 +- test_suite/testSuite.cxx | 9 ++++++++- 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/test_suite/fgCompilerOutputter.cxx b/test_suite/fgCompilerOutputter.cxx index 27f6c84c1..7226595ca 100644 --- a/test_suite/fgCompilerOutputter.cxx +++ b/test_suite/fgCompilerOutputter.cxx @@ -65,12 +65,18 @@ void fgCompilerOutputter::printFailureDetail(CppUnit::TestFailure *failure) test_io = *test_iter; // SG_LOG IO streams. - fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, "+test_io.log_priority+" priority", test_io.sg_interleaved, true); - //fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_BULK only priority", test_io.sg_bulk_only); - //fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_DEBUG only priority", test_io.sg_debug_only); - //fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_INFO only priority", test_io.sg_info_only); - //fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_WARN only priority", test_io.sg_warn_only); - //fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_ALERT only priority", test_io.sg_alert_only); + if (!test_io.sg_interleaved.empty()) + fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, "+test_io.log_priority+" priority", test_io.sg_interleaved, true); + if (!test_io.sg_bulk_only.empty()) + fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_BULK only priority", test_io.sg_bulk_only); + if (!test_io.sg_debug_only.empty()) + fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_DEBUG only priority", test_io.sg_debug_only); + if (!test_io.sg_info_only.empty()) + fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_INFO only priority", test_io.sg_info_only); + if (!test_io.sg_warn_only.empty()) + fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_WARN only priority", test_io.sg_warn_only); + if (!test_io.sg_alert_only.empty()) + fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_ALERT only priority", test_io.sg_alert_only); // Default IO streams. fgCompilerOutputter::printIOStreamMessages("STDOUT and STDERR", test_io.stdio); diff --git a/test_suite/logging.cxx b/test_suite/logging.cxx index 26a19c573..aa2ccb98b 100644 --- a/test_suite/logging.cxx +++ b/test_suite/logging.cxx @@ -82,7 +82,7 @@ capturedIO & getIOstreams(sgDebugPriority p) // Set up to capture all the simgear logging priorities as separate streams. -void setupLogging(sgDebugPriority p) +void setupLogging(sgDebugPriority p, bool split) { // Get the single logstream instance. logstream &log = sglog(); @@ -95,12 +95,20 @@ void setupLogging(sgDebugPriority p) // IO capture. capturedIO &obj = getIOstreams(p); - log.addCallback(obj.callback_interleaved); - log.addCallback(obj.callback_bulk_only); - log.addCallback(obj.callback_debug_only); - log.addCallback(obj.callback_info_only); - log.addCallback(obj.callback_warn_only); - log.addCallback(obj.callback_alert_only); + if (!split) + log.addCallback(obj.callback_interleaved); + else { + if (p <= SG_BULK) + log.addCallback(obj.callback_bulk_only); + if (p <= SG_DEBUG) + log.addCallback(obj.callback_debug_only); + if (p <= SG_INFO) + log.addCallback(obj.callback_info_only); + if (p <= SG_WARN) + log.addCallback(obj.callback_warn_only); + if (p <= SG_ALERT) + log.addCallback(obj.callback_alert_only); + } } diff --git a/test_suite/logging.hxx b/test_suite/logging.hxx index 026e57648..67a0df958 100644 --- a/test_suite/logging.hxx +++ b/test_suite/logging.hxx @@ -90,7 +90,7 @@ class capturedIO capturedIO & getIOstreams(sgDebugPriority p=SG_BULK); // Set up to capture all the simgear logging priorities as separate streams. -void setupLogging(sgDebugPriority); +void setupLogging(sgDebugPriority, bool); // Deactivate all the simgear logging priority IO captures. void stopLogging(); diff --git a/test_suite/testSuite.cxx b/test_suite/testSuite.cxx index bc8fe6c53..128efc149 100644 --- a/test_suite/testSuite.cxx +++ b/test_suite/testSuite.cxx @@ -90,6 +90,7 @@ int main(int argc, char **argv) // Declarations. int status_gui=-1, status_simgear=-1, status_system=-1, status_unit=-1, status_fgdata=-1; bool run_system=false, run_unit=false, run_gui=false, run_simgear=false, run_fgdata=false; + bool logSplit=false; bool verbose=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; char firstchar; @@ -166,6 +167,10 @@ int main(int argc, char **argv) return 1; } + // Log splitting. + } else if (arg == "--log-split") { + logSplit = true; + // Verbose output. } else if (arg == "-v" || arg == "--verbose") { verbose = true; @@ -217,6 +222,8 @@ int main(int argc, char **argv) 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-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 << " -v, --verbose verbose output including names and timings for all" << std::endl; @@ -251,7 +258,7 @@ int main(int argc, char **argv) if (debug) sglog().setLogLevels(SG_ALL, logPriority); else - setupLogging(logPriority); + setupLogging(logPriority, logSplit); // Execute each of the test suite categories. if (run_system) From aee367e8c29083a1ba7e42171f46096b68bccd97 Mon Sep 17 00:00:00 2001 From: Edward d'Auvergne Date: Wed, 31 Jul 2019 10:35:23 +0200 Subject: [PATCH 4/7] TestSuite: Addition of the --log-class option for selecting SG_LOG classes. This option mimics the fgfs option of the same name but additionally supports the "particles", "headless", "osg", "undefined", and "all" classes. --- test_suite/fgCompilerOutputter.cxx | 12 ++-- test_suite/fgTestListener.cxx | 1 + test_suite/fgTestListener.hxx | 1 + test_suite/logging.cxx | 33 ++++++--- test_suite/logging.hxx | 9 +-- test_suite/testSuite.cxx | 104 +++++++++++++++++++++++++++-- 6 files changed, 135 insertions(+), 25 deletions(-) diff --git a/test_suite/fgCompilerOutputter.cxx b/test_suite/fgCompilerOutputter.cxx index 7226595ca..76e0e516e 100644 --- a/test_suite/fgCompilerOutputter.cxx +++ b/test_suite/fgCompilerOutputter.cxx @@ -66,17 +66,17 @@ void fgCompilerOutputter::printFailureDetail(CppUnit::TestFailure *failure) // SG_LOG IO streams. if (!test_io.sg_interleaved.empty()) - fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, "+test_io.log_priority+" priority", test_io.sg_interleaved, true); + fgCompilerOutputter::printIOStreamMessages("SG_LOG, "+test_io.log_class+" class, "+test_io.log_priority+" priority", test_io.sg_interleaved, true); if (!test_io.sg_bulk_only.empty()) - fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_BULK only priority", test_io.sg_bulk_only); + fgCompilerOutputter::printIOStreamMessages("SG_LOG, "+test_io.log_class+" class, SG_BULK only priority", test_io.sg_bulk_only); if (!test_io.sg_debug_only.empty()) - fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_DEBUG only priority", test_io.sg_debug_only); + fgCompilerOutputter::printIOStreamMessages("SG_LOG, "+test_io.log_class+" class, SG_DEBUG only priority", test_io.sg_debug_only); if (!test_io.sg_info_only.empty()) - fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_INFO only priority", test_io.sg_info_only); + fgCompilerOutputter::printIOStreamMessages("SG_LOG, "+test_io.log_class+" class, SG_INFO only priority", test_io.sg_info_only); if (!test_io.sg_warn_only.empty()) - fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_WARN only priority", test_io.sg_warn_only); + fgCompilerOutputter::printIOStreamMessages("SG_LOG, "+test_io.log_class+" class, SG_WARN only priority", test_io.sg_warn_only); if (!test_io.sg_alert_only.empty()) - fgCompilerOutputter::printIOStreamMessages("SG_LOG, SG_ALL class, SG_ALERT only priority", test_io.sg_alert_only); + fgCompilerOutputter::printIOStreamMessages("SG_LOG, "+test_io.log_class+" class, SG_ALERT only priority", test_io.sg_alert_only); // Default IO streams. fgCompilerOutputter::printIOStreamMessages("STDOUT and STDERR", test_io.stdio); diff --git a/test_suite/fgTestListener.cxx b/test_suite/fgTestListener.cxx index 307988fd7..160fe1d45 100644 --- a/test_suite/fgTestListener.cxx +++ b/test_suite/fgTestListener.cxx @@ -88,6 +88,7 @@ void fgTestListener::endTest(CppUnit::Test *test) // The simgear logstreams. capturedIO &obj = getIOstreams(); + test_io.log_class = obj.log_class; test_io.log_priority = obj.log_priority; test_io.sg_interleaved = obj.sg_interleaved.str(); test_io.sg_bulk_only = obj.sg_bulk_only.str(); diff --git a/test_suite/fgTestListener.hxx b/test_suite/fgTestListener.hxx index 4880b24de..afe029d50 100644 --- a/test_suite/fgTestListener.hxx +++ b/test_suite/fgTestListener.hxx @@ -31,6 +31,7 @@ // Data structure for holding the captured IO for a failed test. struct TestIOCapt { std::string name; + std::string log_class; std::string log_priority; std::string stdio; std::string sg_interleaved; diff --git a/test_suite/logging.cxx b/test_suite/logging.cxx index aa2ccb98b..7800bdbf9 100644 --- a/test_suite/logging.cxx +++ b/test_suite/logging.cxx @@ -18,6 +18,8 @@ */ +#include + #include "logging.hxx" #include @@ -28,15 +30,24 @@ static capturedIO *_iostreams = NULL; // capturedIO constructor. -capturedIO::capturedIO(sgDebugPriority p) +capturedIO::capturedIO(sgDebugClass c, sgDebugPriority p) { - callback_interleaved = new StreamLogCallback(sg_interleaved, SG_ALL, p, false); - callback_bulk_only = new StreamLogCallback(sg_bulk_only, SG_ALL, SG_BULK, true); - callback_debug_only = new StreamLogCallback(sg_debug_only, SG_ALL, SG_DEBUG, true); - callback_info_only = new StreamLogCallback(sg_info_only, SG_ALL, SG_INFO, true); - callback_warn_only = new StreamLogCallback(sg_warn_only, SG_ALL, SG_WARN, true); - callback_alert_only = new StreamLogCallback(sg_alert_only, SG_ALL, SG_ALERT, true); + callback_interleaved = new StreamLogCallback(sg_interleaved, c, p, false); + callback_bulk_only = new StreamLogCallback(sg_bulk_only, c, SG_BULK, true); + callback_debug_only = new StreamLogCallback(sg_debug_only, c, SG_DEBUG, true); + callback_info_only = new StreamLogCallback(sg_info_only, c, SG_INFO, true); + callback_warn_only = new StreamLogCallback(sg_warn_only, c, SG_WARN, true); + callback_alert_only = new StreamLogCallback(sg_alert_only, c, SG_ALERT, true); + // Store the class as a string. + if (c == SG_ALL) + log_class = "SG_ALL"; + else { + std::stringstream stream; + stream << "0x" << std::right << std::setfill('0') << std::setw(8) << std::hex << c; + log_class = stream.str(); + } + // Store the priority as a string. if (p == SG_BULK) log_priority = "SG_BULK"; @@ -70,11 +81,11 @@ capturedIO::~capturedIO() // Return the global stream capture data structure, creating it if needed. -capturedIO & getIOstreams(sgDebugPriority p) +capturedIO & getIOstreams(sgDebugClass c, sgDebugPriority p) { // Initialise the global stream capture data structure, if needed. if (!_iostreams) - _iostreams = new capturedIO(p); + _iostreams = new capturedIO(c, p); // Return a pointer to the global object. return *_iostreams; @@ -82,7 +93,7 @@ capturedIO & getIOstreams(sgDebugPriority p) // Set up to capture all the simgear logging priorities as separate streams. -void setupLogging(sgDebugPriority p, bool split) +void setupLogging(sgDebugClass c, sgDebugPriority p, bool split) { // Get the single logstream instance. logstream &log = sglog(); @@ -94,7 +105,7 @@ void setupLogging(sgDebugPriority p, bool split) osg::setNotifyHandler(new NotifyLogger); // IO capture. - capturedIO &obj = getIOstreams(p); + capturedIO &obj = getIOstreams(c, p); if (!split) log.addCallback(obj.callback_interleaved); else { diff --git a/test_suite/logging.hxx b/test_suite/logging.hxx index 67a0df958..cdead96c1 100644 --- a/test_suite/logging.hxx +++ b/test_suite/logging.hxx @@ -62,7 +62,7 @@ class capturedIO { public: // Constructor and destructor. - capturedIO(sgDebugPriority); + capturedIO(sgDebugClass, sgDebugPriority); ~capturedIO(); // The IO streams. @@ -81,16 +81,17 @@ class capturedIO StreamLogCallback *callback_warn_only; StreamLogCallback *callback_alert_only; - // The logging priority text. + // The logging class and priority text. + std::string log_class; std::string log_priority; }; // Return the global stream capture data structure, creating it if needed. -capturedIO & getIOstreams(sgDebugPriority p=SG_BULK); +capturedIO & getIOstreams(sgDebugClass c=SG_ALL, sgDebugPriority p=SG_BULK); // Set up to capture all the simgear logging priorities as separate streams. -void setupLogging(sgDebugPriority, bool); +void setupLogging(sgDebugClass, sgDebugPriority, bool); // Deactivate all the simgear logging priority IO captures. void stopLogging(); diff --git a/test_suite/testSuite.cxx b/test_suite/testSuite.cxx index 128efc149..f0179d080 100644 --- a/test_suite/testSuite.cxx +++ b/test_suite/testSuite.cxx @@ -17,6 +17,7 @@ * along with this program. If not, see . */ +#include #include #include @@ -94,10 +95,11 @@ int main(int argc, char **argv) bool verbose=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; char firstchar; - std::string arg, fgRoot, logLevel; + std::string arg, delim, fgRoot, logClassVal, logClassItem, logLevel, val; size_t delimPos; - // The default logging priority to show. + // The default logging class and priority to show. + unsigned int logClass=SG_ALL; sgDebugPriority logPriority=SG_INFO; // Argument parsing. @@ -138,6 +140,94 @@ int main(int argc, char **argv) if (firstchar != '-') subset_fgdata = argv[i+1]; + // Log class. + } else if (arg.find( "--log-class" ) == 0) { + // Process the command line. + 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 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; + } + // Log level. } else if (arg.find( "--log-level" ) == 0) { // Process the command line level. @@ -222,6 +312,12 @@ int main(int argc, char **argv) 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; @@ -256,9 +352,9 @@ int main(int argc, char **argv) // Set up logging. sglog().setDeveloperMode(true); if (debug) - sglog().setLogLevels(SG_ALL, logPriority); + sglog().setLogLevels(sgDebugClass(logClass), logPriority); else - setupLogging(logPriority, logSplit); + setupLogging(sgDebugClass(logClass), logPriority, logSplit); // Execute each of the test suite categories. if (run_system) From f9f201b8304d43d2df699982dce9fcd6dc39b147 Mon Sep 17 00:00:00 2001 From: Edward d'Auvergne Date: Wed, 7 Aug 2019 10:08:22 +0200 Subject: [PATCH 5/7] TestSuite: Renamed the 'verbose' command line option to 'timings'. This is to better reflect what the option does. The -v or --verbose options are now called -t or --timings respectively. --- test_suite/fgTestListener.cxx | 4 ++-- test_suite/fgTestListener.hxx | 2 +- test_suite/fgTestRunner.cxx | 4 ++-- test_suite/testSuite.cxx | 20 ++++++++++---------- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/test_suite/fgTestListener.cxx b/test_suite/fgTestListener.cxx index 160fe1d45..c87fb7ffa 100644 --- a/test_suite/fgTestListener.cxx +++ b/test_suite/fgTestListener.cxx @@ -59,8 +59,8 @@ void fgTestListener::endTest(CppUnit::Test *test) else cerr << '.'; - // Verbose output. - if (verbose || ctest_output || debug) { + // Timing output. + if (timings || ctest_output || debug) { // Test timing. float time = ((float)(clock()-m_time))/CLOCKS_PER_SEC; char buffer[100]; diff --git a/test_suite/fgTestListener.hxx b/test_suite/fgTestListener.hxx index afe029d50..c3b0090b2 100644 --- a/test_suite/fgTestListener.hxx +++ b/test_suite/fgTestListener.hxx @@ -84,7 +84,7 @@ protected: std::vector io_capt; // Output settings. - bool verbose; + bool timings; bool ctest_output; bool debug; diff --git a/test_suite/fgTestRunner.cxx b/test_suite/fgTestRunner.cxx index 3fda79b6d..d329215cd 100644 --- a/test_suite/fgTestRunner.cxx +++ b/test_suite/fgTestRunner.cxx @@ -29,7 +29,7 @@ // Execute all test suites for the given test category. -int testRunner(const std::string& type, const std::string& title, char *subset, bool verbose, bool ctest_output, bool debug) +int testRunner(const std::string& type, const std::string& title, char *subset, bool timings, bool ctest_output, bool debug) { // Declarations. CppUnit::TextTestRunner runner; @@ -45,7 +45,7 @@ int testRunner(const std::string& type, const std::string& title, char *subset, fgTestListener *testListener; testListener = new fgTestListener; runner.eventManager().addListener(testListener); - testListener->verbose = verbose; + testListener->timings = timings; testListener->ctest_output = ctest_output; testListener->debug = debug; diff --git a/test_suite/testSuite.cxx b/test_suite/testSuite.cxx index f0179d080..a941f0dca 100644 --- a/test_suite/testSuite.cxx +++ b/test_suite/testSuite.cxx @@ -92,7 +92,7 @@ int main(int argc, char **argv) int status_gui=-1, status_simgear=-1, status_system=-1, status_unit=-1, status_fgdata=-1; bool run_system=false, run_unit=false, run_gui=false, run_simgear=false, run_fgdata=false; bool logSplit=false; - bool verbose=false, ctest_output=false, debug=false, printSummary=true, help=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; char firstchar; std::string arg, delim, fgRoot, logClassVal, logClassItem, logLevel, val; @@ -261,9 +261,9 @@ int main(int argc, char **argv) } else if (arg == "--log-split") { logSplit = true; - // Verbose output. - } else if (arg == "-v" || arg == "--verbose") { - verbose = true; + // Timing output. + } else if (arg == "-t" || arg == "--timings") { + timings = true; // CTest suitable output. } else if (arg == "-c" || arg == "--ctest") { @@ -322,7 +322,7 @@ int main(int argc, char **argv) std::cout << " sequentially" << std::endl; std::cout << std::endl; std::cout << " Verbosity options:" << std::endl; - std::cout << " -v, --verbose verbose output including names and timings for all" << 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; @@ -358,15 +358,15 @@ int main(int argc, char **argv) // Execute each of the test suite categories. if (run_system) - status_system = testRunner("System tests", "System / functional tests", subset_system, verbose, ctest_output, debug); + status_system = testRunner("System tests", "System / functional tests", subset_system, timings, ctest_output, debug); if (run_unit) - status_unit = testRunner("Unit tests", "Unit tests", subset_unit, verbose, ctest_output, debug); + status_unit = testRunner("Unit tests", "Unit tests", subset_unit, timings, ctest_output, debug); if (run_gui && 0) // Disabled as there are no GUI tests yet. - status_gui = testRunner("GUI tests", "GUI tests", subset_gui, verbose, ctest_output, debug); + status_gui = testRunner("GUI tests", "GUI tests", subset_gui, timings, ctest_output, debug); if (run_simgear) - status_simgear = testRunner("Simgear unit tests", "Simgear unit tests", subset_simgear, verbose, ctest_output, debug); + status_simgear = testRunner("Simgear unit tests", "Simgear unit tests", subset_simgear, timings, ctest_output, debug); if (run_fgdata) - status_fgdata = testRunner("FGData tests", "FGData tests", subset_fgdata, verbose, ctest_output, debug); + status_fgdata = testRunner("FGData tests", "FGData tests", subset_fgdata, timings, ctest_output, debug); // Summary printout. if (printSummary && !ctest_output) From c5dd4d37155da2efeac3a33bec65b11267fa5d78 Mon Sep 17 00:00:00 2001 From: Edward d'Auvergne Date: Wed, 7 Aug 2019 11:21:42 +0200 Subject: [PATCH 6/7] 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 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 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; } From 4f5b0c82918afd2408143412a03e9ff7b7d2adb0 Mon Sep 17 00:00:00 2001 From: Edward d'Auvergne Date: Wed, 7 Aug 2019 11:24:02 +0200 Subject: [PATCH 7/7] TestSuite: Environmental variables support for controlling the test suite. This includes the addition of FG_TEST_LOG_LEVEL, FG_TEST_LOG_CLASS, FG_TEST_LOG_SPLIT, FG_TEST_TIMINGS, and FG_TEST_DEBUG. These match the command line option naming. --- test_suite/testSuite.cxx | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test_suite/testSuite.cxx b/test_suite/testSuite.cxx index d33bd3fc2..5ea9bbf75 100644 --- a/test_suite/testSuite.cxx +++ b/test_suite/testSuite.cxx @@ -71,6 +71,13 @@ void helpPrintout(std::ostream &stream) { stream << std::endl; stream << " FG options:" << std::endl; stream << " --fg-root the path to FGData" << std::endl; + stream << std::endl; + stream << "Environmental variables:" << std::endl; + stream << " FG_TEST_LOG_LEVEL equivalent to the --log-level option." << std::endl; + stream << " FG_TEST_LOG_CLASS equivalent to the --log-class option." << std::endl; + stream << " FG_TEST_LOG_SPLIT equivalent to the --log-split option." << std::endl; + stream << " FG_TEST_TIMINGS equivalent to the -t or --timings option." << std::endl; + stream << " FG_TEST_DEBUG equivalent to the -d or --debug option." << std::endl; stream.flush(); } @@ -274,6 +281,20 @@ int main(int argc, char **argv) sgDebugClass logClass=SG_ALL; sgDebugPriority logPriority=SG_INFO; + // Process environmental variables before the command line options. + if (getenv("FG_TEST_LOG_LEVEL")) + logPriority = processLogPriority(getenv("FG_TEST_LOG_LEVEL"), failure); + if (getenv("FG_TEST_LOG_CLASS")) + logClass = processLogClass(getenv("FG_TEST_LOG_CLASS"), failure); + if (getenv("FG_TEST_LOG_SPLIT")) + logSplit = true; + if (getenv("FG_TEST_TIMINGS")) + timings = true; + if (getenv("FG_TEST_DEBUG")) + debug = true; + if (failure) + return 1; + // Argument parsing. for (int i = 1; i < argc; i++) { firstchar = '\0';