From 0030f655e023d82d3e2905ed5fa66df5c9bab8b3 Mon Sep 17 00:00:00 2001 From: Edward d'Auvergne Date: Mon, 12 Mar 2018 16:43:24 +0100 Subject: [PATCH] TestSuite: Added a debugging command line option. This is to enable full output from passing tests to help with debugging. --- test_suite/fgCompilerOutputter.cxx | 4 +++ test_suite/fgCompilerOutputter.hxx | 3 ++ test_suite/fgTestListener.cxx | 52 +++++++++++++++++++----------- test_suite/fgTestListener.hxx | 3 ++ test_suite/fgTestRunner.cxx | 5 +-- test_suite/fgTestRunner.hxx | 2 +- test_suite/testSuite.cxx | 23 +++++++++---- 7 files changed, 63 insertions(+), 29 deletions(-) diff --git a/test_suite/fgCompilerOutputter.cxx b/test_suite/fgCompilerOutputter.cxx index 7f8e4b56e..1c68da69f 100644 --- a/test_suite/fgCompilerOutputter.cxx +++ b/test_suite/fgCompilerOutputter.cxx @@ -54,6 +54,10 @@ void fgCompilerOutputter::printFailureDetail(CppUnit::TestFailure *failure) fg_stream << (failure->isError() ? "Error" : "Assertion") << ": "; printFailureLocation(failure->sourceLine()); printFailureMessage(failure); + fg_stream.flush(); + + if (debug) + return; // The captured IO for this test. test_iter = find_if(io_capt->begin(), io_capt->end(), matchTestName(failure->failedTestName())); diff --git a/test_suite/fgCompilerOutputter.hxx b/test_suite/fgCompilerOutputter.hxx index 3669d0407..5fd1f0d9b 100644 --- a/test_suite/fgCompilerOutputter.hxx +++ b/test_suite/fgCompilerOutputter.hxx @@ -38,6 +38,7 @@ class fgCompilerOutputter : public CppUnit::CompilerOutputter const clock_t *clock, CppUnit::OStream &stream, bool ctest = false, + bool debug = false, const std::string &locationFormat = CPPUNIT_COMPILER_LOCATION_FORMAT) : CppUnit::CompilerOutputter(result, stream, locationFormat) , io_capt(capt) @@ -45,6 +46,7 @@ class fgCompilerOutputter : public CppUnit::CompilerOutputter , fg_stream(stream) , suite_timer(clock) , ctest_output(ctest) + , debug(debug) { } @@ -76,6 +78,7 @@ class fgCompilerOutputter : public CppUnit::CompilerOutputter // Output control. bool ctest_output; + bool debug; // Simgear logstream IO printout. void printIOStreamMessages(const char *heading, std::string messages, bool empty); diff --git a/test_suite/fgTestListener.cxx b/test_suite/fgTestListener.cxx index 2a4696fc7..3803bae7b 100644 --- a/test_suite/fgTestListener.cxx +++ b/test_suite/fgTestListener.cxx @@ -44,8 +44,14 @@ void fgTestListener::endTest(CppUnit::Test *test) sum_time += clock() - m_time; // Restore the IO streams. - cout.rdbuf(orig_cout); - cerr.rdbuf(orig_cerr); + if (!debug) { + cout.rdbuf(orig_cout); + cerr.rdbuf(orig_cerr); + } + + // Debugging output. + if (debug) + cerr << string(WIDTH_DIVIDER, '-') << endl; // Per-test single character status feedback. if (m_failure) @@ -54,7 +60,7 @@ void fgTestListener::endTest(CppUnit::Test *test) cerr << '.'; // Verbose output. - if (verbose || ctest_output) { + if (verbose || ctest_output || debug) { // Test timing. float time = ((float)(clock()-m_time))/CLOCKS_PER_SEC; char buffer[100]; @@ -72,7 +78,7 @@ void fgTestListener::endTest(CppUnit::Test *test) cerr.flush(); // Store the captured IO for any failed tests. - if (m_failure) { + if (m_failure && !debug) { // Set up the data structure. TestIOCapt test_io; test_io.name = test->getName(); @@ -98,24 +104,32 @@ void fgTestListener::endTest(CppUnit::Test *test) // Override the base class function to capture IO streams. void fgTestListener::startTest(CppUnit::Test *test) { - // Clear the simgear logstream buffers. - capturedIO &obj = getIOstreams(); - obj.sg_bulk.str(""); - obj.sg_bulk_only.str(""); - obj.sg_debug_only.str(""); - obj.sg_info_only.str(""); - obj.sg_warn_only.str(""); - obj.sg_alert_only.str(""); + // IO capture. + if (!debug) { + // Clear the simgear logstream buffers. + capturedIO &obj = getIOstreams(); + obj.sg_bulk.str(""); + obj.sg_bulk_only.str(""); + obj.sg_debug_only.str(""); + obj.sg_info_only.str(""); + obj.sg_warn_only.str(""); + obj.sg_alert_only.str(""); - // Store the original STDOUT and STDERR for restoring later on. - orig_cout = cout.rdbuf(); - orig_cerr = cerr.rdbuf(); + // Store the original STDOUT and STDERR for restoring later on. + orig_cout = cout.rdbuf(); + orig_cerr = cerr.rdbuf(); - // Clear the captured stream and then catch stdout and stderr. - capt.str(string()); - cout.rdbuf(capt.rdbuf()); - cerr.rdbuf(capt.rdbuf()); + // Clear the captured stream and then catch stdout and stderr. + capt.str(string()); + cout.rdbuf(capt.rdbuf()); + cerr.rdbuf(capt.rdbuf()); + // Debugging output. + } else { + cerr << string(WIDTH_DIVIDER, '=') << endl; + cerr << "Starting test: " << test->getName() << endl; + cerr << string(WIDTH_DIVIDER, '-') << endl; + } // Reset the test status. m_failure = false; m_error = false; diff --git a/test_suite/fgTestListener.hxx b/test_suite/fgTestListener.hxx index a05395fb4..30906fbbc 100644 --- a/test_suite/fgTestListener.hxx +++ b/test_suite/fgTestListener.hxx @@ -25,6 +25,8 @@ #include #include +#include "formatting.hxx" + // Data structure for holding the captured IO for a failed test. struct TestIOCapt { @@ -78,6 +80,7 @@ class fgTestListener : public CppUnit::TestListener // Output settings. bool verbose; bool ctest_output; + bool debug; protected: // The original IO streams. diff --git a/test_suite/fgTestRunner.cxx b/test_suite/fgTestRunner.cxx index ed14862f0..7365dbe31 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& title, char *subset, bool verbose, bool ctest_output) +int testRunner(const std::string& title, char *subset, bool verbose, bool ctest_output, bool debug) { // Declarations. CppUnit::TextTestRunner runner; @@ -47,9 +47,10 @@ int testRunner(const std::string& title, char *subset, bool verbose, bool ctest_ runner.eventManager().addListener(testListener); testListener->verbose = verbose; testListener->ctest_output = ctest_output; + testListener->debug = debug; // Set the test suite output IO stream. - runner.setOutputter(new fgCompilerOutputter(&runner.result(), &testListener->io_capt, &testListener->sum_time, std::cerr, ctest_output)); + runner.setOutputter(new fgCompilerOutputter(&runner.result(), &testListener->io_capt, &testListener->sum_time, std::cerr, ctest_output, debug)); // Execute the tests. if (subset == NULL) diff --git a/test_suite/fgTestRunner.hxx b/test_suite/fgTestRunner.hxx index 4a0660d0b..defbf4d7a 100644 --- a/test_suite/fgTestRunner.hxx +++ b/test_suite/fgTestRunner.hxx @@ -23,7 +23,7 @@ // Execute all test suites for the given test category. -int testRunner(const std::string&, char*, bool, bool); +int testRunner(const std::string&, char*, bool, bool, bool); #endif // _FG_TEST_RUNNER_HXX diff --git a/test_suite/testSuite.cxx b/test_suite/testSuite.cxx index dd3ce290a..03fd1aea5 100644 --- a/test_suite/testSuite.cxx +++ b/test_suite/testSuite.cxx @@ -82,7 +82,7 @@ int main(int argc, char **argv) // Declarations. int status_gui=-1, status_simgear=-1, status_system=-1, status_unit=-1; bool run_system=false, run_unit=false, run_gui=false, run_simgear=false; - bool verbose=false, ctest_output=false, help=false; + bool verbose=false, ctest_output=false, debug=false, help=false; char *subset_system=NULL, *subset_unit=NULL, *subset_gui=NULL, *subset_simgear=NULL; char firstchar; @@ -124,6 +124,10 @@ int main(int argc, char **argv) } else if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--ctest") == 0) { ctest_output = true; + // Debug output. + } else if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--debug") == 0) { + debug = true; + // Help. } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { help = true; @@ -154,6 +158,7 @@ int main(int argc, char **argv) std::cout << " -v, --verbose 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.flush(); return 0; } @@ -168,24 +173,28 @@ int main(int argc, char **argv) // Set up logging. sglog().setDeveloperMode(true); - setupLogging(); + if (debug) + sglog().setLogLevels(SG_ALL, SG_BULK); + else + setupLogging(); // Execute each of the test suite categories. if (run_system) - status_system = testRunner("System tests", subset_system, verbose, ctest_output); + status_system = testRunner("System tests", subset_system, verbose, ctest_output, debug); if (run_unit) - status_unit = testRunner("Unit tests", subset_unit, verbose, ctest_output); + status_unit = testRunner("Unit tests", subset_unit, verbose, ctest_output, debug); if (run_gui) - status_gui = testRunner("GUI tests", subset_gui, verbose, ctest_output); + status_gui = testRunner("GUI tests", subset_gui, verbose, ctest_output, debug); if (run_simgear) - status_simgear = testRunner("Simgear unit tests", subset_simgear, verbose, ctest_output); + status_simgear = testRunner("Simgear unit tests", subset_simgear, verbose, ctest_output, debug); // Summary printout. if (!ctest_output) summary(cerr, status_system, status_unit, status_gui, status_simgear); // Deactivate the logging. - stopLogging(); + if (!debug) + stopLogging(); // Failure. if (status_system > 0)