diff --git a/test/options.cpp b/test/options.cpp index 2c1d78d68..76f181515 100644 --- a/test/options.cpp +++ b/test/options.cpp @@ -19,16 +19,19 @@ #include options::options(int argc, const char* const argv[]) - :mOptions(argv + 1, argv + argc) - ,mWhichTest("") - ,mQuiet(mOptions.count("-q") != 0) - ,mHelp(mOptions.count("-h") != 0 || mOptions.count("--help")) + :mWhichTests(argv + 1, argv + argc) + ,mQuiet(mWhichTests.count("-q") != 0) + ,mHelp(mWhichTests.count("-h") != 0 || mWhichTests.count("--help")) { - mOptions.erase("-q"); - mOptions.erase("-h"); - mOptions.erase("--help"); - if (! mOptions.empty()) { - mWhichTest = *mOptions.rbegin(); + for (std::set::const_iterator it = mWhichTests.begin(); it != mWhichTests.end();) { + if (!(*it).empty() && (((*it)[0] == '-') || ((*it).find("::") != std::string::npos && mWhichTests.count((*it).substr(0, (*it).find("::")))))) + it = mWhichTests.erase(it); + else + ++it; + } + + if (mWhichTests.empty()) { + mWhichTests.insert(""); } } @@ -42,7 +45,7 @@ bool options::help() const return mHelp; } -const std::string& options::which_test() const +const std::set& options::which_test() const { - return mWhichTest; + return mWhichTests; } diff --git a/test/options.h b/test/options.h index ff2d2fa63..5871aa18f 100644 --- a/test/options.h +++ b/test/options.h @@ -34,7 +34,7 @@ public: /** Print help. */ bool help() const; /** Which test should be run. Empty string means 'all tests' */ - const std::string& which_test() const; + const std::set& which_test() const; private: options(); @@ -42,8 +42,7 @@ private: const options& operator =(const options& non_assign); private: - std::set mOptions; - std::string mWhichTest; + std::set mWhichTests; const bool mQuiet; const bool mHelp; }; diff --git a/test/testoptions.cpp b/test/testoptions.cpp index d73735820..0e6001b4c 100644 --- a/test/testoptions.cpp +++ b/test/testoptions.cpp @@ -36,6 +36,7 @@ private: TEST_CASE(help); TEST_CASE(help_long); TEST_CASE(multiple_testcases); + TEST_CASE(multiple_testcases_ignore_duplicates); TEST_CASE(invalid_switches); } @@ -43,21 +44,21 @@ private: void which_test() const { const char* argv[] = {"./test_runner", "TestClass"}; options args(sizeof argv / sizeof argv[0], argv); - ASSERT_EQUALS("TestClass", args.which_test()); + ASSERT(std::set {"TestClass"} == args.which_test()); } void which_test_method() const { const char* argv[] = {"./test_runner", "TestClass::TestMethod"}; options args(sizeof argv / sizeof argv[0], argv); - ASSERT_EQUALS("TestClass::TestMethod", args.which_test()); + ASSERT(std::set {"TestClass::TestMethod"} == args.which_test()); } void no_test_method() const { const char* argv[] = {"./test_runner"}; options args(sizeof argv / sizeof argv[0], argv); - ASSERT_EQUALS("", args.which_test()); + ASSERT(std::set {""} == args.which_test()); } @@ -95,16 +96,24 @@ private: } void multiple_testcases() const { - const char* argv[] = {"./test_runner", "TestClass::TestMethod", "Ignore::ThisOne"}; + const char* argv[] = {"./test_runner", "TestClass::TestMethod", "TestClass::AnotherTestMethod"}; options args(sizeof argv / sizeof argv[0], argv); - ASSERT_EQUALS("TestClass::TestMethod", args.which_test()); + std::set expected {"TestClass::TestMethod", "TestClass::AnotherTestMethod"}; + ASSERT(expected == args.which_test()); } + void multiple_testcases_ignore_duplicates() const { + const char* argv[] = {"./test_runner", "TestClass::TestMethod", "TestClass"}; + options args(sizeof argv / sizeof argv[0], argv); + std::set expected {"TestClass"}; + ASSERT(expected == args.which_test()); + } void invalid_switches() const { const char* argv[] = {"./test_runner", "TestClass::TestMethod", "-a", "-v", "-q"}; options args(sizeof argv / sizeof argv[0], argv); - ASSERT_EQUALS("TestClass::TestMethod", args.which_test()); + std::set expected {"TestClass::TestMethod"}; + ASSERT(expected == args.which_test()); ASSERT_EQUALS(true, args.quiet()); } }; diff --git a/test/testsuite.cpp b/test/testsuite.cpp index f398f0a20..167ced325 100644 --- a/test/testsuite.cpp +++ b/test/testsuite.cpp @@ -280,13 +280,15 @@ void TestFixture::printHelp() std::cout << "Testrunner - run Cppcheck tests\n" "\n" "Syntax:\n" - " testrunner [OPTIONS] [TestClass::TestCase]\n" + " testrunner [OPTIONS] [TestClass::TestCase...]\n" " run all test cases:\n" " testrunner\n" " run all test cases in TestClass:\n" " testrunner TestClass\n" " run TestClass::TestCase:\n" " testrunner TestClass::TestCase\n" + " run all test cases in TestClass1 and TestClass2::TestCase:\n" + " testrunner TestClass1 TestClass2::TestCase\n" "\n" "Options:\n" " -q Do not print the test cases that have run.\n" @@ -311,22 +313,24 @@ void TestFixture::processOptions(const options& args) std::size_t TestFixture::runTests(const options& args) { - std::string classname(args.which_test()); - std::string testname; - if (classname.find("::") != std::string::npos) { - testname = classname.substr(classname.find("::") + 2); - classname.erase(classname.find("::")); - } - countTests = 0; errmsg.str(""); - const TestSet &tests = TestRegistry::theInstance().tests(); + const std::set& tests = args.which_test(); + for (std::string classname : tests) { + std::string testname; + if (classname.find("::") != std::string::npos) { + testname = classname.substr(classname.find("::") + 2); + classname.erase(classname.find("::")); + } - for (TestFixture * test : tests) { - if (classname.empty() || test->classname == classname) { - test->processOptions(args); - test->run(testname); + const TestSet &tests = TestRegistry::theInstance().tests(); + + for (TestFixture * test : tests) { + if (classname.empty() || test->classname == classname) { + test->processOptions(args); + test->run(testname); + } } }