From d63211409c29bdbc46c8428ebebf71cc0fe29759 Mon Sep 17 00:00:00 2001 From: Edward d'Auvergne Date: Sat, 10 Mar 2018 00:02:14 +0100 Subject: [PATCH] TestSuite: Addition of command line options for fine control of the executable. This includes the following help message detailing all of the new options: """ Usage: run_test_suite [options] Options: -h, --help show this help message and exit. Test selection options: -s, --system-tests execute the system/functional tests. -u, --unit-tests execute the unit tests. -g, --gui-tests execute the GUI tests. -m, --simgear-tests execute the simgear tests. The -s, -u, -g, and -m options accept an optional argument to perform a subset of all tests. This argument should either be the name of a test suite or the full name of an individual test. Full test names consist of the test suite name, the separator '::' and then the individual test name. The test names can revealed with the verbose option. Verbosity options: -v, --verbose verbose output including names and timings for all tests. """ --- test_suite/fgTestListener.cxx | 17 +++++ test_suite/fgTestListener.hxx | 5 +- test_suite/fgTestRunner.cxx | 8 ++- test_suite/fgTestRunner.hxx | 2 +- test_suite/testSuite.cxx | 127 ++++++++++++++++++++++++++++++---- 5 files changed, 140 insertions(+), 19 deletions(-) diff --git a/test_suite/fgTestListener.cxx b/test_suite/fgTestListener.cxx index d2671236d..c4148c57e 100644 --- a/test_suite/fgTestListener.cxx +++ b/test_suite/fgTestListener.cxx @@ -52,6 +52,23 @@ void fgTestListener::endTest(CppUnit::Test *test) cerr << (m_error ? "E" : "F"); else cerr << '.'; + + // Verbose output. + if (verbose) { + // Test timing. + float time = ((float)(clock()-m_time))/CLOCKS_PER_SEC; + char buffer[100]; + if (time > 60.0) + snprintf(buffer, sizeof(buffer), "%10.3f %-3s", time/60, "min"); + else if (time > 1.0) + snprintf(buffer, sizeof(buffer), "%10.3f %-3s", time, "s"); + else + snprintf(buffer, sizeof(buffer), "%10.3f %-3s", time*1000, "ms"); + cerr << buffer; + + // Test name. + cerr << " for " << test->getName() << endl; + } cerr.flush(); // Store the captured IO for any failed tests. diff --git a/test_suite/fgTestListener.hxx b/test_suite/fgTestListener.hxx index 2896937db..c6d8ea691 100644 --- a/test_suite/fgTestListener.hxx +++ b/test_suite/fgTestListener.hxx @@ -75,7 +75,10 @@ class fgTestListener : public CppUnit::TestListener // IO capture for all failed tests. std::vector io_capt; - private: + // Output settings. + bool verbose; + + protected: // The original IO streams. std::streambuf *orig_cerr, *orig_cout; diff --git a/test_suite/fgTestRunner.cxx b/test_suite/fgTestRunner.cxx index 9f0f0c9d2..f4c811ac6 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) +int testRunner(const std::string& title, char *subset, bool verbose) { // Declarations. CppUnit::TextTestRunner runner; @@ -44,12 +44,16 @@ int testRunner(const std::string& title) fgTestListener *testListener; testListener = new fgTestListener; runner.eventManager().addListener(testListener); + testListener->verbose = verbose; // Set the test suite output IO stream. runner.setOutputter(new fgCompilerOutputter(&runner.result(), &testListener->io_capt, &testListener->sum_time, std::cerr)); // Execute the tests. - runner.run("", false, true, false); + if (subset == NULL) + runner.run("", false, true, false); + else + runner.run(subset, false, true, false); // Clean up. delete testListener; diff --git a/test_suite/fgTestRunner.hxx b/test_suite/fgTestRunner.hxx index e9bf495a4..ff46a0a7d 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&); +int testRunner(const std::string&, char*, bool); #endif // _FG_TEST_RUNNER_HXX diff --git a/test_suite/testSuite.cxx b/test_suite/testSuite.cxx index f3b9f13aa..064cd9c82 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 "fgTestRunner.hxx" @@ -29,6 +30,8 @@ using namespace std; // 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 synopsis = 0; + // Title. string text = "Summary of the FlightGear test suite"; printTitle(stream, text); @@ -38,24 +41,35 @@ void summary(CppUnit::OStream &stream, int system_result, int unit_result, int g printSection(stream, text); // System/functional test summary. - text = "System/functional tests"; - printSummaryLine(stream, text, system_result); + if (system_result != -1) { + text = "System/functional tests"; + printSummaryLine(stream, text, system_result); + synopsis += system_result; + } // Unit test summary. - text = "Unit tests"; - printSummaryLine(stream, text, unit_result); + if (unit_result != -1) { + text = "Unit tests"; + printSummaryLine(stream, text, unit_result); + synopsis += unit_result; + } // GUI test summary. - text = "GUI tests"; - printSummaryLine(stream, text, gui_result); + if (gui_result != -1) { + text = "GUI tests"; + printSummaryLine(stream, text, gui_result); + synopsis += gui_result; + } // Simgear unit test summary. - text = "Simgear unit tests"; - printSummaryLine(stream, text, simgear_result); + if (simgear_result != -1) { + text = "Simgear unit tests"; + printSummaryLine(stream, text, simgear_result); + synopsis += simgear_result; + } // Synopsis. text ="Synopsis"; - int synopsis = system_result + unit_result + gui_result + simgear_result; printSummaryLine(stream, text, synopsis); // End. @@ -63,20 +77,103 @@ void summary(CppUnit::OStream &stream, int system_result, int unit_result, int g } -int main(void) +int main(int argc, char **argv) { // Declarations. - int status_gui, status_simgear, status_system, status_unit; + 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, help=false; + char *subset_system=NULL, *subset_unit=NULL, *subset_gui=NULL, *subset_simgear=NULL; + char firstchar; + + // Argument parsing. + for (int i = 1; i < argc; i++) { + firstchar = '\0'; + if (i < argc-1) + firstchar = argv[i+1][0]; + + // System test. + if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--system-tests") == 0) { + 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) { + 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) { + 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) { + run_simgear = true; + if (firstchar != '-') + subset_simgear = argv[i+1]; + + // Verbose output. + } else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) { + verbose = true; + + // Help. + } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { + help = true; + } + } + + // 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 << 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 << " Verbosity options:" << std::endl; + std::cout << " -v, --verbose verbose output including names and timings for all" << std::endl; + std::cout << " tests." << std::endl; + std::cout.flush(); + return 0; + } + + // Turn on all tests if no subset was specified. + if (!run_system && !run_unit && !run_gui && !run_simgear) { + run_system = true; + run_unit = true; + run_gui = true; + run_simgear = true; + } // Set up logging. sglog().setDeveloperMode(true); setupLogging(); // Execute each of the test suite categories. - status_system = testRunner("System tests"); - status_unit = testRunner("Unit tests"); - status_gui = testRunner("GUI tests"); - status_simgear = testRunner("Simgear unit tests"); + if (run_system) + status_system = testRunner("System tests", subset_system, verbose); + if (run_unit) + status_unit = testRunner("Unit tests", subset_unit, verbose); + if (run_gui) + status_gui = testRunner("GUI tests", subset_gui, verbose); + if (run_simgear) + status_simgear = testRunner("Simgear unit tests", subset_simgear, verbose); // Summary printout. summary(cerr, status_system, status_unit, status_gui, status_simgear);