#ifdef WITH_MODULE import argparse; #else #include #endif #include #include #include #include using doctest::test_suite; TEST_CASE("Add subparsers" * test_suite("subparsers")) { argparse::ArgumentParser program("test"); program.add_argument("--output"); argparse::ArgumentParser command_1("add"); command_1.add_argument("file").nargs(2); argparse::ArgumentParser command_2("clean"); program.add_subparser(command_1); program.add_subparser(command_2); program.parse_args({"test", "--output", "thrust_profile.csv"}); REQUIRE(program.is_subcommand_used("add") == false); REQUIRE(program.get("--output") == "thrust_profile.csv"); } TEST_CASE("Parse subparser command" * test_suite("subparsers")) { argparse::ArgumentParser program("test"); program.add_argument("--output"); argparse::ArgumentParser command_1("add"); command_1.add_argument("file").nargs(2); argparse::ArgumentParser command_2("clean"); command_2.add_argument("--fullclean") .default_value(false) .implicit_value(true); program.add_subparser(command_1); program.add_subparser(command_2); SUBCASE("command 1") { program.parse_args({"test", "add", "file1.txt", "file2.txt"}); REQUIRE(program.is_subcommand_used("add") == true); REQUIRE(command_1.is_used("file")); REQUIRE((command_1.get>("file") == std::vector{"file1.txt", "file2.txt"})); } SUBCASE("command 2") { program.parse_args({"test", "clean", "--fullclean"}); REQUIRE(program.is_subcommand_used("clean") == true); REQUIRE(command_2.get("--fullclean") == true); } } TEST_CASE("Parse subparser command with optional argument" * test_suite("subparsers")) { argparse::ArgumentParser program("test"); program.add_argument("--verbose").flag(); argparse::ArgumentParser command_1("add"); command_1.add_argument("file"); argparse::ArgumentParser command_2("clean"); command_2.add_argument("--fullclean") .default_value(false) .implicit_value(true); program.add_subparser(command_1); program.add_subparser(command_2); SUBCASE("Optional argument BEFORE subcommand") { program.parse_args({"test", "--verbose", "clean", "--fullclean"}); REQUIRE(program.is_subcommand_used("clean") == true); REQUIRE(program.get("--verbose") == true); REQUIRE(command_2.get("--fullclean") == true); } SUBCASE("Optional argument AFTER subcommand") { REQUIRE_THROWS_WITH_AS( program.parse_args({"test", "clean", "--fullclean", "--verbose"}), "Unknown argument: --verbose", std::runtime_error); } } TEST_CASE("Parse subparser command with parent parser" * test_suite("subparsers")) { argparse::ArgumentParser program("test"); argparse::ArgumentParser parent("parent"); parent.add_argument("--verbose").flag(); program.add_parents(parent); argparse::ArgumentParser command_1("add"); command_1.add_argument("file"); argparse::ArgumentParser command_2("clean"); command_2.add_argument("--fullclean") .default_value(false) .implicit_value(true); program.add_subparser(command_1); program.add_subparser(command_2); SUBCASE("Optional argument BEFORE subcommand") { program.parse_args({"test", "--verbose", "clean", "--fullclean"}); REQUIRE(program.is_subcommand_used("clean") == true); REQUIRE(program.get("--verbose") == true); REQUIRE(command_2.get("--fullclean") == true); } SUBCASE("Optional argument AFTER subcommand") { REQUIRE_THROWS_WITH_AS( program.parse_args({"test", "clean", "--fullclean", "--verbose"}), "Unknown argument: --verbose", std::runtime_error); } } TEST_CASE("Parse git commands" * test_suite("subparsers")) { argparse::ArgumentParser program("git"); argparse::ArgumentParser add_command("add"); add_command.add_argument("files").remaining(); argparse::ArgumentParser commit_command("commit"); commit_command.add_argument("-a").flag(); commit_command.add_argument("-m"); argparse::ArgumentParser catfile_command("cat-file"); catfile_command.add_argument("-t"); catfile_command.add_argument("-p"); argparse::ArgumentParser submodule_command("submodule"); argparse::ArgumentParser submodule_update_command("update"); submodule_update_command.add_argument("--init") .default_value(false) .implicit_value(true); submodule_update_command.add_argument("--recursive") .default_value(false) .implicit_value(true); submodule_command.add_subparser(submodule_update_command); program.add_subparser(add_command); program.add_subparser(commit_command); program.add_subparser(catfile_command); program.add_subparser(submodule_command); SUBCASE("git add") { program.parse_args({"git", "add", "main.cpp", "foo.hpp", "foo.cpp"}); REQUIRE(program.is_subcommand_used("add") == true); REQUIRE((add_command.get>("files") == std::vector{"main.cpp", "foo.hpp", "foo.cpp"})); } SUBCASE("git commit") { program.parse_args({"git", "commit", "-am", "Initial commit"}); REQUIRE(program.is_subcommand_used("commit") == true); REQUIRE(commit_command.get("-a") == true); REQUIRE(commit_command.get("-m") == std::string{"Initial commit"}); } SUBCASE("git cat-file -t") { program.parse_args({"git", "cat-file", "-t", "3739f5"}); REQUIRE(program.is_subcommand_used("cat-file") == true); REQUIRE(catfile_command.get("-t") == std::string{"3739f5"}); } SUBCASE("git cat-file -p") { program.parse_args({"git", "cat-file", "-p", "3739f5"}); REQUIRE(program.is_subcommand_used("cat-file") == true); REQUIRE(catfile_command.get("-p") == std::string{"3739f5"}); } SUBCASE("git submodule update") { program.parse_args({"git", "submodule", "update"}); REQUIRE(program.is_subcommand_used("submodule") == true); REQUIRE(submodule_command.is_subcommand_used("update") == true); } SUBCASE("git submodule update --init") { program.parse_args({"git", "submodule", "update", "--init"}); REQUIRE(program.is_subcommand_used("submodule") == true); REQUIRE(submodule_command.is_subcommand_used("update") == true); REQUIRE(submodule_update_command.get("--init") == true); REQUIRE(submodule_update_command.get("--recursive") == false); } SUBCASE("git submodule update --recursive") { program.parse_args({"git", "submodule", "update", "--recursive"}); REQUIRE(program.is_subcommand_used("submodule") == true); REQUIRE(submodule_command.is_subcommand_used("update") == true); REQUIRE(submodule_update_command.get("--recursive") == true); } SUBCASE("git submodule update --init --recursive") { program.parse_args({"git", "submodule", "update", "--init", "--recursive"}); REQUIRE(program.is_subcommand_used("submodule") == true); REQUIRE(submodule_command.is_subcommand_used("update") == true); REQUIRE(submodule_update_command.get("--init") == true); REQUIRE(submodule_update_command.get("--recursive") == true); } } TEST_CASE("Check is_subcommand_used after parse" * test_suite("subparsers")) { argparse::ArgumentParser command_1("add"); argparse::ArgumentParser command_2("clean"); command_2.add_argument("--fullclean") .default_value(false) .implicit_value(true); argparse::ArgumentParser program("test"); program.add_subparser(command_1); program.add_subparser(command_2); SUBCASE("command 1") { program.parse_args({"test", "add"}); REQUIRE(program.is_subcommand_used("add") == true); REQUIRE(program.is_subcommand_used(command_1) == true); REQUIRE(program.is_subcommand_used("clean") == false); REQUIRE(program.is_subcommand_used(command_2) == false); } SUBCASE("command 2") { program.parse_args({"test", "clean", "--fullclean"}); REQUIRE(program.is_subcommand_used("add") == false); REQUIRE(program.is_subcommand_used(command_1) == false); REQUIRE(program.is_subcommand_used("clean") == true); REQUIRE(program.is_subcommand_used(command_2) == true); } SUBCASE("none") { program.parse_args({"test"}); REQUIRE(program.is_subcommand_used("add") == false); REQUIRE(program.is_subcommand_used(command_1) == false); REQUIRE(program.is_subcommand_used("clean") == false); REQUIRE(program.is_subcommand_used(command_2) == false); } } static bool contains(const std::string &haystack, const std::string &needle) { return haystack.find(needle) != std::string::npos; } TEST_CASE("Check set_suppress" * test_suite("subparsers")) { argparse::ArgumentParser command("cmd"); command.add_argument("arg").remaining(); argparse::ArgumentParser program("test"); program.add_subparser(command); SUBCASE("help message contain info if subcommand not suppressed") { command.set_suppress(false); REQUIRE(contains(program.help().str(), "Subcommands") == true); REQUIRE(contains(program.help().str(), "cmd") == true); } SUBCASE("help message does not contain info if subcommand suppressed") { command.set_suppress(true); REQUIRE(contains(program.help().str(), "Subcommands") == false); REQUIRE(contains(program.help().str(), "cmd") == false); } SUBCASE("help message contain info if not all subcommands suppressed") { argparse::ArgumentParser command_2("command_2"); program.add_subparser(command_2); command.set_suppress(true); command_2.set_suppress(false); REQUIRE(contains(program.help().str(), "Subcommands") == true); REQUIRE(contains(program.help().str(), "cmd") == false); REQUIRE(contains(program.help().str(), "command_2") == true); } }