diff --git a/cmake/_mutiny_discovery.cmake b/cmake/_mutiny_discovery.cmake index 03ecae498..12c311bfe 100644 --- a/cmake/_mutiny_discovery.cmake +++ b/cmake/_mutiny_discovery.cmake @@ -51,7 +51,7 @@ macro(add_test_to_script TEST_NAME TEST_LOCATION SELECT_ARG) endmacro() execute_process( - COMMAND ${EMULATOR} "${EXECUTABLE}" -ll + COMMAND ${EMULATOR} "${EXECUTABLE}" --list-locations OUTPUT_VARIABLE discovered_tests RESULT_VARIABLE result ERROR_VARIABLE error @@ -75,15 +75,15 @@ string(CONCAT LL_LINE_REGEX ) string(REGEX MATCHALL "[^\n]+\n" discovered_test_lines "${discovered_tests}") -# Query group declaration locations (-lgl). +# Query group declaration locations (--list-group-locations). execute_process( - COMMAND ${EMULATOR} "${EXECUTABLE}" -lgl + COMMAND ${EMULATOR} "${EXECUTABLE}" --list-group-locations OUTPUT_VARIABLE group_locations_output RESULT_VARIABLE lgl_result ERROR_VARIABLE _lgl_error ) if(NOT lgl_result EQUAL 0) - message(FATAL_ERROR "Error running ${EXECUTABLE} -lgl:\n${_lgl_error}") + message(FATAL_ERROR "Error running ${EXECUTABLE} --list-group-locations:\n${_lgl_error}") endif() string(CONCAT LGL_LINE_REGEX "^([^.]*)" # group name @@ -106,13 +106,13 @@ endforeach() if(TESTS_DETAILED) # Identify groups containing ordered tests. execute_process( - COMMAND ${EMULATOR} "${EXECUTABLE}" -lo + COMMAND ${EMULATOR} "${EXECUTABLE}" --list-ordered-locations OUTPUT_VARIABLE ordered_locations_output RESULT_VARIABLE lo_result ERROR_VARIABLE _lo_error ) if(NOT lo_result EQUAL 0) - message(FATAL_ERROR "Error running ${EXECUTABLE} -lo:\n${_lo_error}") + message(FATAL_ERROR "Error running ${EXECUTABLE} --list-ordered-locations:\n${_lo_error}") endif() set(ordered_groups) string(REGEX MATCHALL "[^\n]+\n" ordered_lines "${ordered_locations_output}") @@ -138,11 +138,11 @@ if(TESTS_DETAILED) set(group_location "${_group_loc_${group_name}_file}:${_group_loc_${group_name}_line}" ) - add_test_to_script("${group_name}" "${group_location}" -sg) + add_test_to_script("${group_name}" "${group_location}" --exact-group) endif() else() set(test_name "${group_name}.${CMAKE_MATCH_2}") - add_test_to_script("${test_name}" "${test_location}" -st) + add_test_to_script("${test_name}" "${test_location}" --exact-test) endif() endforeach() else() @@ -155,7 +155,7 @@ else() set(test_location "${_group_loc_${test_name}_file}:${_group_loc_${test_name}_line}" ) - add_test_to_script("${test_name}" "${test_location}" -sg) + add_test_to_script("${test_name}" "${test_location}" --exact-group) endforeach() endif() diff --git a/docs/command-line-reference.rst b/docs/command-line-reference.rst index c087f0905..58250fbf1 100644 --- a/docs/command-line-reference.rst +++ b/docs/command-line-reference.rst @@ -13,27 +13,31 @@ plugin-provided flags). Query Flags (do not run tests) ------------------------------- -.. option:: -h +.. option:: -h, --help Print help screen and exit. -.. option:: -lg +.. option:: --version + + Print the mutiny version string and exit. + +.. option:: --list-groups Print all group names, space-separated. -.. option:: -ln +.. option:: --list-tests Print all test names as ``group.name``, space-separated. -.. option:: -ll +.. option:: --list-locations Print test locations as ``group.name.file.line``. -.. option:: -lo +.. option:: --list-ordered-locations Print ordered test locations as ``group.name.file.line``. -.. option:: -lgl +.. option:: --list-group-locations Print group source locations as ``group.file.line``. Each entry points to the :c:macro:`TEST_GROUP` declaration rather than an individual test. @@ -41,15 +45,15 @@ Query Flags (do not run tests) Output Flags ------------ -.. option:: -c +.. option:: -c, --color Colorize output: green for pass, red for fail. -.. option:: -v +.. option:: -v, --verbose, --verbose=1 Verbose: print each test name as it runs. -.. option:: -vv +.. option:: -vv, --verbose=2 Very verbose: print internal framework state. @@ -83,62 +87,74 @@ Multiple filter flags can be combined; all must match for a test to run. Include filters (substring match by default) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. option:: -g +.. option:: -g , --group - Run tests whose group name *contains* ````. + Run tests whose group name *contains* ````. Also accepts + ``--group=``. -.. option:: -n +.. option:: -n , --name - Run tests whose test name *contains* ````. + Run tests whose test name *contains* ````. Also accepts + ``--name=``. -.. option:: -t . +.. option:: -t ., --test . Run tests whose group contains ```` **and** name contains ````. + Also accepts ``--test=.``. Include filters (exact match) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. option:: -sg +.. option:: --exact-group - Run tests whose group *exactly equals* ````. + Run tests whose group *exactly equals* ````. Also accepts + ``--exact-group=``. -.. option:: -sn +.. option:: --exact-name - Run tests whose test name *exactly equals* ````. + Run tests whose test name *exactly equals* ````. Also accepts + ``--exact-name=``. -.. option:: -st . +.. option:: --exact-test . - Run tests where both group and name exactly equal the given values. + Run tests where both group and name exactly equal the given values. Also + accepts ``--exact-test=.``. Exclude filters (substring match) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. option:: -xg +.. option:: --exclude-group - Exclude tests whose group contains ````. + Exclude tests whose group contains ````. Also accepts + ``--exclude-group=``. -.. option:: -xn +.. option:: --exclude-name - Exclude tests whose name contains ````. + Exclude tests whose name contains ````. Also accepts + ``--exclude-name=``. -.. option:: -xt . +.. option:: --exclude-test . Exclude tests whose group and name both contain the respective substrings. + Also accepts ``--exclude-test=.``. Exclude filters (exact match) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. option:: -xsg +.. option:: --exclude-exact-group - Exclude tests whose group exactly equals ````. + Exclude tests whose group exactly equals ````. Also accepts + ``--exclude-exact-group=``. -.. option:: -xsn +.. option:: --exclude-exact-name - Exclude tests whose name exactly equals ````. + Exclude tests whose name exactly equals ````. Also accepts + ``--exclude-exact-name=``. -.. option:: -xst . +.. option:: --exclude-exact-test . Exclude tests where both group and name exactly equal the given values. + Also accepts ``--exclude-exact-test=.``. Copy-paste filter ~~~~~~~~~~~~~~~~~ @@ -156,29 +172,30 @@ This performs an exact match on both group and name. Execution Flags --------------- -.. option:: -b +.. option:: -b, --reverse Run tests in reverse registration order. -.. option:: -s [seed] +.. option:: -s [seed], --shuffle [seed] Shuffle test execution order randomly. Optional ``seed`` (integer > 0) makes the order reproducible; if omitted, seed is time-based and - printed to console. + printed to console. Also accepts ``--shuffle=``. -.. option:: -r[#] +.. option:: -r[#], --repeat [#] Repeat the full test suite ``#`` times. If ``#`` is omitted, repeats - twice. Useful for detecting order-dependent failures. + twice. Useful for detecting order-dependent failures. Also accepts + ``--repeat=<#>``. -.. option:: -rs +.. option:: --run-skipped Run skipped tests (:c:macro:`SKIPPED_TEST`) as if they were normal tests. -.. option:: -f +.. option:: -f, --crash-on-fail Crash on first failure instead of continuing (useful with a debugger). -.. option:: -e +.. option:: -e, --no-rethrow Do not rethrow unexpected exceptions as failures (catch and continue). diff --git a/docs/test-macros.rst b/docs/test-macros.rst index 1bcf5fa7d..60654645c 100644 --- a/docs/test-macros.rst +++ b/docs/test-macros.rst @@ -47,13 +47,13 @@ Skipping and Expected Failures ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :c:macro:`SKIPPED_TEST` marks a test as skipped. It is registered but skipped during -normal runs. Use :option:`-rs` to run skipped tests anyway. +normal runs. Use :option:`--run-skipped` to run skipped tests anyway. .. code-block:: cpp SKIPPED_TEST(MyGroup, NotImplementedYet) { - // will not run unless -rs is passed + // will not run unless --run-skipped is passed CHECK(false); } @@ -117,12 +117,12 @@ tests by default. Listing Ordered Tests ~~~~~~~~~~~~~~~~~~~~~ -Pass :option:`-lo` to print each ordered test's location as +Pass :option:`--list-ordered-locations` to print each ordered test's location as ``group.name.file.line``: .. code-block:: console - $ ./my_tests -lo + $ ./my_tests --list-ordered-locations OrderedDemo.Init.examples/tests/OrderedTest.test.cpp.53 OrderedDemo.FirstEvent.examples/tests/OrderedTest.test.cpp.62 OrderedDemo.SecondEvent.examples/tests/OrderedTest.test.cpp.68 diff --git a/examples/tests/FEDemo.test.cpp b/examples/tests/FEDemo.test.cpp index 2124e51b1..343af883a 100644 --- a/examples/tests/FEDemo.test.cpp +++ b/examples/tests/FEDemo.test.cpp @@ -9,7 +9,7 @@ /* * To see a demonstration of tests failing as a result of * IEEE754ExceptionsPlugin picking up floating point errors, run the test - * executable with the -rs option. + * executable with the --run-skipped option. * */ diff --git a/include/mu/tiny/test/CommandLineArguments.hpp b/include/mu/tiny/test/CommandLineArguments.hpp index 252b2c5e6..00786c3f7 100644 --- a/include/mu/tiny/test/CommandLineArguments.hpp +++ b/include/mu/tiny/test/CommandLineArguments.hpp @@ -54,25 +54,29 @@ class MUTINY_EXPORT CommandLineArguments */ bool parse(Plugin* plugin); - /** @return true if `-h` was passed. */ + /** @return true if `-h` / `--help` was passed. */ bool need_help() const; - /** @return true if verbose output was requested (`-v`). */ + /** @return true if `--version` was passed. */ + bool need_version() const; + /** @return true if verbose output was requested (`-v` / `--verbose`). */ bool is_verbose() const; - /** @return true if very-verbose output was requested (`-vv`). */ + /** + * @return true if very-verbose output was requested (`-vv` / `--verbose=2`). + */ bool is_very_verbose() const; - /** @return true if coloured output was requested (`-c`). */ + /** @return true if coloured output was requested (`-c` / `--color`). */ bool is_color() const; - /** @return true if `-lg` (list group names) was passed. */ + /** @return true if `--list-groups` was passed. */ bool is_listing_test_group_names() const; - /** @return true if `-ln` (list group.case names) was passed. */ + /** @return true if `--list-tests` was passed. */ bool is_listing_test_group_and_case_names() const; - /** @return true if `-ll` (list test locations) was passed. */ + /** @return true if `--list-locations` was passed. */ bool is_listing_test_locations() const; - /** @return true if `-lo` (list ordered test locations) was passed. */ + /** @return true if `--list-ordered-locations` was passed. */ bool is_listing_ordered_test_locations() const; - /** @return true if `-lgl` (list group locations) was passed. */ + /** @return true if `--list-group-locations` was passed. */ bool is_listing_test_group_locations() const; - /** @return true if `-rs` (run skipped tests) was passed. */ + /** @return true if `--run-skipped` was passed. */ bool is_run_skipped() const; /** @return The number of times to repeat the full test suite (`-r N`). */ unsigned int get_repeat_count() const; @@ -80,9 +84,15 @@ class MUTINY_EXPORT CommandLineArguments bool is_shuffling() const; /** @return true if tests should run in reverse order (`-rv`). */ bool is_reversing() const; - /** @return true if the process should crash on first failure (`-p`). */ + /** + * @return true if the process should crash on first failure (`-f` / + * `--crash-on-fail`). + */ bool is_crashing_on_fail() const; - /** @return true if exceptions should be re-thrown after being caught. */ + /** + * @return true if exceptions should be re-thrown after being caught + * (`--no-rethrow` disables). + */ bool is_rethrowing_exceptions() const; /** @return The seed used when shuffling (0 means time-seeded). */ unsigned int get_shuffle_seed() const; @@ -92,12 +102,15 @@ class MUTINY_EXPORT CommandLineArguments const Filter* get_name_filters() const; /** @return A formatted help string describing all supported arguments. */ static String help(); + /** @return A version string suitable for `--version` output. */ + static String version_string(); private: int ac_; const char* const* av_; bool need_help_{ false }; + bool need_version_{ false }; bool verbose_{ false }; bool very_verbose_{ false }; bool color_{ false }; @@ -116,9 +129,17 @@ class MUTINY_EXPORT CommandLineArguments unsigned int shuffle_seed_{ 0 }; Filter* group_filters_{ nullptr }; Filter* name_filters_{ nullptr }; - int set_repeat_count(int argc, const char* const* argv); - int set_shuffle(int argc, const char* const* argv); - int add_group_filter(int argc, const char* const* argv); + int set_repeat_count( + int argc, + const char* const* argv, + const String& flag = "-r" + ); + int set_shuffle(int argc, const char* const* argv, const String& flag = "-s"); + int add_group_filter( + int argc, + const char* const* argv, + const String& flag = "-g" + ); int add_group_dot_name_filter( int argc, const char* const* argv, @@ -129,7 +150,11 @@ class MUTINY_EXPORT CommandLineArguments int add_strict_group_filter(int argc, const char* const* argv); int add_exclude_group_filter(int argc, const char* const* argv); int add_exclude_strict_group_filter(int argc, const char* const* argv); - int add_name_filter(int argc, const char* const* argv); + int add_name_filter( + int argc, + const char* const* argv, + const String& flag = "-n" + ); int add_strict_name_filter(int argc, const char* const* argv); int add_exclude_name_filter(int argc, const char* const* argv); int add_exclude_strict_name_filter(int argc, const char* const* argv); diff --git a/src/test/CommandLineArguments.cpp b/src/test/CommandLineArguments.cpp index b9cafbf55..b33f056d3 100644 --- a/src/test/CommandLineArguments.cpp +++ b/src/test/CommandLineArguments.cpp @@ -28,7 +28,11 @@ ParsedField get_parameter_field( size_t parameter_length = parameter_name.size(); String parameter(argv[0]); if (parameter.size() > parameter_length) { - ParsedField result = { String(argv[0] + parameter_length), 0 }; + size_t offset = parameter_length; + if (argv[0][offset] == '=') { + offset++; + } + ParsedField result = { String(argv[0] + offset), 0 }; return result; } if (argc > 1) { @@ -82,55 +86,60 @@ CommandLineArguments::~CommandLineArguments() bool CommandLineArguments::parse_simple_flag(const String& argument) { - if (argument == "-h") { + if ((argument == "-h") || (argument == "--help")) { need_help_ = true; return true; } - if (argument == "-v") { + if (argument == "--version") { + need_version_ = true; + return true; + } + if ((argument == "-v") || (argument == "--verbose") || + (argument == "--verbose=1")) { verbose_ = true; return true; } - if (argument == "-vv") { + if ((argument == "-vv") || (argument == "--verbose=2")) { very_verbose_ = true; return true; } - if (argument == "-c") { + if ((argument == "-c") || (argument == "--color")) { color_ = true; return true; } - if (argument == "-b") { + if ((argument == "-b") || (argument == "--reverse")) { reversing_ = true; return true; } - if (argument == "-lg") { + if (argument == "--list-groups") { list_test_group_names_ = true; return true; } - if (argument == "-ln") { + if (argument == "--list-tests") { list_test_group_and_case_names_ = true; return true; } - if (argument == "-lo") { + if (argument == "--list-ordered-locations") { list_ordered_test_locations_ = true; return true; } - if (argument == "-lgl") { + if (argument == "--list-group-locations") { list_test_group_locations_ = true; return true; } - if (argument == "-ll") { + if (argument == "--list-locations") { list_test_locations_ = true; return true; } - if (argument == "-rs") { + if (argument == "--run-skipped") { run_skipped_ = true; return true; } - if (argument == "-f") { + if ((argument == "-f") || (argument == "--crash-on-fail")) { crash_on_fail_ = true; return true; } - if (argument == "-e") { + if ((argument == "-e") || (argument == "--no-rethrow")) { rethrow_exceptions_ = false; return true; } @@ -144,44 +153,61 @@ int CommandLineArguments::parse_prefix_arg( ) { String argument(argv[0]); + if (string_starts_with(argument, "--repeat")) { + return set_repeat_count(argc, argv, "--repeat"); + } + if (string_starts_with(argument, "--shuffle")) { + return set_shuffle(argc, argv, "--shuffle"); + } if (string_starts_with(argument, "-r")) { return set_repeat_count(argc, argv); } - if (string_starts_with(argument, "-g")) { - return add_group_filter(argc, argv); + if (string_starts_with(argument, "--exact-group")) { + return add_strict_group_filter(argc, argv); } - if (string_starts_with(argument, "-t")) { - return add_group_dot_name_filter(argc, argv, "-t", false, false); + if (string_starts_with(argument, "--exclude-exact-group")) { + return add_exclude_strict_group_filter(argc, argv); } - if (string_starts_with(argument, "-st")) { - return add_group_dot_name_filter(argc, argv, "-st", true, false); + if (string_starts_with(argument, "--exclude-group")) { + return add_exclude_group_filter(argc, argv); } - if (string_starts_with(argument, "-xt")) { - return add_group_dot_name_filter(argc, argv, "-xt", false, true); + if (string_starts_with(argument, "--exact-name")) { + return add_strict_name_filter(argc, argv); } - if (string_starts_with(argument, "-xst")) { - return add_group_dot_name_filter(argc, argv, "-xst", true, true); + if (string_starts_with(argument, "--exclude-exact-name")) { + return add_exclude_strict_name_filter(argc, argv); } - if (string_starts_with(argument, "-sg")) { - return add_strict_group_filter(argc, argv); + if (string_starts_with(argument, "--exclude-name")) { + return add_exclude_name_filter(argc, argv); } - if (string_starts_with(argument, "-xg")) { - return add_exclude_group_filter(argc, argv); + if (string_starts_with(argument, "--exact-test")) { + return add_group_dot_name_filter(argc, argv, "--exact-test", true, false); } - if (string_starts_with(argument, "-xsg")) { - return add_exclude_strict_group_filter(argc, argv); + if (string_starts_with(argument, "--exclude-exact-test")) { + return add_group_dot_name_filter( + argc, argv, "--exclude-exact-test", true, true + ); } - if (string_starts_with(argument, "-n")) { - return add_name_filter(argc, argv); + if (string_starts_with(argument, "--exclude-test")) { + return add_group_dot_name_filter(argc, argv, "--exclude-test", false, true); } - if (string_starts_with(argument, "-sn")) { - return add_strict_name_filter(argc, argv); + if (string_starts_with(argument, "--group")) { + return add_group_filter(argc, argv, "--group"); } - if (string_starts_with(argument, "-xn")) { - return add_exclude_name_filter(argc, argv); + if (string_starts_with(argument, "--name")) { + return add_name_filter(argc, argv, "--name"); } - if (string_starts_with(argument, "-xsn")) { - return add_exclude_strict_name_filter(argc, argv); + if (string_starts_with(argument, "--test")) { + return add_group_dot_name_filter(argc, argv, "--test", false, false); + } + if (string_starts_with(argument, "-g")) { + return add_group_filter(argc, argv); + } + if (string_starts_with(argument, "-t")) { + return add_group_dot_name_filter(argc, argv, "-t", false, false); + } + if (string_starts_with(argument, "-n")) { + return add_name_filter(argc, argv); } if (string_starts_with(argument, "-s")) { return set_shuffle(argc, argv); @@ -227,56 +253,53 @@ String CommandLineArguments::help() String help_str = "mutiny v" MUTINY_VERSION_STRING "\n\n" "Options that do not run tests but query:\n" - " -h - this wonderful help screen. Joy!\n" - " -lg - print a list of group names, separated by " - "spaces\n" - " -ln - print a list of test names in the form of " - "group.name, separated by spaces\n" - " -ll - print a list of test names in the form of " - "group.name.test_file_path.line\n" - " -lo - print a list of ordered test names in the form " + " -h, --help - display this help and exit\n" + " --version - output version information and exit\n" + " --list-groups - print a list of group names, separated " + "by spaces\n" + " --list-tests - print a list of test names in the form " + "of group.name, separated by spaces\n" + " --list-locations - print a list of test names in the form " "of group.name.test_file_path.line\n" - " -lgl - print a list of group locations in the form of " - "group.file_path.line\n" + " --list-ordered-locations - print a list of ordered test names in " + "the form of group.name.test_file_path.line\n" + " --list-group-locations - print a list of group locations in the " + "form of group.file_path.line\n" "\n" "Options that change the output format:\n" - " -c - colorize output, print green if OK, or red if " - "failed\n" - " -v - verbose, print each test name as it runs\n" - " -vv - very verbose, print internal information " - "during test run\n"; - - Plugin* plugin = Registry::get_current_registry()->get_first_plugin(); - String plugin_help = plugin->get_all_help(); - - if (!plugin_help.empty()) { - help_str += "\nOptions that are provided by plugins:\n"; - help_str += plugin_help; - } - - help_str += + " -c, --color - colorize output, print green if OK, or " + "red if failed\n" + " -v, --verbose[=1] - verbose, print each test name as it " + "runs\n" + " -vv, --verbose=2 - very verbose, print internal information " + "during test run\n" "\n" "Options that control which tests are run:\n" - " -g - only run tests whose group contains \n" - " -n - only run tests whose name contains \n" - " -t . - only run tests whose group and name contain " - " and \n" - " -sg - only run tests whose group exactly matches " + " -g, --group - only run tests whose group contains " "\n" - " -sn - only run tests whose name exactly matches " + " -n, --name - only run tests whose name contains " "\n" - " -st . - only run tests whose group and name exactly " - "match and \n" - " -xg - exclude tests whose group contains \n" - " -xn - exclude tests whose name contains \n" - " -xt . - exclude tests whose group and name contain " - " and \n" - " -xsg - exclude tests whose group exactly matches " + " -t, --test . - only run tests whose group and name " + "contain and \n" + " --exact-group - only run tests whose group exactly " + "matches \n" + " --exact-name - only run tests whose name exactly " + "matches \n" + " --exact-test . - only run tests whose group and name " + "exactly match and \n" + " --exclude-group - exclude tests whose group contains " "\n" - " -xsn - exclude tests whose name exactly matches " + " --exclude-name - exclude tests whose name contains " "\n" - " -xst . - exclude tests whose group and name exactly " - "match and \n" + " --exclude-test . - exclude tests whose group and name " + "contain and \n" + " --exclude-exact-group - exclude tests whose group exactly " + "matches \n" + " --exclude-exact-name - exclude tests whose name exactly " + "matches \n" + " --exclude-exact-test .\n" + " - exclude tests whose group and name " + "exactly match and \n" " \"[SKIPPED_]TEST(, )\"\n" " - only run tests whose group and name exactly " "match and \n" @@ -284,18 +307,27 @@ String CommandLineArguments::help() "the -v option on the command line)\n" "\n" "Options that control how the tests are run:\n" - " -b - run the tests backwards, reversing the normal " - "way\n" - " -s [] - shuffle tests randomly (randomization seed is " - "optional, must be greater than 0)\n" - " -r[<#>] - repeat the tests <#> times (or twice if <#> is " - "not specified)\n" - " -rs - run skipped tests as if they are not skipped\n" - " -f - Cause the tests to crash on failure (to allow " - "the test to be debugged if necessary)\n" - " -e - do not rethrow unexpected exceptions on " + " -b, --reverse - run the tests backwards, reversing the " + "normal way\n" + " -s, --shuffle [] - shuffle tests randomly (randomization " + "seed is optional, must be greater than 0)\n" + " -r, --repeat [<#>] - repeat the tests <#> times (or twice " + "if <#> is not specified)\n" + " --run-skipped - run skipped tests as if they are not " + "skipped\n" + " -f, --crash-on-fail - Cause the tests to crash on failure " + "(to allow the test to be debugged if necessary)\n" + " -e, --no-rethrow - do not rethrow unexpected exceptions on " "failure\n"; + Plugin* plugin = Registry::get_current_registry()->get_first_plugin(); + String plugin_help = plugin->get_all_help(); + + if (!plugin_help.empty()) { + help_str += "\nOptions that are provided by plugins:\n"; + help_str += plugin_help; + } + return help_str; } @@ -304,6 +336,16 @@ bool CommandLineArguments::need_help() const return need_help_; } +bool CommandLineArguments::need_version() const +{ + return need_version_; +} + +String CommandLineArguments::version_string() +{ + return "mutiny v" MUTINY_VERSION_STRING "\n"; +} + bool CommandLineArguments::is_verbose() const { return verbose_; @@ -389,14 +431,23 @@ const Filter* CommandLineArguments::get_name_filters() const return name_filters_; } -int CommandLineArguments::set_repeat_count(int argc, const char* const* argv) +int CommandLineArguments::set_repeat_count( + int argc, + const char* const* argv, + const String& flag +) { repeat_ = 0; int extra = 0; + size_t flag_length = flag.size(); String repeat_parameter(argv[0]); - if (repeat_parameter.size() > 2) { - repeat_ = static_cast(strtoul(argv[0] + 2)); + if (repeat_parameter.size() > flag_length) { + size_t offset = flag_length; + if (argv[0][offset] == '=') { + offset++; + } + repeat_ = static_cast(strtoul(argv[0] + offset)); } else if (argc > 1) { repeat_ = static_cast(strtoul(argv[1])); if (repeat_ != 0) { @@ -410,7 +461,11 @@ int CommandLineArguments::set_repeat_count(int argc, const char* const* argv) return extra; } -int CommandLineArguments::set_shuffle(int argc, const char* const* argv) +int CommandLineArguments::set_shuffle( + int argc, + const char* const* argv, + const String& flag +) { shuffling_ = true; shuffle_seed_ = static_cast(get_time_in_millis()); @@ -419,10 +474,15 @@ int CommandLineArguments::set_shuffle(int argc, const char* const* argv) } int extra = 0; + size_t flag_length = flag.size(); String shuffle_parameter = argv[0]; - if (shuffle_parameter.size() > 2) { + if (shuffle_parameter.size() > flag_length) { shuffling_pre_seeded_ = true; - shuffle_seed_ = static_cast(strtoul(argv[0] + 2)); + size_t offset = flag_length; + if (argv[0][offset] == '=') { + offset++; + } + shuffle_seed_ = static_cast(strtoul(argv[0] + offset)); } else if (argc > 1) { auto parsed_parameter = static_cast(strtoul(argv[1])); if (parsed_parameter != 0) { @@ -434,9 +494,13 @@ int CommandLineArguments::set_shuffle(int argc, const char* const* argv) return (shuffle_seed_ != 0) ? extra : -1; } -int CommandLineArguments::add_group_filter(int argc, const char* const* argv) +int CommandLineArguments::add_group_filter( + int argc, + const char* const* argv, + const String& flag +) { - ParsedField field = get_parameter_field(argc, argv, "-g"); + ParsedField field = get_parameter_field(argc, argv, flag); auto* group_filter = new Filter(field.value); group_filters_ = group_filter->add(group_filters_); return field.extra; @@ -478,7 +542,7 @@ int CommandLineArguments::add_strict_group_filter( const char* const* argv ) { - ParsedField field = get_parameter_field(argc, argv, "-sg"); + ParsedField field = get_parameter_field(argc, argv, "--exact-group"); auto* group_filter = new Filter(field.value); group_filter->strict_matching(); group_filters_ = group_filter->add(group_filters_); @@ -490,7 +554,7 @@ int CommandLineArguments::add_exclude_group_filter( const char* const* argv ) { - ParsedField field = get_parameter_field(argc, argv, "-xg"); + ParsedField field = get_parameter_field(argc, argv, "--exclude-group"); auto* group_filter = new Filter(field.value); group_filter->invert_matching(); group_filters_ = group_filter->add(group_filters_); @@ -502,7 +566,7 @@ int CommandLineArguments::add_exclude_strict_group_filter( const char* const* argv ) { - ParsedField field = get_parameter_field(argc, argv, "-xsg"); + ParsedField field = get_parameter_field(argc, argv, "--exclude-exact-group"); auto* group_filter = new Filter(field.value); group_filter->strict_matching(); group_filter->invert_matching(); @@ -510,9 +574,13 @@ int CommandLineArguments::add_exclude_strict_group_filter( return field.extra; } -int CommandLineArguments::add_name_filter(int argc, const char* const* argv) +int CommandLineArguments::add_name_filter( + int argc, + const char* const* argv, + const String& flag +) { - ParsedField field = get_parameter_field(argc, argv, "-n"); + ParsedField field = get_parameter_field(argc, argv, flag); auto* name_filter = new Filter(field.value); name_filters_ = name_filter->add(name_filters_); return field.extra; @@ -523,7 +591,7 @@ int CommandLineArguments::add_strict_name_filter( const char* const* argv ) { - ParsedField field = get_parameter_field(argc, argv, "-sn"); + ParsedField field = get_parameter_field(argc, argv, "--exact-name"); auto* name_filter = new Filter(field.value); name_filter->strict_matching(); name_filters_ = name_filter->add(name_filters_); @@ -535,7 +603,7 @@ int CommandLineArguments::add_exclude_name_filter( const char* const* argv ) { - ParsedField field = get_parameter_field(argc, argv, "-xn"); + ParsedField field = get_parameter_field(argc, argv, "--exclude-name"); auto* name_filter = new Filter(field.value); name_filter->invert_matching(); name_filters_ = name_filter->add(name_filters_); @@ -547,7 +615,7 @@ int CommandLineArguments::add_exclude_strict_name_filter( const char* const* argv ) { - ParsedField field = get_parameter_field(argc, argv, "-xsn"); + ParsedField field = get_parameter_field(argc, argv, "--exclude-exact-name"); auto* name_filter = new Filter(field.value); name_filter->invert_matching(); name_filter->strict_matching(); diff --git a/src/test/CommandLineRunner.cpp b/src/test/CommandLineRunner.cpp index 8d14d2996..c41ea6891 100644 --- a/src/test/CommandLineRunner.cpp +++ b/src/test/CommandLineRunner.cpp @@ -77,7 +77,10 @@ int CommandLineRunner::run_all_tests_main() registry_->install_plugin(&tap_plugin); if (parse_arguments(registry_->get_first_plugin())) { - if (arguments_->need_help()) { + if (arguments_->need_version()) { + output_->print(CommandLineArguments::version_string().c_str()); + test_result = 0; + } else if (arguments_->need_help()) { output_->print(arguments_->help().c_str()); test_result = 0; } else { diff --git a/tests/cmake/discovery/Discovery/check.cmake b/tests/cmake/discovery/Discovery/check.cmake index 73d3bbb4d..4d0db9469 100644 --- a/tests/cmake/discovery/Discovery/check.cmake +++ b/tests/cmake/discovery/Discovery/check.cmake @@ -1,5 +1,5 @@ # Verify the generated CTest file for group-mode discovery (TESTS_DETAILED=OFF). -# Each group becomes a single add_test(-sg ) entry. +# Each group becomes a single add_test(--exact-group ) entry. set(generated_file "${RunCMake_BINARY_DIR}/Discovery-generated.cmake") if(NOT EXISTS "${generated_file}") @@ -10,11 +10,11 @@ endif() file(READ "${generated_file}" content) set(patterns - "add_test\\( MyTests\\.Group1 .* -sg Group1\\)" + "add_test\\( MyTests\\.Group1 .* --exact-group Group1\\)" "set_tests_properties\\( MyTests\\.Group1 PROPERTIES DEF_SOURCE_LINE file1\\.cpp:5\\)" - "add_test\\( MyTests\\.Group2 .* -sg Group2\\)" + "add_test\\( MyTests\\.Group2 .* --exact-group Group2\\)" "set_tests_properties\\( MyTests\\.Group2 PROPERTIES DEF_SOURCE_LINE file2\\.cpp:25\\)" - "add_test\\( MyTests\\.OrderedGroup .* -sg OrderedGroup\\)" + "add_test\\( MyTests\\.OrderedGroup .* --exact-group OrderedGroup\\)" "set_tests_properties\\( MyTests\\.OrderedGroup PROPERTIES DEF_SOURCE_LINE file3\\.cpp:35\\)" ) diff --git a/tests/cmake/discovery/DiscoveryDetailed/check.cmake b/tests/cmake/discovery/DiscoveryDetailed/check.cmake index 158fc6ac4..6fa982825 100644 --- a/tests/cmake/discovery/DiscoveryDetailed/check.cmake +++ b/tests/cmake/discovery/DiscoveryDetailed/check.cmake @@ -1,6 +1,6 @@ # Verify the generated CTest file for detailed-mode discovery (TESTS_DETAILED=ON). -# Non-ordered tests are registered individually with -st; ordered groups stay -# as a single -sg group entry. +# Non-ordered tests are registered individually with --exact-test; ordered +# groups stay as a single --exact-group entry. set(generated_file "${RunCMake_BINARY_DIR}/DiscoveryDetailed-generated.cmake") if(NOT EXISTS "${generated_file}") @@ -11,13 +11,13 @@ endif() file(READ "${generated_file}" content) set(patterns - "add_test\\( MyTests\\.Group1\\.Test1 .* -st Group1\\.Test1\\)" + "add_test\\( MyTests\\.Group1\\.Test1 .* --exact-test Group1\\.Test1\\)" "set_tests_properties\\( MyTests\\.Group1\\.Test1 PROPERTIES DEF_SOURCE_LINE file1\\.cpp:10\\)" - "add_test\\( MyTests\\.Group1\\.Test2 .* -st Group1\\.Test2\\)" + "add_test\\( MyTests\\.Group1\\.Test2 .* --exact-test Group1\\.Test2\\)" "set_tests_properties\\( MyTests\\.Group1\\.Test2 PROPERTIES DEF_SOURCE_LINE file1\\.cpp:20\\)" - "add_test\\( MyTests\\.Group2\\.Test3 .* -st Group2\\.Test3\\)" + "add_test\\( MyTests\\.Group2\\.Test3 .* --exact-test Group2\\.Test3\\)" "set_tests_properties\\( MyTests\\.Group2\\.Test3 PROPERTIES DEF_SOURCE_LINE file2\\.cpp:30\\)" - "add_test\\( MyTests\\.OrderedGroup .* -sg OrderedGroup\\)" + "add_test\\( MyTests\\.OrderedGroup .* --exact-group OrderedGroup\\)" "set_tests_properties\\( MyTests\\.OrderedGroup PROPERTIES DEF_SOURCE_LINE file3\\.cpp:35\\)" ) diff --git a/tests/cmake/discovery/DiscoveryJUnit/check.cmake b/tests/cmake/discovery/DiscoveryJUnit/check.cmake index ed246b33c..72c7e6484 100644 --- a/tests/cmake/discovery/DiscoveryJUnit/check.cmake +++ b/tests/cmake/discovery/DiscoveryJUnit/check.cmake @@ -9,9 +9,9 @@ endif() file(READ "${generated_file}" content) set(patterns - "add_test\\( MyTests\\.Group1 .* -pjunit -sg Group1\\)" - "add_test\\( MyTests\\.Group2 .* -pjunit -sg Group2\\)" - "add_test\\( MyTests\\.OrderedGroup .* -pjunit -sg OrderedGroup\\)" + "add_test\\( MyTests\\.Group1 .* -pjunit --exact-group Group1\\)" + "add_test\\( MyTests\\.Group2 .* -pjunit --exact-group Group2\\)" + "add_test\\( MyTests\\.OrderedGroup .* -pjunit --exact-group OrderedGroup\\)" ) foreach(p IN LISTS patterns) diff --git a/tests/cmake/discovery/mock_test_exe.cmake b/tests/cmake/discovery/mock_test_exe.cmake index f52aee91b..7cd19c2b0 100644 --- a/tests/cmake/discovery/mock_test_exe.cmake +++ b/tests/cmake/discovery/mock_test_exe.cmake @@ -1,19 +1,21 @@ # Fake mutiny test executable for use in discovery script tests. # -# When invoked as "cmake -P mock_test_exe.cmake -ll" it prints mock test -# location lines to stdout in the format expected by _mutiny_discovery.cmake: +# When invoked as "cmake -P mock_test_exe.cmake --list-locations" it prints +# mock test location lines to stdout in the format expected by +# _mutiny_discovery.cmake: # GROUP.NAME.FILE.LINE # -# When invoked with -lo it prints only the ordered-test group line. +# When invoked with --list-ordered-locations it prints only the ordered-test +# group line. set(mode "") math(EXPR last "${CMAKE_ARGC} - 1") foreach(i RANGE 0 "${last}") - if("${CMAKE_ARGV${i}}" STREQUAL "-ll") + if("${CMAKE_ARGV${i}}" STREQUAL "--list-locations") set(mode ll) - elseif("${CMAKE_ARGV${i}}" STREQUAL "-lo") + elseif("${CMAKE_ARGV${i}}" STREQUAL "--list-ordered-locations") set(mode lo) - elseif("${CMAKE_ARGV${i}}" STREQUAL "-lgl") + elseif("${CMAKE_ARGV${i}}" STREQUAL "--list-group-locations") set(mode lgl) endif() endforeach() @@ -30,5 +32,5 @@ elseif(mode STREQUAL "lgl") execute_process(COMMAND "${CMAKE_COMMAND}" -E echo "Group2.file2.cpp.25") execute_process(COMMAND "${CMAKE_COMMAND}" -E echo "OrderedGroup.file3.cpp.35") else() - message(FATAL_ERROR "Expected -ll, -lo, or -lgl flag") + message(FATAL_ERROR "Expected --list-locations, --list-ordered-locations, or --list-group-locations flag") endif() diff --git a/tests/src/CommandLineArguments.test.cpp b/tests/src/CommandLineArguments.test.cpp index 59f3e3b7b..013b677a9 100644 --- a/tests/src/CommandLineArguments.test.cpp +++ b/tests/src/CommandLineArguments.test.cpp @@ -4,6 +4,7 @@ #include "mu/tiny/String.hpp" #include "mu/tiny/test.hpp" +#include "mu/tiny/version.h" namespace { class OptionsPlugin : public mu::tiny::test::Plugin @@ -163,7 +164,7 @@ TEST(CommandLineArguments, shuffleEnabledSpecificSeedCase3) TEST(CommandLineArguments, shuffleBeforeDoesNotDisturbOtherSwitch) { int argc = 4; - const char* argv[] = { "tests.exe", "-s", "-sg", "group" }; + const char* argv[] = { "tests.exe", "-s", "--exact-group", "group" }; CHECK(new_argument_parser(argc, argv)); mu::tiny::test::Filter group_filter("group"); group_filter.strict_matching(); @@ -206,14 +207,14 @@ TEST(CommandLineArguments, setCompleteGroupDotNameFilter) TEST(CommandLineArguments, setCompleteStrictGroupDotNameFilterInvalidArgument) { int argc = 3; - const char* argv[] = { "tests.exe", "-st", "groupname" }; + const char* argv[] = { "tests.exe", "--exact-test", "groupname" }; CHECK(!new_argument_parser(argc, argv)); } TEST(CommandLineArguments, setCompleteStrictGroupDotNameFilter) { int argc = 3; - const char* argv[] = { "tests.exe", "-st", "group.name" }; + const char* argv[] = { "tests.exe", "--exact-test", "group.name" }; CHECK(new_argument_parser(argc, argv)); mu::tiny::test::Filter group_filter("group"); group_filter.strict_matching(); @@ -226,14 +227,14 @@ TEST(CommandLineArguments, setCompleteStrictGroupDotNameFilter) TEST(CommandLineArguments, setCompleteExcludeGroupDotNameFilterInvalidArgument) { int argc = 3; - const char* argv[] = { "tests.exe", "-xt", "groupname" }; + const char* argv[] = { "tests.exe", "--exclude-test", "groupname" }; CHECK(!new_argument_parser(argc, argv)); } TEST(CommandLineArguments, setCompleteExcludeGroupDotNameFilter) { int argc = 3; - const char* argv[] = { "tests.exe", "-xt", "group.name" }; + const char* argv[] = { "tests.exe", "--exclude-test", "group.name" }; CHECK(new_argument_parser(argc, argv)); mu::tiny::test::Filter group_filter("group"); group_filter.invert_matching(); @@ -246,14 +247,14 @@ TEST(CommandLineArguments, setCompleteExcludeGroupDotNameFilter) TEST(CommandLineArguments, setCompleteExcludeStrictGroupDotNameFilterInvalidArgument) { int argc = 3; - const char* argv[] = { "tests.exe", "-xst", "groupname" }; + const char* argv[] = { "tests.exe", "--exclude-exact-test", "groupname" }; CHECK(!new_argument_parser(argc, argv)); } TEST(CommandLineArguments, setCompleteExcludeStrictGroupDotNameFilter) { int argc = 3; - const char* argv[] = { "tests.exe", "-xst", "group.name" }; + const char* argv[] = { "tests.exe", "--exclude-exact-test", "group.name" }; CHECK(new_argument_parser(argc, argv)); mu::tiny::test::Filter group_filter("group"); group_filter.strict_matching(); @@ -276,17 +277,17 @@ TEST(CommandLineArguments, setGroupFilterSameParameter) TEST(CommandLineArguments, setStrictGroupFilter) { int argc = 3; - const char* argv[] = { "tests.exe", "-sg", "group" }; + const char* argv[] = { "tests.exe", "--exact-group", "group" }; CHECK(new_argument_parser(argc, argv)); mu::tiny::test::Filter group_filter("group"); group_filter.strict_matching(); CHECK_EQUAL(group_filter, *args->get_group_filters()); } -TEST(CommandLineArguments, setStrictGroupFilterSameParameter) +TEST(CommandLineArguments, setStrictGroupFilterEqualsSyntax) { int argc = 2; - const char* argv[] = { "tests.exe", "-sggroup" }; + const char* argv[] = { "tests.exe", "--exact-group=group" }; CHECK(new_argument_parser(argc, argv)); mu::tiny::test::Filter group_filter("group"); group_filter.strict_matching(); @@ -296,17 +297,17 @@ TEST(CommandLineArguments, setStrictGroupFilterSameParameter) TEST(CommandLineArguments, setExcludeGroupFilter) { int argc = 3; - const char* argv[] = { "tests.exe", "-xg", "group" }; + const char* argv[] = { "tests.exe", "--exclude-group", "group" }; CHECK(new_argument_parser(argc, argv)); mu::tiny::test::Filter group_filter("group"); group_filter.invert_matching(); CHECK_EQUAL(group_filter, *args->get_group_filters()); } -TEST(CommandLineArguments, setExcludeGroupFilterSameParameter) +TEST(CommandLineArguments, setExcludeGroupFilterEqualsSyntax) { int argc = 2; - const char* argv[] = { "tests.exe", "-xggroup" }; + const char* argv[] = { "tests.exe", "--exclude-group=group" }; CHECK(new_argument_parser(argc, argv)); mu::tiny::test::Filter group_filter("group"); group_filter.invert_matching(); @@ -316,7 +317,7 @@ TEST(CommandLineArguments, setExcludeGroupFilterSameParameter) TEST(CommandLineArguments, setExcludeStrictGroupFilter) { int argc = 3; - const char* argv[] = { "tests.exe", "-xsg", "group" }; + const char* argv[] = { "tests.exe", "--exclude-exact-group", "group" }; CHECK(new_argument_parser(argc, argv)); mu::tiny::test::Filter group_filter("group"); group_filter.invert_matching(); @@ -324,10 +325,10 @@ TEST(CommandLineArguments, setExcludeStrictGroupFilter) CHECK_EQUAL(group_filter, *args->get_group_filters()); } -TEST(CommandLineArguments, setExcludeStrictGroupFilterSameParameter) +TEST(CommandLineArguments, setExcludeStrictGroupFilterEqualsSyntax) { int argc = 2; - const char* argv[] = { "tests.exe", "-xsggroup" }; + const char* argv[] = { "tests.exe", "--exclude-exact-group=group" }; CHECK(new_argument_parser(argc, argv)); mu::tiny::test::Filter group_filter("group"); group_filter.invert_matching(); @@ -354,17 +355,17 @@ TEST(CommandLineArguments, setNameFilterSameParameter) TEST(CommandLineArguments, setStrictNameFilter) { int argc = 3; - const char* argv[] = { "tests.exe", "-sn", "name" }; + const char* argv[] = { "tests.exe", "--exact-name", "name" }; CHECK(new_argument_parser(argc, argv)); mu::tiny::test::Filter name_filter("name"); name_filter.strict_matching(); CHECK_EQUAL(name_filter, *args->get_name_filters()); } -TEST(CommandLineArguments, setStrictNameFilterSameParameter) +TEST(CommandLineArguments, setStrictNameFilterEqualsSyntax) { int argc = 2; - const char* argv[] = { "tests.exe", "-snname" }; + const char* argv[] = { "tests.exe", "--exact-name=name" }; CHECK(new_argument_parser(argc, argv)); mu::tiny::test::Filter name_filter("name"); name_filter.strict_matching(); @@ -374,17 +375,17 @@ TEST(CommandLineArguments, setStrictNameFilterSameParameter) TEST(CommandLineArguments, setExcludeNameFilter) { int argc = 3; - const char* argv[] = { "tests.exe", "-xn", "name" }; + const char* argv[] = { "tests.exe", "--exclude-name", "name" }; CHECK(new_argument_parser(argc, argv)); mu::tiny::test::Filter name_filter("name"); name_filter.invert_matching(); CHECK_EQUAL(name_filter, *args->get_name_filters()); } -TEST(CommandLineArguments, setExcludeNameFilterSameParameter) +TEST(CommandLineArguments, setExcludeNameFilterEqualsSyntax) { int argc = 2; - const char* argv[] = { "tests.exe", "-xnname" }; + const char* argv[] = { "tests.exe", "--exclude-name=name" }; CHECK(new_argument_parser(argc, argv)); mu::tiny::test::Filter name_filter("name"); name_filter.invert_matching(); @@ -394,7 +395,7 @@ TEST(CommandLineArguments, setExcludeNameFilterSameParameter) TEST(CommandLineArguments, setExcludeStrictNameFilter) { int argc = 3; - const char* argv[] = { "tests.exe", "-xsn", "name" }; + const char* argv[] = { "tests.exe", "--exclude-exact-name", "name" }; CHECK(new_argument_parser(argc, argv)); mu::tiny::test::Filter name_filter("name"); name_filter.invert_matching(); @@ -402,10 +403,10 @@ TEST(CommandLineArguments, setExcludeStrictNameFilter) CHECK_EQUAL(name_filter, *args->get_name_filters()); } -TEST(CommandLineArguments, setExcludeStrictNameFilterSameParameter) +TEST(CommandLineArguments, setExcludeStrictNameFilterEqualsSyntax) { int argc = 2; - const char* argv[] = { "tests.exe", "-xsnname" }; + const char* argv[] = { "tests.exe", "--exclude-exact-name=name" }; CHECK(new_argument_parser(argc, argv)); mu::tiny::test::Filter name_filter("name"); name_filter.invert_matching(); @@ -445,7 +446,7 @@ TEST(CommandLineArguments, setTestToRunUsingVerboseOutputOfIgnoreTest) TEST(CommandLineArguments, setPrintGroups) { int argc = 2; - const char* argv[] = { "tests.exe", "-lg" }; + const char* argv[] = { "tests.exe", "--list-groups" }; CHECK(new_argument_parser(argc, argv)); CHECK(args->is_listing_test_group_names()); } @@ -453,7 +454,7 @@ TEST(CommandLineArguments, setPrintGroups) TEST(CommandLineArguments, setPrintGroupsAndNames) { int argc = 2; - const char* argv[] = { "tests.exe", "-ln" }; + const char* argv[] = { "tests.exe", "--list-tests" }; CHECK(new_argument_parser(argc, argv)); CHECK(args->is_listing_test_group_and_case_names()); } @@ -461,7 +462,7 @@ TEST(CommandLineArguments, setPrintGroupsAndNames) TEST(CommandLineArguments, setPrintGroupLocations) { int argc = 2; - const char* argv[] = { "tests.exe", "-lgl" }; + const char* argv[] = { "tests.exe", "--list-group-locations" }; CHECK(new_argument_parser(argc, argv)); CHECK(args->is_listing_test_group_locations()); } @@ -521,9 +522,16 @@ TEST(CommandLineArguments, checkDefaultArguments) TEST(CommandLineArguments, lotsOfGroupsAndTests) { int argc = 10; - const char* argv[] = { "tests.exe", "-sggroup1", "-xntest1", "-sggroup2", - "-sntest2", "-sntest3", "-sggroup3", "-sntest4", - "-sggroup4", "-sntest5" }; + const char* argv[] = { "tests.exe", + "--exact-group=group1", + "--exclude-name=test1", + "--exact-group=group2", + "--exact-name=test2", + "--exact-name=test3", + "--exact-group=group3", + "--exact-name=test4", + "--exact-group=group4", + "--exact-name=test5" }; CHECK(new_argument_parser(argc, argv)); mu::tiny::test::Filter name_filter("test1"); name_filter.invert_matching(); @@ -542,7 +550,7 @@ TEST(CommandLineArguments, lotsOfGroupsAndTests) TEST(CommandLineArguments, setOptRun) { int argc = 2; - const char* argv[] = { "tests.exe", "-rs" }; + const char* argv[] = { "tests.exe", "--run-skipped" }; CHECK(new_argument_parser(argc, argv)); CHECK(args->is_run_skipped()); } @@ -569,3 +577,157 @@ TEST(CommandLineArguments, setOptRethrowExceptions) CHECK(new_argument_parser(argc, argv)); CHECK(!args->is_rethrowing_exceptions()); } + +// Long-form aliases for single-letter flags + +TEST(CommandLineArguments, longFormHelp) +{ + const char* argv[] = { "tests.exe", "--help" }; + CHECK(new_argument_parser(2, argv)); + CHECK(args->need_help()); +} + +TEST(CommandLineArguments, version) +{ + const char* argv[] = { "tests.exe", "--version" }; + CHECK(new_argument_parser(2, argv)); + CHECK(args->need_version()); +} + +TEST(CommandLineArguments, versionStringContainsVersion) +{ + CHECK( + mu::tiny::test::CommandLineArguments::version_string().find( + MUTINY_VERSION_STRING + ) != mu::tiny::String::npos + ); +} + +TEST(CommandLineArguments, longFormColor) +{ + const char* argv[] = { "tests.exe", "--color" }; + CHECK(new_argument_parser(2, argv)); + CHECK(args->is_color()); +} + +TEST(CommandLineArguments, longFormReverse) +{ + const char* argv[] = { "tests.exe", "--reverse" }; + CHECK(new_argument_parser(2, argv)); + CHECK(args->is_reversing()); +} + +TEST(CommandLineArguments, longFormCrashOnFail) +{ + const char* argv[] = { "tests.exe", "--crash-on-fail" }; + CHECK(new_argument_parser(2, argv)); + CHECK(args->is_crashing_on_fail()); +} + +TEST(CommandLineArguments, longFormNoRethrow) +{ + const char* argv[] = { "tests.exe", "--no-rethrow" }; + CHECK(new_argument_parser(2, argv)); + CHECK(!args->is_rethrowing_exceptions()); +} + +TEST(CommandLineArguments, longFormVerbose) +{ + const char* argv[] = { "tests.exe", "--verbose" }; + CHECK(new_argument_parser(2, argv)); + CHECK(args->is_verbose()); + CHECK(!args->is_very_verbose()); +} + +TEST(CommandLineArguments, longFormVerboseLevel1) +{ + const char* argv[] = { "tests.exe", "--verbose=1" }; + CHECK(new_argument_parser(2, argv)); + CHECK(args->is_verbose()); + CHECK(!args->is_very_verbose()); +} + +TEST(CommandLineArguments, longFormVerboseLevel2) +{ + const char* argv[] = { "tests.exe", "--verbose=2" }; + CHECK(new_argument_parser(2, argv)); + CHECK(args->is_very_verbose()); +} + +TEST(CommandLineArguments, longFormVerboseInvalidLevel) +{ + const char* argv[] = { "tests.exe", "--verbose=3" }; + CHECK(!new_argument_parser(2, argv)); +} + +TEST(CommandLineArguments, longFormGroup) +{ + const char* argv[] = { "tests.exe", "--group", "mygroup" }; + CHECK(new_argument_parser(3, argv)); + CHECK_EQUAL(mu::tiny::test::Filter("mygroup"), *args->get_group_filters()); +} + +TEST(CommandLineArguments, longFormGroupEqualsSyntax) +{ + const char* argv[] = { "tests.exe", "--group=mygroup" }; + CHECK(new_argument_parser(2, argv)); + CHECK_EQUAL(mu::tiny::test::Filter("mygroup"), *args->get_group_filters()); +} + +TEST(CommandLineArguments, longFormName) +{ + const char* argv[] = { "tests.exe", "--name", "mytest" }; + CHECK(new_argument_parser(3, argv)); + CHECK_EQUAL(mu::tiny::test::Filter("mytest"), *args->get_name_filters()); +} + +TEST(CommandLineArguments, longFormNameEqualsSyntax) +{ + const char* argv[] = { "tests.exe", "--name=mytest" }; + CHECK(new_argument_parser(2, argv)); + CHECK_EQUAL(mu::tiny::test::Filter("mytest"), *args->get_name_filters()); +} + +TEST(CommandLineArguments, longFormTest) +{ + const char* argv[] = { "tests.exe", "--test", "group.name" }; + CHECK(new_argument_parser(3, argv)); + CHECK_EQUAL(mu::tiny::test::Filter("group"), *args->get_group_filters()); + CHECK_EQUAL(mu::tiny::test::Filter("name"), *args->get_name_filters()); +} + +TEST(CommandLineArguments, longFormRepeat) +{ + const char* argv[] = { "tests.exe", "--repeat", "5" }; + CHECK(new_argument_parser(3, argv)); + CHECK_EQUAL(5U, args->get_repeat_count()); +} + +TEST(CommandLineArguments, longFormRepeatEqualsSyntax) +{ + const char* argv[] = { "tests.exe", "--repeat=5" }; + CHECK(new_argument_parser(2, argv)); + CHECK_EQUAL(5U, args->get_repeat_count()); +} + +TEST(CommandLineArguments, longFormRepeatDefaultsToTwo) +{ + const char* argv[] = { "tests.exe", "--repeat" }; + CHECK(new_argument_parser(2, argv)); + CHECK_EQUAL(2U, args->get_repeat_count()); +} + +TEST(CommandLineArguments, longFormShuffle) +{ + const char* argv[] = { "tests.exe", "--shuffle" }; + CHECK(new_argument_parser(2, argv)); + CHECK(args->is_shuffling()); +} + +TEST(CommandLineArguments, longFormShuffleWithSeed) +{ + const char* argv[] = { "tests.exe", "--shuffle=42" }; + CHECK(new_argument_parser(2, argv)); + CHECK(args->is_shuffling()); + CHECK_EQUAL(42U, args->get_shuffle_seed()); +} diff --git a/tests/src/CommandLineTestRunner.test.cpp b/tests/src/CommandLineTestRunner.test.cpp index 8fc43d2aa..1fc556061 100644 --- a/tests/src/CommandLineTestRunner.test.cpp +++ b/tests/src/CommandLineTestRunner.test.cpp @@ -4,6 +4,7 @@ #include "mu/tiny/test/StringBufferOutput.hpp" #include "mu/tiny/test.hpp" +#include "mu/tiny/version.h" namespace { class DummyPluginWhichCountsThePlugins : public mu::tiny::test::Plugin @@ -300,7 +301,7 @@ TEST(CommandLineRunner, testsCanBeRunInReverseOrder) TEST(CommandLineRunner, listTestGroupNamesShouldWorkProperly) { - const char* argv[] = { "tests.exe", "-lg" }; + const char* argv[] = { "tests.exe", "--list-groups" }; CommandLineTestRunnerWithStringBufferOutput command_line_test_runner( 2, argv, ®istry @@ -317,7 +318,7 @@ TEST(CommandLineRunner, listTestGroupNamesShouldWorkProperly) TEST(CommandLineRunner, listTestGroupAndCaseNamesShouldWorkProperly) { - const char* argv[] = { "tests.exe", "-ln" }; + const char* argv[] = { "tests.exe", "--list-tests" }; CommandLineTestRunnerWithStringBufferOutput command_line_test_runner( 2, argv, ®istry @@ -334,7 +335,7 @@ TEST(CommandLineRunner, listTestGroupAndCaseNamesShouldWorkProperly) TEST(CommandLineRunner, listTestLocationsShouldWorkProperly) { - const char* argv[] = { "tests.exe", "-ll" }; + const char* argv[] = { "tests.exe", "--list-locations" }; CommandLineTestRunnerWithStringBufferOutput command_line_test_runner( 2, argv, ®istry @@ -504,7 +505,7 @@ TEST(CommandLineRunner, SkippedTestWillBeSkippedIfNoOptionSpecified) TEST(CommandLineRunner, listOrderedTestLocations) { - const char* argv[] = { "tests.exe", "-lo" }; + const char* argv[] = { "tests.exe", "--list-ordered-locations" }; CommandLineTestRunnerWithStringBufferOutput command_line_test_runner( 2, argv, ®istry ); @@ -520,7 +521,7 @@ TEST(CommandLineRunner, SkippedTestWillGetRunIfOptionSpecified) "PluginCountingPlugin", &skipped_registry ); - const char* argv[] = { "tests.exe", "-rs" }; + const char* argv[] = { "tests.exe", "--run-skipped" }; CommandLineTestRunnerWithStringBufferOutput command_line_test_runner( 2, argv, &skipped_registry ); @@ -530,6 +531,28 @@ TEST(CommandLineRunner, SkippedTestWillGetRunIfOptionSpecified) RunSkippedTest::checker_ = false; } +TEST(CommandLineRunner, ReturnsZeroPrintsVersionOnVersion) +{ + const char* argv[] = { "tests.exe", "--version" }; + TestExecutionVerifierShell verifier_test; + registry.add_test(&verifier_test); + TestExecutionVerifier::was_run_ = false; + + CommandLineTestRunnerWithStringBufferOutput command_line_test_runner( + 2, argv, ®istry + ); + int returned = command_line_test_runner.run_all_tests_main(); + + CHECK_EQUAL(0, returned); + STRCMP_CONTAINS( + MUTINY_VERSION_STRING, + command_line_test_runner.fake_console_output_which_is_really_a_buffer + ->get_output() + .c_str() + ); + CHECK(!TestExecutionVerifier::was_run_); +} + TEST(CommandLineRunner, StaticInstallPluginAddsPluginToCurrentRegistry) { registry.set_current_registry(®istry);