diff --git a/test/unittest/CMakeLists.txt b/test/unittest/CMakeLists.txt index 844e2a97..9c14fd67 100644 --- a/test/unittest/CMakeLists.txt +++ b/test/unittest/CMakeLists.txt @@ -8,6 +8,8 @@ target_sources(unittest main.cpp test_argument_parser.cpp test_parsing.cpp + test_parsing_positional.cpp + test_parsing_optional.cpp test_parsing_mutually_exclusive_group.cpp test_usage_message.cpp test_help_message.cpp diff --git a/test/unittest/test_parsing.cpp b/test/unittest/test_parsing.cpp index a6a25883..429e74c1 100644 --- a/test/unittest/test_parsing.cpp +++ b/test/unittest/test_parsing.cpp @@ -1,8 +1,6 @@ #include "argparse.h" #include "cstring_array.h" -#include "custom_a.h" -#include "custom_b.h" #include "doctest.h" @@ -10,392 +8,6 @@ #include -using namespace std::string_literals; - -namespace bar -{ -auto operator==(Custom const & lhs, Custom const & rhs) -> bool -{ - return lhs.m_text == rhs.m_text; -} -} - -TEST_CASE("Parsing a positional argument yields its value") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("p1"); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "v1"}); - - CHECK(parsed.get_value("p1") == "v1"); -} - -TEST_CASE("Parsing an optional argument yields false when it's missing") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o"); - - auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); - - CHECK(!parsed.get("o")); -} - -TEST_CASE("Parsing an optional argument throws an exception when it's missing argument") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o"); - - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "-o"}), "argument -o: expected one argument", argparse::parsing_error); -} - -TEST_CASE("Parsing an optional argument yields its value") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o"); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "v1"}); - - CHECK(parsed.get_value("o") == "v1"); -} - -TEST_CASE("Parsing an optional argument with store true action yields false when it's missing") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("-o").action(argparse::store_true); - - auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); - - CHECK(parsed.get_value("o") == false); -} - -TEST_CASE("Parsing an optional argument with store true action yields true when it's present") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("-o").action(argparse::store_true); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-o"}); - - CHECK(parsed.get_value("o") == true); -} - -TEST_CASE("Parsing an optional argument with store false action yields true when it's missing") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("-o").action(argparse::store_false); - - auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); - - CHECK(parsed.get_value("o") == true); -} - -TEST_CASE("Parsing an optional argument with store false action yields false when it's present") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("-o").action(argparse::store_false); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-o"}); - - CHECK(parsed.get_value("o") == false); -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with store const action yields false when it's missing", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string, foo::Custom, bar::Custom) -{ - auto parser = argparse::ArgumentParser(); - - if constexpr (std::is_integral_v) - { - parser.add_argument("-o").action(argparse::store_const).const_(T(65)); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").action(argparse::store_const).const_(T(1.125)); - } - else - { - parser.add_argument("-o").action(argparse::store_const).const_(T("bar")); - } - - auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); - - CHECK(!parsed.get("o")); -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with store const action yields const value", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string, foo::Custom, bar::Custom) -{ - auto parser = argparse::ArgumentParser(); - - if constexpr (std::is_integral_v) - { - parser.add_argument("-o").action(argparse::store_const).const_(T(65)); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").action(argparse::store_const).const_(T(1.125)); - } - else - { - parser.add_argument("-o").action(argparse::store_const).const_(T("bar")); - } - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-o"}); - - if constexpr (std::is_integral_v) - { - CHECK(parsed.get_value("o") == T(65)); - } - else if constexpr (std::is_floating_point_v) - { - CHECK(parsed.get_value("o") == T(1.125)); - } - else - { - CHECK(parsed.get_value("o") == T("bar")); - } -} - -TEST_CASE("Parsing an optional argument with help action yields false when it's missing") -{ - auto parser = argparse::ArgumentParser().add_help(false).handle(argparse::Handle::none); - parser.add_argument("-h").action(argparse::help); - - auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); - - CHECK(parsed.get_value("h") == false); -} - -TEST_CASE("Parsing an optional argument with help action yields true when it's present") -{ - auto parser = argparse::ArgumentParser().add_help(false).handle(argparse::Handle::none); - parser.add_argument("-h").action(argparse::help); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-h"}); - - CHECK(parsed.get_value("h") == true); -} - -TEST_CASE("Parsing an optional argument with version action yields false when it's missing") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-v").action(argparse::version); - - auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); - - CHECK(parsed.get_value("v") == false); -} - -TEST_CASE("Parsing an optional argument with version action yields true when it's present") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-v").action(argparse::version); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-v"}); - - CHECK(parsed.get_value("v") == true); -} - -TEST_CASE("Optional argument can be used with either short name") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("-o", "--option"); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "val"}); - - CHECK(parsed.get_value("option") == "val"); -} - -TEST_CASE("Optional argument can be used with either long name") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("-o", "--option"); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "--option", "val"}); - - CHECK(parsed.get_value("option") == "val"); -} - -TEST_CASE_TEMPLATE("Parsing a positional argument yields its requested type", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, foo::Custom, bar::Custom) -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("pos").type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "A"}); - - CHECK(parsed.get_value("pos") == T(65)); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "65"}); - - CHECK(parsed.get_value("pos") == T(65)); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "1.125"}); - - CHECK(parsed.get_value("pos") == T(1.125)); - } - else - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "bar"}); - - CHECK(parsed.get_value("pos") == T("bar")); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument yields its requested type", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, foo::Custom, bar::Custom) -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("-o").type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); - - CHECK(parsed.get_value("o") == T(65)); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "65"}); - - CHECK(parsed.get_value("o") == T(65)); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "1.125"}); - - CHECK(parsed.get_value("o") == T(1.125)); - } - else - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "bar"}); - - CHECK(parsed.get_value("o") == T("bar")); - } -} - -TEST_CASE("Parsing a positional argument with invalid value throws an exception") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "not-a-number"}), "argument pos: invalid value: 'not-a-number'", argparse::parsing_error); - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "10gibberish"}), "argument pos: invalid value: '10gibberish'", argparse::parsing_error); -} - -TEST_CASE("Parsing an optional argument with invalid value throws an exception") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "not-a-number"}), "argument -o: invalid value: 'not-a-number'", argparse::parsing_error); - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "10gibberish"}), "argument -o: invalid value: '10gibberish'", argparse::parsing_error); -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with default value yields the default value when it's missing", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string, foo::Custom, bar::Custom) -{ - auto parser = argparse::ArgumentParser(); - - if constexpr (std::is_integral_v) - { - parser.add_argument("-o").default_(T(54)).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").default_(T(0.125)).template type(); - } - else - { - parser.add_argument("-o").default_(T("foo")).template type(); - } - - auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); - - if constexpr (std::is_integral_v) - { - CHECK(parsed.get_value("o") == T(54)); - } - else if constexpr (std::is_floating_point_v) - { - CHECK(parsed.get_value("o") == T(0.125)); - } - else - { - CHECK(parsed.get_value("o") == T("foo")); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with default value yields value of the argument's type", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string, foo::Custom, bar::Custom) -{ - auto parser = argparse::ArgumentParser(); - - if constexpr (std::is_integral_v) - { - parser.add_argument("-o").default_(T(54)).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").default_(T(0.125)).template type(); - } - else - { - parser.add_argument("-o").default_(T("foo")).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); - - CHECK(parsed.get_value("o") == T(65)); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "65"}); - - CHECK(parsed.get_value("o") == T(65)); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "1.125"}); - - CHECK(parsed.get_value("o") == T(1.125)); - } - else - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "bar"}); - - CHECK(parsed.get_value("o") == T("bar")); - } -} - -TEST_CASE("Parsing missing positional argument throws an exception for one missing argument") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("p1"); - - CHECK_THROWS_WITH_AS(parser.parse_args(1, cstr_arr{"prog"}), "the following arguments are required: p1", argparse::parsing_error); -} - -TEST_CASE("Parsing missing positional argument throws an exception for two missing arguments") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("p1"); - parser.add_argument("p2"); - - CHECK_THROWS_WITH_AS(parser.parse_args(1, cstr_arr{"prog"}), "the following arguments are required: p1 p2", argparse::parsing_error); -} - -TEST_CASE("Parsing missing positional argument throws an exception for three missing arguments") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("p1"); - parser.add_argument("p2"); - parser.add_argument("p3"); - - CHECK_THROWS_WITH_AS(parser.parse_args(1, cstr_arr{"prog"}), "the following arguments are required: p1 p2 p3", argparse::parsing_error); -} - TEST_CASE("Parsing arguments with help requested disregards parsing errors for missing positional argument") { auto parser = argparse::ArgumentParser().add_help(false).handle(argparse::Handle::none); @@ -421,53 +33,6 @@ TEST_CASE("Parsing arguments with help requested disregards parsing errors for u CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-a", "-h"})); } -TEST_CASE("Parsing unrecognised positional argument throws an exception for one unrecognised argument") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("p1"); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "v1", "v2"}), "unrecognised arguments: v2", argparse::parsing_error); -} - -TEST_CASE("Parsing unrecognised positional argument throws an exception for two unrecognised arguments") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("p1"); - - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "v1", "v2", "v3"}), "unrecognised arguments: v2 v3", argparse::parsing_error); -} - -TEST_CASE("Parsing unrecognised positional argument throws an exception for three unrecognised arguments") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("p1"); - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "v1", "v2", "v3", "v4"}), "unrecognised arguments: v2 v3 v4", argparse::parsing_error); -} - -TEST_CASE("Parsing unrecognised optional argument throws an exception for one unrecognised argument") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-a"); - - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-a", "v1", "-b"}), "unrecognised arguments: -b", argparse::parsing_error); -} - -TEST_CASE("Parsing unrecognised optional argument throws an exception for two unrecognised arguments") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-a"); - - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-a", "v1", "-b", "-c"}), "unrecognised arguments: -b -c", argparse::parsing_error); -} - -TEST_CASE("Parsing unrecognised optional argument throws an exception for three unrecognised arguments") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-a"); - - CHECK_THROWS_WITH_AS(parser.parse_args(6, cstr_arr{"prog", "-a", "v1", "-b", "-c", "-d"}), "unrecognised arguments: -b -c -d", argparse::parsing_error); -} - TEST_CASE("Parsing mixed positional and optional arguments give same result no matter the order for positional and optional") { auto parser1 = argparse::ArgumentParser(); @@ -502,4000 +67,27 @@ TEST_CASE("Parsing mixed positional and optional arguments give same result no m CHECK(parsed1.get_value("f") == parsed2.get_value("f")); } -TEST_CASE("The resulting attribute name is based on for positional argument on its name") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("foo"); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "val"}); - - CHECK(parsed.get("foo")); -} - -TEST_CASE("The resulting attribute name is based on for positional argument on dest parameter") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("foo").dest("bar"); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "val"}); - - CHECK(parsed.get("bar")); -} - -TEST_CASE("The resulting attribute name is based on for optional argument on its long name") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("-f", "--foo"); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-f", "val"}); - - CHECK(parsed.get("foo")); -} - -TEST_CASE("The resulting attribute name is based on for optional argument on its short name") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("-f"); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-f", "val"}); - - CHECK(parsed.get("f")); -} - -TEST_CASE("The resulting attribute name is based on for optional argument on dest parameter") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("-f", "--foo").dest("bar"); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-f", "val"}); - - CHECK(parsed.get("bar")); -} - -TEST_CASE("Parsing a missing optional argument with required true throws an exception") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").required(true); - - CHECK_THROWS_WITH_AS(parser.parse_args(1, cstr_arr{"prog"}), "the following arguments are required: -o", argparse::parsing_error); -} - -TEST_CASE("Parsing a missing optional argument with required false does not throw") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").required(false); - - CHECK_NOTHROW(parser.parse_args(1, cstr_arr{"prog"})); -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set accepts one of the values", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string, foo::Custom, bar::Custom) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).template type(); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "A"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "C"})); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(23), T(34)}).template type(); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "23"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "34"})); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(1.5)}).template type(); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.125"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "1.5"})); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).template type(); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "foo"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string, foo::Custom, bar::Custom) +TEST_CASE("Parsing -- pseudo argument does not throw") { auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(23), T(34)}).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "3"}), "argument pos: invalid choice: 3 (choose from 23, 34)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(1.5)}).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 1.5)", argparse::parsing_error); - } - else if constexpr (std::is_same_v) - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "baz"}), "argument pos: invalid choice: (choose from , )", argparse::parsing_error); - } + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "--"})); } -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set accepts one of the values", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string, foo::Custom, bar::Custom) +TEST_CASE("Arguments past the -- pseudo argument are treated as positional for optional arguments") { auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").action(argparse::store_true); - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).template type(); - - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "A"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "C"})); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(23), T(34)}).template type(); - - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "23"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "34"})); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(1.5)}).template type(); - - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.125"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "1.5"})); - } - else - { - parser.add_argument("-o").choices({T("foo"), T("bar")}).template type(); - - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "foo"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "bar"})); - } + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "--", "-o"}), "unrecognised arguments: -o", argparse::parsing_error); } -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string, foo::Custom, bar::Custom) +TEST_CASE("Arguments past the -- pseudo argument are treated as positional for positional arguments") { auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos"); - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(23), T(34)}).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "3"}), "argument -o: invalid choice: 3 (choose from 23, 34)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(1.5)}).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 1.5)", argparse::parsing_error); - } - else if constexpr (std::is_same_v) - { - parser.add_argument("-o").choices({T("foo"), T("bar")}).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } - else - { - parser.add_argument("-o").choices({T("foo"), T("bar")}).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "baz"}), "argument -o: invalid choice: (choose from , )", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number consumes the number of arguments for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(1).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "A"})); - } - else if constexpr (std::is_integral_v) - { - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "42"})); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.5"})); - } - else - { - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "foo"})); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number consumes the number of arguments for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(2).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "A", "C"})); - } - else if constexpr (std::is_integral_v) - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "42", "54"})); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "0.5", "1.125"})); - } - else - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "foo", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number consumes the number of arguments for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(3).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "A", "C", "E"})); - } - else if constexpr (std::is_integral_v) - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "42", "54", "65"})); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "0.5", "1.125", "2.375"})); - } - else - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "baz"})); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number yields a list of arguments for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(1).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "B"}); - - CHECK(parsed.get_value>("pos") == std::vector{'B'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "42"}); - - CHECK(parsed.get_value>("pos") == std::vector{42}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "0.5"}); - - CHECK(parsed.get_value>("pos") == std::vector{0.5}); - } - else - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "foo"}); - - CHECK(parsed.get_value>("pos") == std::vector{"foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number yields a list of arguments for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(2).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "B", "D"}); - - CHECK(parsed.get_value>("pos") == std::vector{'B', 'D'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "42", "54"}); - - CHECK(parsed.get_value>("pos") == std::vector{42, 54}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "0.5", "1.125"}); - - CHECK(parsed.get_value>("pos") == std::vector{0.5, 1.125}); - } - else - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "foo", "bar"}); - - CHECK(parsed.get_value>("pos") == std::vector{"foo", "bar"}); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number yields a list of arguments for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(3).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "B", "D", "F"}); - - CHECK(parsed.get_value>("pos") == std::vector{'B', 'D', 'F'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "42", "54", "65"}); - - CHECK(parsed.get_value>("pos") == std::vector{42, 54, 65}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "0.5", "1.125", "2.375"}); - - CHECK(parsed.get_value>("pos") == std::vector{0.5, 1.125, 2.375}); - } - else - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "baz"}); - - CHECK(parsed.get_value>("pos") == std::vector{"foo", "bar", "baz"}); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number throws an exception for incorrect arguments number for one argument and no provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(1).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(1, cstr_arr{"prog"}), "the following arguments are required: pos", argparse::parsing_error); -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number throws an exception for incorrect arguments number for two arguments and one provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(2).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "A"}), "the following arguments are required: pos", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "42"}), "the following arguments are required: pos", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "0.5"}), "the following arguments are required: pos", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "foo"}), "the following arguments are required: pos", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number throws an exception for incorrect arguments number for three arguments and two provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(3).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "A", "B"}), "the following arguments are required: pos", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "42", "54"}), "the following arguments are required: pos", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "0.5", "1.125"}), "the following arguments are required: pos", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "foo", "bar"}), "the following arguments are required: pos", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number throws an exception for incorrect arguments number for one argument and two provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(1).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "A", "B"}), "unrecognised arguments: B", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "42", "54"}), "unrecognised arguments: 54", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "0.5", "1.125"}), "unrecognised arguments: 1.125", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "foo", "bar"}), "unrecognised arguments: bar", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number throws an exception for incorrect arguments number for one arguments and three provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(1).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "A", "B", "C"}), "unrecognised arguments: B C", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "42", "54", "65"}), "unrecognised arguments: 54 65", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "0.5", "1.125", "2.375"}), "unrecognised arguments: 1.125 2.375", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "baz"}), "unrecognised arguments: bar baz", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number throws an exception for incorrect arguments number for two arguments and three provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(2).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "A", "B", "C"}), "unrecognised arguments: C", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "42", "54", "65"}), "unrecognised arguments: 65", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "0.5", "1.125", "2.375"}), "unrecognised arguments: 2.375", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "baz"}), "unrecognised arguments: baz", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as zero_or_one consumes single argument and yields it as a single item", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(argparse::zero_or_one).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "A"}); - - CHECK(parsed.get_value("pos") == T('A')); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "42"}); - - CHECK(parsed.get_value("pos") == T(42)); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "0.5"}); - - CHECK(parsed.get_value("pos") == T(0.5)); - } - else - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "foo"}); - - CHECK(parsed.get_value("pos") == T("foo")); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as zero_or_one yields default value if no argument is provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").nargs(argparse::zero_or_one).default_(T('A')); - - auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); - - CHECK(parsed.get_value("pos") == T('A')); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").nargs(argparse::zero_or_one).default_(T(10)); - - auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); - - CHECK(parsed.get_value("pos") == T(10)); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").nargs(argparse::zero_or_one).default_(T(0.0625)); - - auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); - - CHECK(parsed.get_value("pos") == T(0.0625)); - } - else - { - parser.add_argument("pos").nargs(argparse::zero_or_one).default_("foo"s); - - auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); - - CHECK(parsed.get_value("pos") == T("foo")); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as zero_or_more yields an empty list if no arguments provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(argparse::zero_or_more).template type(); - - auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); - - CHECK(parsed.get_value>("pos") == std::vector()); -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as zero_or_more consumes single argument and yields it as a list", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(argparse::zero_or_more).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "A"}); - - CHECK(parsed.get_value>("pos") == std::vector{'A'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "42"}); - - CHECK(parsed.get_value>("pos") == std::vector{42}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "0.5"}); - - CHECK(parsed.get_value>("pos") == std::vector{0.5}); - } - else - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "foo"}); - - CHECK(parsed.get_value>("pos") == std::vector{"foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as zero_or_more consumes all available arguments and yields them as a list", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(argparse::zero_or_more).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "A", "G", "J"}); - - CHECK(parsed.get_value>("pos") == std::vector{'A', 'G', 'J'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "42", "54", "65"}); - - CHECK(parsed.get_value>("pos") == std::vector{42, 54, 65}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "0.5", "1.125", "2.375"}); - - CHECK(parsed.get_value>("pos") == std::vector{0.5, 1.125, 2.375}); - } - else - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "baz"}); - - CHECK(parsed.get_value>("pos") == std::vector{"foo", "bar", "baz"}); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as one_or_more throws an exception if no arguments provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(argparse::one_or_more).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(1, cstr_arr{"prog"}), "the following arguments are required: pos", argparse::parsing_error); -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as one_or_more consumes single argument and yields it as a list", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(argparse::one_or_more).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "A"}); - - CHECK(parsed.get_value>("pos") == std::vector{'A'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "42"}); - - CHECK(parsed.get_value>("pos") == std::vector{42}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "0.5"}); - - CHECK(parsed.get_value>("pos") == std::vector{0.5}); - } - else - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "foo"}); - - CHECK(parsed.get_value>("pos") == std::vector{"foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as one_or_more consumes all available arguments and yields them as a list", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos").nargs(argparse::one_or_more).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "A", "G", "J"}); - - CHECK(parsed.get_value>("pos") == std::vector{'A', 'G', 'J'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "42", "54", "65"}); - - CHECK(parsed.get_value>("pos") == std::vector{42, 54, 65}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "0.5", "1.125", "2.375"}); - - CHECK(parsed.get_value>("pos") == std::vector{0.5, 1.125, 2.375}); - } - else - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "baz"}); - - CHECK(parsed.get_value>("pos") == std::vector{"foo", "bar", "baz"}); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number consumes the number of arguments for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(1).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "A"})); - } - else if constexpr (std::is_integral_v) - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "42"})); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"})); - } - else - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "foo"})); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number consumes the number of arguments for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(2).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "A", "C"})); - } - else if constexpr (std::is_integral_v) - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "42", "54"})); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "0.5", "1.125"})); - } - else - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number consumes the number of arguments for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(3).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "A", "C", "E"})); - } - else if constexpr (std::is_integral_v) - { - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "42", "54", "65"})); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "0.5", "1.125", "2.375"})); - } - else - { - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "baz"})); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number yields a list of arguments for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(1).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); - - CHECK(parsed.get_value>("o") == std::vector{'A'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "42"}); - - CHECK(parsed.get_value>("o") == std::vector{42}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}); - - CHECK(parsed.get_value>("o") == std::vector{0.5}); - } - else - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "foo"}); - - CHECK(parsed.get_value>("o") == std::vector{"foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number yields a list of arguments for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(2).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "A", "C"}); - - CHECK(parsed.get_value>("o") == std::vector{'A', 'C'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "42", "54"}); - - CHECK(parsed.get_value>("o") == std::vector{42, 54}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "0.5", "1.125"}); - - CHECK(parsed.get_value>("o") == std::vector{0.5, 1.125}); - } - else - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "bar"}); - - CHECK(parsed.get_value>("o") == std::vector{"foo", "bar"}); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number yields a list of arguments for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(3).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "A", "C", "E"}); - - CHECK(parsed.get_value>("o") == std::vector{'A', 'C', 'E'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "42", "54", "65"}); - - CHECK(parsed.get_value>("o") == std::vector{42, 54, 65}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "0.5", "1.125", "2.375"}); - - CHECK(parsed.get_value>("o") == std::vector{0.5, 1.125, 2.375}); - } - else - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "baz"}); - - CHECK(parsed.get_value>("o") == std::vector{"foo", "bar", "baz"}); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number throws an exception for incorrect arguments number for one argument and no provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(1).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "-o"}), "argument -o: expected 1 argument", argparse::parsing_error); -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number throws an exception for incorrect arguments number for two arguments and one provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(2).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "A"}), "argument -o: expected 2 arguments", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "42"}), "argument -o: expected 2 arguments", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}), "argument -o: expected 2 arguments", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "foo"}), "argument -o: expected 2 arguments", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number throws an exception for incorrect arguments number for three arguments and two provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(3).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "A", "B"}), "argument -o: expected 3 arguments", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "42", "54"}), "argument -o: expected 3 arguments", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "0.5", "1.125"}), "argument -o: expected 3 arguments", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "bar"}), "argument -o: expected 3 arguments", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number throws an exception for incorrect arguments number for one argument and two provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(1).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "A", "B"}), "unrecognised arguments: B", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "42", "54"}), "unrecognised arguments: 54", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "0.5", "1.125"}), "unrecognised arguments: 1.125", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "bar"}), "unrecognised arguments: bar", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number throws an exception for incorrect arguments number for one argument and three provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(1).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "A", "B", "C"}), "unrecognised arguments: B C", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "42", "54", "65"}), "unrecognised arguments: 54 65", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "0.5", "1.125", "2.375"}), "unrecognised arguments: 1.125 2.375", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "baz"}), "unrecognised arguments: bar baz", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number throws an exception for incorrect arguments number for two arguments and three provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(2).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "A", "B", "C"}), "unrecognised arguments: C", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "42", "54", "65"}), "unrecognised arguments: 65", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "0.5", "1.125", "2.375"}), "unrecognised arguments: 2.375", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "baz"}), "unrecognised arguments: baz", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as zero_or_one consumes single argument and yields it as a single item", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(argparse::zero_or_one).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); - - CHECK(parsed.get_value("o") == T('A')); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "42"}); - - CHECK(parsed.get_value("o") == T(42)); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}); - - CHECK(parsed.get_value("o") == T(0.5)); - } - else - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "foo"}); - - CHECK(parsed.get_value("o") == T("foo")); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as zero_or_one yields default value if no argument is provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").nargs(argparse::zero_or_one).default_(T('A')); - - auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); - - CHECK(parsed.get_value("o") == T('A')); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").nargs(argparse::zero_or_one).default_(T(10)); - - auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); - - CHECK(parsed.get_value("o") == T(10)); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").nargs(argparse::zero_or_one).default_(T(0.0625)); - - auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); - - CHECK(parsed.get_value("o") == T(0.0625)); - } - else - { - parser.add_argument("-o").nargs(argparse::zero_or_one).default_("foo"s); - - auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); - - CHECK(parsed.get_value("o") == "foo"); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as zero_or_one yields const value if option string is present and no argument is provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").nargs(argparse::zero_or_one).const_(T('A')); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-o"}); - - CHECK(parsed.get_value("o") == T('A')); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").nargs(argparse::zero_or_one).const_(T(5)); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-o"}); - - CHECK(parsed.get_value("o") == T(5)); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").nargs(argparse::zero_or_one).const_(T(0.875)); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-o"}); - - CHECK(parsed.get_value("o") == T(0.875)); - } - else - { - parser.add_argument("-o").nargs(argparse::zero_or_one).const_("foo"s); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-o"}); - - CHECK(parsed.get_value("o") == "foo"); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as zero_or_more yields an empty list if no arguments provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(argparse::zero_or_more).template type(); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-o"}); - - CHECK(parsed.get_value>("o") == std::vector()); -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as zero_or_more consumes single argument and yields it as a list", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(argparse::zero_or_more).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); - - CHECK(parsed.get_value>("o") == std::vector{'A'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "42"}); - - CHECK(parsed.get_value>("o") == std::vector{42}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}); - - CHECK(parsed.get_value>("o") == std::vector{0.5}); - } - else - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "foo"}); - - CHECK(parsed.get_value>("o") == std::vector{"foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as zero_or_more consumes all available arguments and yields them as a list", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(argparse::zero_or_more).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "A", "C", "E"}); - - CHECK(parsed.get_value>("o") == std::vector{'A', 'C', 'E'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "42", "54", "65"}); - - CHECK(parsed.get_value>("o") == std::vector{42, 54, 65}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "0.5", "1.125", "2.375"}); - - CHECK(parsed.get_value>("o") == std::vector{0.5, 1.125, 2.375}); - } - else - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "baz"}); - - CHECK(parsed.get_value>("o") == std::vector{"foo", "bar", "baz"}); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as one_or_more throws an exception if no arguments provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(argparse::one_or_more).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "-o"}), "argument -o: expected at least one argument", argparse::parsing_error); -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as one_or_more consumes single argument and yields it as a list", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(argparse::one_or_more).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); - - CHECK(parsed.get_value>("o") == std::vector{'A'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "42"}); - - CHECK(parsed.get_value>("o") == std::vector{42}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}); - - CHECK(parsed.get_value>("o") == std::vector{0.5}); - } - else - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "foo"}); - - CHECK(parsed.get_value>("o") == std::vector{"foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as one_or_more consumes all available arguments and yields them as a list", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(argparse::one_or_more).template type(); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "A", "C", "E"}); - - CHECK(parsed.get_value>("o") == std::vector{'A', 'C', 'E'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "42", "54", "65"}); - - CHECK(parsed.get_value>("o") == std::vector{42, 54, 65}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "0.5", "1.125", "2.375"}); - - CHECK(parsed.get_value>("o") == std::vector{0.5, 1.125, 2.375}); - } - else - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "baz"}); - - CHECK(parsed.get_value>("o") == std::vector{"foo", "bar", "baz"}); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as a number for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(1).template type(); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "A"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "C"})); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(1).template type(); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "11"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(1).template type(); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.125"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.25"})); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(1).template type(); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "foo"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as a number for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(2).template type(); - - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "A", "A"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "C", "C"})); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(2).template type(); - - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "11", "11"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "22", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(2).template type(); - - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "0.125", "0.125"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "0.25", "0.25"})); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(2).template type(); - - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "foo", "foo"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "bar", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as a number for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(3).template type(); - - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "A", "A", "A"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "C", "C", "C"})); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(3).template type(); - - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "11", "11", "11"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "22", "22", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(3).template type(); - - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "0.125", "0.125", "0.125"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "0.25", "0.25", "0.25"})); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(3).template type(); - - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "foo", "foo", "foo"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "bar", "bar", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as zero_or_one for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_one).template type(); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "A"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "C"})); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_one).template type(); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "11"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_one).template type(); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.125"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.25"})); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_one).template type(); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "foo"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as zero_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "A"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "C"})); - } - else if constexpr (std::is_integral_v) - { - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "11"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.125"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.25"})); - } - else - { - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "foo"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as zero_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "A", "A"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "C", "C"})); - } - else if constexpr (std::is_integral_v) - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "11", "11"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "22", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "0.125", "0.125"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "0.25", "0.25"})); - } - else - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "foo", "foo"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "bar", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as zero_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "A", "A", "A"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "C", "C", "C"})); - } - else if constexpr (std::is_integral_v) - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "11", "11", "11"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "22", "22", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "0.125", "0.125", "0.125"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "0.25", "0.25", "0.25"})); - } - else - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "foo", "foo", "foo"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "bar", "bar", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as one_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::one_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "A"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "C"})); - } - else if constexpr (std::is_integral_v) - { - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "11"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.125"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.25"})); - } - else - { - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "foo"})); - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as one_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::one_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "A", "A"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "C", "C"})); - } - else if constexpr (std::is_integral_v) - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "11", "11"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "22", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "0.125", "0.125"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "0.25", "0.25"})); - } - else - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "foo", "foo"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "bar", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as one_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::one_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "A", "A", "A"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "C", "C", "C"})); - } - else if constexpr (std::is_integral_v) - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "11", "11", "11"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "22", "22", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "0.125", "0.125", "0.125"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "0.25", "0.25", "0.25"})); - } - else - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "foo", "foo", "foo"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "bar", "bar", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as a number for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(1).template type(); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "A"}); - - CHECK(parsed.get_value>("pos") == std::vector{'A'}); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(1).template type(); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "11"}); - - CHECK(parsed.get_value>("pos") == std::vector{11}); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(1).template type(); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "0.125"}); - - CHECK(parsed.get_value>("pos") == std::vector{0.125}); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(1).template type(); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "foo"}); - - CHECK(parsed.get_value>("pos") == std::vector{"foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as a number for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(2).template type(); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "A", "C"}); - - CHECK(parsed.get_value>("pos") == std::vector{'A', 'C'}); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(2).template type(); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "11", "22"}); - - CHECK(parsed.get_value>("pos") == std::vector{11, 22}); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(2).template type(); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "0.125", "0.25"}); - - CHECK(parsed.get_value>("pos") == std::vector{0.125, 0.25}); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(2).template type(); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "foo", "bar"}); - - CHECK(parsed.get_value>("pos") == std::vector{"foo", "bar"}); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as a number for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(3).template type(); - - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "A", "C", "A"}); - - CHECK(parsed.get_value>("pos") == std::vector{'A', 'C', 'A'}); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(3).template type(); - - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "11", "22", "11"}); - - CHECK(parsed.get_value>("pos") == std::vector{11, 22, 11}); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(3).template type(); - - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "0.125", "0.25", "0.125"}); - - CHECK(parsed.get_value>("pos") == std::vector{0.125, 0.25, 0.125}); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(3).template type(); - - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "foo"}); - - CHECK(parsed.get_value>("pos") == std::vector{"foo", "bar", "foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as zero_or_one for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_one).template type(); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "A"}); - - CHECK(parsed.get_value("pos") == T('A')); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_one).template type(); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "11"}); - - CHECK(parsed.get_value("pos") == T(11)); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_one).template type(); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "0.125"}); - - CHECK(parsed.get_value("pos") == T(0.125)); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_one).template type(); - - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "foo"}); - - CHECK(parsed.get_value("pos") == T("foo")); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as zero_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "A"}); - - CHECK(parsed.get_value>("pos") == std::vector{'A'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "11"}); - - CHECK(parsed.get_value>("pos") == std::vector{11}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "0.125"}); - - CHECK(parsed.get_value>("pos") == std::vector{0.125}); - } - else - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "foo"}); - - CHECK(parsed.get_value>("pos") == std::vector{"foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as zero_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "A", "A"}); - - CHECK(parsed.get_value>("pos") == std::vector{'A', 'A'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "11", "11"}); - - CHECK(parsed.get_value>("pos") == std::vector{11, 11}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "0.125", "0.125"}); - - CHECK(parsed.get_value>("pos") == std::vector{0.125, 0.125}); - } - else - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "foo", "foo"}); - - CHECK(parsed.get_value>("pos") == std::vector{"foo", "foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as zero_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "A", "A", "A"}); - - CHECK(parsed.get_value>("pos") == std::vector{'A', 'A', 'A'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "11", "11", "11"}); - - CHECK(parsed.get_value>("pos") == std::vector{11, 11, 11}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "0.125", "0.125", "0.125"}); - - CHECK(parsed.get_value>("pos") == std::vector{0.125, 0.125, 0.125}); - } - else - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "foo", "foo", "foo"}); - - CHECK(parsed.get_value>("pos") == std::vector{"foo", "foo", "foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as one_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::one_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "A"}); - - CHECK(parsed.get_value>("pos") == std::vector{'A'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "11"}); - - CHECK(parsed.get_value>("pos") == std::vector{11}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "0.125"}); - - CHECK(parsed.get_value>("pos") == std::vector{0.125}); - } - else - { - auto const parsed = parser.parse_args(2, cstr_arr{"prog", "foo"}); - - CHECK(parsed.get_value>("pos") == std::vector{"foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as one_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::one_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "A", "A"}); - - CHECK(parsed.get_value>("pos") == std::vector{'A', 'A'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "11", "11"}); - - CHECK(parsed.get_value>("pos") == std::vector{11, 11}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "0.125", "0.125"}); - - CHECK(parsed.get_value>("pos") == std::vector{0.125, 0.125}); - } - else - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "foo", "foo"}); - - CHECK(parsed.get_value>("pos") == std::vector{"foo", "foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as one_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::one_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "A", "A", "A"}); - - CHECK(parsed.get_value>("pos") == std::vector{'A', 'A', 'A'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "11", "11", "11"}); - - CHECK(parsed.get_value>("pos") == std::vector{11, 11, 11}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "0.125", "0.125", "0.125"}); - - CHECK(parsed.get_value>("pos") == std::vector{0.125, 0.125, 0.125}); - } - else - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "foo", "foo", "foo"}); - - CHECK(parsed.get_value>("pos") == std::vector{"foo", "foo", "foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as a number for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(1).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(1).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(1).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(1).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as a number for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(2).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "A", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(2).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "11", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(2).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "0.125", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(2).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "foo", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as a number for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(3).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "A", "C", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(3).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "11", "22", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(3).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "0.125", "0.25", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(3).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as zero_or_one for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_one).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_one).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_one).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_one).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as zero_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as zero_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "A", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "11", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "0.125", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "foo", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as zero_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "A", "C", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "11", "22", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "0.125", "0.25", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as one_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::one_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as one_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::one_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "A", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "11", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "0.125", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "foo", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as one_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); - } - else - { - parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::one_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "A", "C", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "11", "22", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "0.125", "0.25", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as a number for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(1).template type(); - - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "A"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "C"})); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(1).template type(); - - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "11"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(1).template type(); - - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.125"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.25"})); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(1).template type(); - - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "foo"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as a number for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(2).template type(); - - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "A", "A"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "C", "C"})); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(2).template type(); - - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "11", "11"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "22", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(2).template type(); - - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "0.125", "0.125"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "0.25", "0.25"})); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(2).template type(); - - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "foo"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "bar", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as a number for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(3).template type(); - - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "A", "A", "A"})); - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "C", "C", "C"})); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(3).template type(); - - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "11", "11", "11"})); - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "22", "22", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(3).template type(); - - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "0.125", "0.125", "0.125"})); - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "0.25", "0.25", "0.25"})); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(3).template type(); - - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "foo", "foo"})); - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "bar", "bar", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as zero_or_one for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_one).template type(); - - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "A"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "C"})); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_one).template type(); - - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "11"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_one).template type(); - - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.125"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.25"})); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_one).template type(); - - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "foo"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as zero_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "A"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "C"})); - } - else if constexpr (std::is_integral_v) - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "11"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.125"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.25"})); - } - else - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "foo"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as zero_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "A", "A"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "C", "C"})); - } - else if constexpr (std::is_integral_v) - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "11", "11"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "22", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "0.125", "0.125"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "0.25", "0.25"})); - } - else - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "foo"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "bar", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as zero_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "A", "A", "A"})); - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "C", "C", "C"})); - } - else if constexpr (std::is_integral_v) - { - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "11", "11", "11"})); - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "22", "22", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "0.125", "0.125", "0.125"})); - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "0.25", "0.25", "0.25"})); - } - else - { - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "foo", "foo"})); - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "bar", "bar", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as one_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::one_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "A"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "C"})); - } - else if constexpr (std::is_integral_v) - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "11"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.125"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.25"})); - } - else - { - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "foo"})); - CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as one_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::one_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "A", "A"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "C", "C"})); - } - else if constexpr (std::is_integral_v) - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "11", "11"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "22", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "0.125", "0.125"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "0.25", "0.25"})); - } - else - { - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "foo"})); - CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "bar", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as one_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::one_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "A", "A", "A"})); - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "C", "C", "C"})); - } - else if constexpr (std::is_integral_v) - { - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "11", "11", "11"})); - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "22", "22", "22"})); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "0.125", "0.125", "0.125"})); - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "0.25", "0.25", "0.25"})); - } - else - { - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "foo", "foo"})); - CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "bar", "bar", "bar"})); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as a number for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(1).template type(); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); - - CHECK(parsed.get_value>("o") == std::vector{'A'}); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(1).template type(); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "11"}); - - CHECK(parsed.get_value>("o") == std::vector{11}); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(1).template type(); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "0.125"}); - - CHECK(parsed.get_value>("o") == std::vector{0.125}); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(1).template type(); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "foo"}); - - CHECK(parsed.get_value>("o") == std::vector{"foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as a number for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(2).template type(); - - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "A", "C"}); - - CHECK(parsed.get_value>("o") == std::vector{'A', 'C'}); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(2).template type(); - - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "11", "22"}); - - CHECK(parsed.get_value>("o") == std::vector{11, 22}); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(2).template type(); - - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "0.125", "0.25"}); - - CHECK(parsed.get_value>("o") == std::vector{0.125, 0.25}); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(2).template type(); - - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "bar"}); - - CHECK(parsed.get_value>("o") == std::vector{"foo", "bar"}); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as a number for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(3).template type(); - - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "A", "C", "A"}); - - CHECK(parsed.get_value>("o") == std::vector{'A', 'C', 'A'}); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(3).template type(); - - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "11", "22", "11"}); - - CHECK(parsed.get_value>("o") == std::vector{11, 22, 11}); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(3).template type(); - - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "0.125", "0.25", "0.125"}); - - CHECK(parsed.get_value>("o") == std::vector{0.125, 0.25, 0.125}); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(3).template type(); - - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "foo"}); - - CHECK(parsed.get_value>("o") == std::vector{"foo", "bar", "foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as zero_or_one for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_one).template type(); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); - - CHECK(parsed.get_value("o") == T('A')); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_one).template type(); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "11"}); - - CHECK(parsed.get_value("o") == T(11)); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_one).template type(); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "0.125"}); - - CHECK(parsed.get_value("o") == T(0.125)); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_one).template type(); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "foo"}); - - CHECK(parsed.get_value("o") == T("foo")); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as zero_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); - - CHECK(parsed.get_value>("o") == std::vector{'A'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "11"}); - - CHECK(parsed.get_value>("o") == std::vector{11}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "0.125"}); - - CHECK(parsed.get_value>("o") == std::vector{0.125}); - } - else - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "foo"}); - - CHECK(parsed.get_value>("o") == std::vector{"foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as zero_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "A", "A"}); - - CHECK(parsed.get_value>("o") == std::vector{'A', 'A'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "11", "11"}); - - CHECK(parsed.get_value>("o") == std::vector{11, 11}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "0.125", "0.125"}); - - CHECK(parsed.get_value>("o") == std::vector{0.125, 0.125}); - } - else - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "foo"}); - - CHECK(parsed.get_value>("o") == std::vector{"foo", "foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as zero_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "A", "A", "A"}); - - CHECK(parsed.get_value>("o") == std::vector{'A', 'A', 'A'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "11", "11", "11"}); - - CHECK(parsed.get_value>("o") == std::vector{11, 11, 11}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "0.125", "0.125", "0.125"}); - - CHECK(parsed.get_value>("o") == std::vector{0.125, 0.125, 0.125}); - } - else - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "foo", "foo"}); - - CHECK(parsed.get_value>("o") == std::vector{"foo", "foo", "foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as one_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::one_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); - - CHECK(parsed.get_value>("o") == std::vector{'A'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "11"}); - - CHECK(parsed.get_value>("o") == std::vector{11}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "0.125"}); - - CHECK(parsed.get_value>("o") == std::vector{0.125}); - } - else - { - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "foo"}); - - CHECK(parsed.get_value>("o") == std::vector{"foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as one_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::one_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "A", "A"}); - - CHECK(parsed.get_value>("o") == std::vector{'A', 'A'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "11", "11"}); - - CHECK(parsed.get_value>("o") == std::vector{11, 11}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "0.125", "0.125"}); - - CHECK(parsed.get_value>("o") == std::vector{0.125, 0.125}); - } - else - { - auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "foo"}); - - CHECK(parsed.get_value>("o") == std::vector{"foo", "foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as one_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::one_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "A", "A", "A"}); - - CHECK(parsed.get_value>("o") == std::vector{'A', 'A', 'A'}); - } - else if constexpr (std::is_integral_v) - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "11", "11", "11"}); - - CHECK(parsed.get_value>("o") == std::vector{11, 11, 11}); - } - else if constexpr (std::is_floating_point_v) - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "0.125", "0.125", "0.125"}); - - CHECK(parsed.get_value>("o") == std::vector{0.125, 0.125, 0.125}); - } - else - { - auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "foo", "foo"}); - - CHECK(parsed.get_value>("o") == std::vector{"foo", "foo", "foo"}); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as a number for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(1).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(1).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(1).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(1).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as a number for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(2).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "A", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(2).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "11", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(2).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "0.125", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(2).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as a number for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(3).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "A", "C", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(3).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "11", "22", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(3).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "0.125", "0.25", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(3).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as zero_or_one for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_one).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_one).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_one).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_one).template type(); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as zero_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as zero_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "A", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "11", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "0.125", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as zero_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "A", "C", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "11", "22", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "0.125", "0.25", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as one_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::one_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as one_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::one_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "A", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "11", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "0.125", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as one_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_integral_v) - { - parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); - } - else if constexpr (std::is_floating_point_v) - { - parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); - } - else - { - parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::one_or_more).template type(); - } - - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "A", "C", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); - } - else if constexpr (std::is_integral_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "11", "22", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); - } - else if constexpr (std::is_floating_point_v) - { - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "0.125", "0.25", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); - } - else - { - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); - } -} - -TEST_CASE("Parsing missing positional argument with nargs set throws an exception for one missing argument") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("p1").nargs(2); - - CHECK_THROWS_WITH_AS(parser.parse_args(1, cstr_arr{"prog"}), "the following arguments are required: p1", argparse::parsing_error); -} - -TEST_CASE("Parsing missing positional argument with nargs set throws an exception for two missing arguments") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("p1").nargs(2); - parser.add_argument("p2").nargs(2); - - CHECK_THROWS_WITH_AS(parser.parse_args(1, cstr_arr{"prog"}), "the following arguments are required: p1 p2", argparse::parsing_error); -} - -TEST_CASE("Parsing missing positional argument with nargs set throws an exception for three missing arguments") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("p1").nargs(2); - parser.add_argument("p2").nargs(2); - parser.add_argument("p3").nargs(2); - - CHECK_THROWS_WITH_AS(parser.parse_args(1, cstr_arr{"prog"}), "the following arguments are required: p1 p2 p3", argparse::parsing_error); -} - -TEST_CASE("An optional argument does not consume another optional argument for simple argument") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o"); - parser.add_argument("-p"); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "-p"}), "argument -o: expected one argument", argparse::parsing_error); -} - -TEST_CASE("An optional argument does not consume another optional argument for argument with nargs set as number 1") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(1); - parser.add_argument("-p"); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "-p"}), "argument -o: expected 1 argument", argparse::parsing_error); -} - -TEST_CASE("An optional argument does not consume another optional argument for argument with nargs set as number 2") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(2); - parser.add_argument("-p"); - - CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "-p"}), "argument -o: expected 2 arguments", argparse::parsing_error); -} - -TEST_CASE("An optional argument does not consume another optional argument for argument with nargs set as number 3") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(3); - parser.add_argument("-p"); - - CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "-p"}), "argument -o: expected 3 arguments", argparse::parsing_error); -} - -TEST_CASE("An optional argument does not consume another optional argument for argument with nargs set as zero_or_one") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(argparse::zero_or_one); - parser.add_argument("-p"); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "-p"}), "argument -p: expected one argument", argparse::parsing_error); -} - -TEST_CASE("An optional argument does not consume another optional argument for argument with nargs set as zero_or_more") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(argparse::zero_or_more); - parser.add_argument("-p"); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "-p"}), "argument -p: expected one argument", argparse::parsing_error); -} - -TEST_CASE("An optional argument does not consume another optional argument for argument with nargs set as one_or_more") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(argparse::one_or_more); - parser.add_argument("-p"); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "-p"}), "argument -o: expected at least one argument", argparse::parsing_error); -} - -TEST_CASE("Parsing -- pseudo argument does not throw") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "--"})); -} - -TEST_CASE("Arguments past the -- pseudo argument are treated as positional for optional arguments") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").action(argparse::store_true); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "--", "-o"}), "unrecognised arguments: -o", argparse::parsing_error); -} - -TEST_CASE("Arguments past the -- pseudo argument are treated as positional for positional arguments") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("pos"); - - auto const parsed = parser.parse_args(3, cstr_arr{"prog", "--", "-o"}); + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "--", "-o"}); CHECK(parsed.get_value("pos") == "-o"); } - -TEST_CASE("An optional argument does not consume arguments past the -- pseudo argument for simple argument") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o"); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "--"}), "argument -o: expected one argument", argparse::parsing_error); -} - -TEST_CASE("An optional argument does not consume arguments past the -- pseudo argument for argument with nargs set as number 1") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(1); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "--"}), "argument -o: expected 1 argument", argparse::parsing_error); -} - -TEST_CASE("An optional argument does not consume arguments past the -- pseudo argument for argument with nargs set as number 2") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(2); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "--"}), "argument -o: expected 2 arguments", argparse::parsing_error); -} - -TEST_CASE("An optional argument does not consume arguments past the -- pseudo argument for argument with nargs set as number 3") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(3); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "--"}), "argument -o: expected 3 arguments", argparse::parsing_error); -} - -TEST_CASE("An optional argument does not consume arguments past the -- pseudo argument for argument with nargs set as zero_or_one") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(argparse::zero_or_one); - - auto args = parser.parse_args(3, cstr_arr{"prog", "-o", "--"}); - - CHECK(!args.get("o")); -} - -TEST_CASE("An optional argument does not consume arguments past the -- pseudo argument for argument with nargs set as zero_or_more") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(argparse::zero_or_more); - - auto args = parser.parse_args(3, cstr_arr{"prog", "-o", "--"}); - - CHECK(args.get_value>("o") == std::vector()); -} - -TEST_CASE("An optional argument does not consume arguments past the -- pseudo argument for argument with nargs set as one_or_more") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(argparse::one_or_more); - - CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "--"}), "argument -o: expected at least one argument", argparse::parsing_error); -} - -TEST_CASE("An optional argument does not consume arguments past the -- pseudo argument for argument with nargs set as zero_or_more and followed by a positional argument") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o").nargs(argparse::zero_or_more); - parser.add_argument("pos"); - - auto args = parser.parse_args(4, cstr_arr{"prog", "-o", "--", "val"}); - - CHECK(args.get_value>("o") == std::vector()); - CHECK(args.get_value("pos") == "val"); -} - -TEST_CASE("Parsing joined short options does not throw for arguments with store true action") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-a").action(argparse::store_true); - parser.add_argument("-b").action(argparse::store_true); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "-ab"})); -} - -TEST_CASE("Parsing joined short options does not throw for arguments with store false action") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-a").action(argparse::store_false); - parser.add_argument("-b").action(argparse::store_false); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "-ab"})); -} - -TEST_CASE("Parsing joined short options does not throw for arguments with store const action") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-a").action(argparse::store_const).const_(10); - parser.add_argument("-b").action(argparse::store_const).const_(20); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "-ab"})); -} - -TEST_CASE("Parsing joined short options with store true action yields true for each of them") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("-a").action(argparse::store_true); - parser.add_argument("-b").action(argparse::store_true); - - auto args = parser.parse_args(2, cstr_arr{"prog", "-ab"}); - - CHECK(args.get_value("a") == true); - CHECK(args.get_value("b") == true); -} - -TEST_CASE("Parsing joined short options with store false action yields false for each of them") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("-a").action(argparse::store_false); - parser.add_argument("-b").action(argparse::store_false); - - auto args = parser.parse_args(2, cstr_arr{"prog", "-ab"}); - - CHECK(args.get_value("a") == false); - CHECK(args.get_value("b") == false); -} - -TEST_CASE("Parsing joined short options with store const action yields const value") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("-a").action(argparse::store_const).const_(10); - parser.add_argument("-b").action(argparse::store_const).const_(20); - - auto args = parser.parse_args(2, cstr_arr{"prog", "-ab"}); - - CHECK(args.get_value("a") == 10); - CHECK(args.get_value("b") == 20); -} - -TEST_CASE("Parsing long option with joined argument does not throw") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("--long-opt"); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "--long-opt=value"})); -} - -TEST_CASE("Parsing long option with joined argument yields its value") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("--long"); - - auto args = parser.parse_args(2, cstr_arr{"prog", "--long=value"}); - - CHECK(args.get_value("long") == "value"); -} - -TEST_CASE("Parsing long options with same prefix correctly recognises them plane options") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("--same").action(argparse::store_true); - parser.add_argument("--same-prefix").action(argparse::store_true); - - auto args = parser.parse_args(2, cstr_arr{"prog", "--same-prefix"}); - - CHECK(args.get_value("same") == false); -} - -TEST_CASE("Parsing long options with same prefix correctly recognises them options with joined argument") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("--same"); - parser.add_argument("--same-prefix"); - - auto args = parser.parse_args(2, cstr_arr{"prog", "--same-prefix=value"}); - - CHECK(!args.get("same")); -} - -TEST_CASE("Parsing short option with joined argument does not throw") -{ - auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); - parser.add_argument("-o"); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "-ovalue"})); -} - -TEST_CASE("Parsing short option with joined argument yields its value") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("-o"); - - auto args = parser.parse_args(2, cstr_arr{"prog", "-ovalue"}); - - CHECK(args.get_value("o") == "value"); -} - -TEST_CASE("Parsing joined short options and short option joined with argument does not throw order ao") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("-a").action(argparse::store_true); - parser.add_argument("-o"); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "-aovalue"})); -} - -TEST_CASE("Parsing joined short options and short option joined with argument does not throw order oa") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("-o"); - parser.add_argument("-a").action(argparse::store_true); - - CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "-aovalue"})); -} - -TEST_CASE("Parsing joined short options and short option joined with argument yields their values order ao") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("-a").action(argparse::store_true); - parser.add_argument("-o"); - - auto args = parser.parse_args(2, cstr_arr{"prog", "-aovalue"}); - - CHECK(args.get_value("a") == true); - CHECK(args.get_value("o") == "value"); -} - -TEST_CASE("Parsing joined short options and short option joined with argument yields their values order oa") -{ - auto parser = argparse::ArgumentParser(); - parser.add_argument("-o"); - parser.add_argument("-a").action(argparse::store_true); - - auto args = parser.parse_args(2, cstr_arr{"prog", "-aovalue"}); - - CHECK(args.get_value("a") == true); - CHECK(args.get_value("o") == "value"); -} - -TEST_CASE("Parsing long options does not affect short options") -{ - auto parser = argparse::ArgumentParser().add_help(false); - parser.add_argument("-b").action(argparse::store_true); - parser.add_argument("--bar").action(argparse::store_true); - parser.add_argument("-a").action(argparse::store_true); - parser.add_argument("-r").action(argparse::store_true); - - auto args = parser.parse_args(2, cstr_arr{"prog", "--bar"}); - - CHECK(args.get_value("b") == false); - CHECK(args.get_value("a") == false); - CHECK(args.get_value("r") == false); - CHECK(args.get_value("bar") == true); -} - -TEST_CASE("Parsing long options does not affect short options") -{ - auto parser = argparse::ArgumentParser().add_help(false); - parser.add_argument("-b").action(argparse::store_true); - parser.add_argument("--bar"); - parser.add_argument("-a").action(argparse::store_true); - parser.add_argument("-r").action(argparse::store_true); - - auto args = parser.parse_args(2, cstr_arr{"prog", "--bar=bar"}); - - CHECK(args.get_value("b") == false); - CHECK(args.get_value("a") == false); - CHECK(args.get_value("r") == false); - CHECK(args.get_value("bar") == "bar"); -} - -TEST_CASE("Parsing joined flags does not affect long options") -{ - auto parser = argparse::ArgumentParser().add_help(false); - parser.add_argument("--bar").action(argparse::store_true); - parser.add_argument("-b").action(argparse::store_true); - parser.add_argument("-a").action(argparse::store_true); - parser.add_argument("-r").action(argparse::store_true); - - auto args = parser.parse_args(2, cstr_arr{"prog", "-bar"}); - - CHECK(args.get_value("bar") == false); - CHECK(args.get_value("b") == true); - CHECK(args.get_value("a") == true); - CHECK(args.get_value("r") == true); -} diff --git a/test/unittest/test_parsing_optional.cpp b/test/unittest/test_parsing_optional.cpp new file mode 100644 index 00000000..d38e96e6 --- /dev/null +++ b/test/unittest/test_parsing_optional.cpp @@ -0,0 +1,2522 @@ +#include "argparse.h" + +#include "cstring_array.h" +#include "custom_a.h" +#include "custom_b.h" + +#include "doctest.h" + +#include +#include + + +using namespace std::string_literals; + +namespace bar +{ +inline auto operator==(Custom const & lhs, Custom const & rhs) -> bool +{ + return lhs.m_text == rhs.m_text; +} +} + +TEST_CASE("Parsing an optional argument yields false when it's missing") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o"); + + auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); + + CHECK(!parsed.get("o")); +} + +TEST_CASE("Parsing an optional argument throws an exception when it's missing argument") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o"); + + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "-o"}), "argument -o: expected one argument", argparse::parsing_error); +} + +TEST_CASE("Parsing an optional argument yields its value") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o"); + + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "v1"}); + + CHECK(parsed.get_value("o") == "v1"); +} + +TEST_CASE("Parsing an optional argument with store true action yields false when it's missing") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("-o").action(argparse::store_true); + + auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); + + CHECK(parsed.get_value("o") == false); +} + +TEST_CASE("Parsing an optional argument with store true action yields true when it's present") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("-o").action(argparse::store_true); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-o"}); + + CHECK(parsed.get_value("o") == true); +} + +TEST_CASE("Parsing an optional argument with store false action yields true when it's missing") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("-o").action(argparse::store_false); + + auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); + + CHECK(parsed.get_value("o") == true); +} + +TEST_CASE("Parsing an optional argument with store false action yields false when it's present") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("-o").action(argparse::store_false); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-o"}); + + CHECK(parsed.get_value("o") == false); +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with store const action yields false when it's missing", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string, foo::Custom, bar::Custom) +{ + auto parser = argparse::ArgumentParser(); + + if constexpr (std::is_integral_v) + { + parser.add_argument("-o").action(argparse::store_const).const_(T(65)); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").action(argparse::store_const).const_(T(1.125)); + } + else + { + parser.add_argument("-o").action(argparse::store_const).const_(T("bar")); + } + + auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); + + CHECK(!parsed.get("o")); +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with store const action yields const value", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string, foo::Custom, bar::Custom) +{ + auto parser = argparse::ArgumentParser(); + + if constexpr (std::is_integral_v) + { + parser.add_argument("-o").action(argparse::store_const).const_(T(65)); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").action(argparse::store_const).const_(T(1.125)); + } + else + { + parser.add_argument("-o").action(argparse::store_const).const_(T("bar")); + } + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-o"}); + + if constexpr (std::is_integral_v) + { + CHECK(parsed.get_value("o") == T(65)); + } + else if constexpr (std::is_floating_point_v) + { + CHECK(parsed.get_value("o") == T(1.125)); + } + else + { + CHECK(parsed.get_value("o") == T("bar")); + } +} + +TEST_CASE("Parsing an optional argument with help action yields false when it's missing") +{ + auto parser = argparse::ArgumentParser().add_help(false).handle(argparse::Handle::none); + parser.add_argument("-h").action(argparse::help); + + auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); + + CHECK(parsed.get_value("h") == false); +} + +TEST_CASE("Parsing an optional argument with help action yields true when it's present") +{ + auto parser = argparse::ArgumentParser().add_help(false).handle(argparse::Handle::none); + parser.add_argument("-h").action(argparse::help); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-h"}); + + CHECK(parsed.get_value("h") == true); +} + +TEST_CASE("Parsing an optional argument with version action yields false when it's missing") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-v").action(argparse::version); + + auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); + + CHECK(parsed.get_value("v") == false); +} + +TEST_CASE("Parsing an optional argument with version action yields true when it's present") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-v").action(argparse::version); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-v"}); + + CHECK(parsed.get_value("v") == true); +} + +TEST_CASE("Optional argument can be used with either short name") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("-o", "--option"); + + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "val"}); + + CHECK(parsed.get_value("option") == "val"); +} + +TEST_CASE("Optional argument can be used with either long name") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("-o", "--option"); + + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "--option", "val"}); + + CHECK(parsed.get_value("option") == "val"); +} + +TEST_CASE_TEMPLATE("Parsing an optional argument yields its requested type", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, foo::Custom, bar::Custom) +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("-o").type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); + + CHECK(parsed.get_value("o") == T(65)); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "65"}); + + CHECK(parsed.get_value("o") == T(65)); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "1.125"}); + + CHECK(parsed.get_value("o") == T(1.125)); + } + else + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "bar"}); + + CHECK(parsed.get_value("o") == T("bar")); + } +} + +TEST_CASE("Parsing an optional argument with invalid value throws an exception") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "not-a-number"}), "argument -o: invalid value: 'not-a-number'", argparse::parsing_error); + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "10gibberish"}), "argument -o: invalid value: '10gibberish'", argparse::parsing_error); +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with default value yields the default value when it's missing", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string, foo::Custom, bar::Custom) +{ + auto parser = argparse::ArgumentParser(); + + if constexpr (std::is_integral_v) + { + parser.add_argument("-o").default_(T(54)).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").default_(T(0.125)).template type(); + } + else + { + parser.add_argument("-o").default_(T("foo")).template type(); + } + + auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); + + if constexpr (std::is_integral_v) + { + CHECK(parsed.get_value("o") == T(54)); + } + else if constexpr (std::is_floating_point_v) + { + CHECK(parsed.get_value("o") == T(0.125)); + } + else + { + CHECK(parsed.get_value("o") == T("foo")); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with default value yields value of the argument's type", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string, foo::Custom, bar::Custom) +{ + auto parser = argparse::ArgumentParser(); + + if constexpr (std::is_integral_v) + { + parser.add_argument("-o").default_(T(54)).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").default_(T(0.125)).template type(); + } + else + { + parser.add_argument("-o").default_(T("foo")).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); + + CHECK(parsed.get_value("o") == T(65)); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "65"}); + + CHECK(parsed.get_value("o") == T(65)); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "1.125"}); + + CHECK(parsed.get_value("o") == T(1.125)); + } + else + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "bar"}); + + CHECK(parsed.get_value("o") == T("bar")); + } +} + +TEST_CASE("Parsing unrecognised optional argument throws an exception for one unrecognised argument") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-a"); + + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-a", "v1", "-b"}), "unrecognised arguments: -b", argparse::parsing_error); +} + +TEST_CASE("Parsing unrecognised optional argument throws an exception for two unrecognised arguments") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-a"); + + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-a", "v1", "-b", "-c"}), "unrecognised arguments: -b -c", argparse::parsing_error); +} + +TEST_CASE("Parsing unrecognised optional argument throws an exception for three unrecognised arguments") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-a"); + + CHECK_THROWS_WITH_AS(parser.parse_args(6, cstr_arr{"prog", "-a", "v1", "-b", "-c", "-d"}), "unrecognised arguments: -b -c -d", argparse::parsing_error); +} + +TEST_CASE("The resulting attribute name is based on for optional argument on its long name") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("-f", "--foo"); + + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-f", "val"}); + + CHECK(parsed.get("foo")); +} + +TEST_CASE("The resulting attribute name is based on for optional argument on its short name") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("-f"); + + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-f", "val"}); + + CHECK(parsed.get("f")); +} + +TEST_CASE("The resulting attribute name is based on for optional argument on dest parameter") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("-f", "--foo").dest("bar"); + + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-f", "val"}); + + CHECK(parsed.get("bar")); +} + +TEST_CASE("Parsing a missing optional argument with required true throws an exception") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").required(true); + + CHECK_THROWS_WITH_AS(parser.parse_args(1, cstr_arr{"prog"}), "the following arguments are required: -o", argparse::parsing_error); +} + +TEST_CASE("Parsing a missing optional argument with required false does not throw") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").required(false); + + CHECK_NOTHROW(parser.parse_args(1, cstr_arr{"prog"})); +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set accepts one of the values", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string, foo::Custom, bar::Custom) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).template type(); + + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "A"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "C"})); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(23), T(34)}).template type(); + + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "23"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "34"})); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(1.5)}).template type(); + + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.125"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "1.5"})); + } + else + { + parser.add_argument("-o").choices({T("foo"), T("bar")}).template type(); + + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "foo"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string, foo::Custom, bar::Custom) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(23), T(34)}).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "3"}), "argument -o: invalid choice: 3 (choose from 23, 34)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(1.5)}).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 1.5)", argparse::parsing_error); + } + else if constexpr (std::is_same_v) + { + parser.add_argument("-o").choices({T("foo"), T("bar")}).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } + else + { + parser.add_argument("-o").choices({T("foo"), T("bar")}).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "baz"}), "argument -o: invalid choice: (choose from , )", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number consumes the number of arguments for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(1).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "A"})); + } + else if constexpr (std::is_integral_v) + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "42"})); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"})); + } + else + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "foo"})); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number consumes the number of arguments for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(2).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "A", "C"})); + } + else if constexpr (std::is_integral_v) + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "42", "54"})); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "0.5", "1.125"})); + } + else + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number consumes the number of arguments for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(3).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "A", "C", "E"})); + } + else if constexpr (std::is_integral_v) + { + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "42", "54", "65"})); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "0.5", "1.125", "2.375"})); + } + else + { + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "baz"})); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number yields a list of arguments for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(1).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); + + CHECK(parsed.get_value>("o") == std::vector{'A'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "42"}); + + CHECK(parsed.get_value>("o") == std::vector{42}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}); + + CHECK(parsed.get_value>("o") == std::vector{0.5}); + } + else + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "foo"}); + + CHECK(parsed.get_value>("o") == std::vector{"foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number yields a list of arguments for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(2).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "A", "C"}); + + CHECK(parsed.get_value>("o") == std::vector{'A', 'C'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "42", "54"}); + + CHECK(parsed.get_value>("o") == std::vector{42, 54}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "0.5", "1.125"}); + + CHECK(parsed.get_value>("o") == std::vector{0.5, 1.125}); + } + else + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "bar"}); + + CHECK(parsed.get_value>("o") == std::vector{"foo", "bar"}); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number yields a list of arguments for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(3).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "A", "C", "E"}); + + CHECK(parsed.get_value>("o") == std::vector{'A', 'C', 'E'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "42", "54", "65"}); + + CHECK(parsed.get_value>("o") == std::vector{42, 54, 65}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "0.5", "1.125", "2.375"}); + + CHECK(parsed.get_value>("o") == std::vector{0.5, 1.125, 2.375}); + } + else + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "baz"}); + + CHECK(parsed.get_value>("o") == std::vector{"foo", "bar", "baz"}); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number throws an exception for incorrect arguments number for one argument and no provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(1).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "-o"}), "argument -o: expected 1 argument", argparse::parsing_error); +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number throws an exception for incorrect arguments number for two arguments and one provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(2).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "A"}), "argument -o: expected 2 arguments", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "42"}), "argument -o: expected 2 arguments", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}), "argument -o: expected 2 arguments", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "foo"}), "argument -o: expected 2 arguments", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number throws an exception for incorrect arguments number for three arguments and two provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(3).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "A", "B"}), "argument -o: expected 3 arguments", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "42", "54"}), "argument -o: expected 3 arguments", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "0.5", "1.125"}), "argument -o: expected 3 arguments", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "bar"}), "argument -o: expected 3 arguments", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number throws an exception for incorrect arguments number for one argument and two provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(1).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "A", "B"}), "unrecognised arguments: B", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "42", "54"}), "unrecognised arguments: 54", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "0.5", "1.125"}), "unrecognised arguments: 1.125", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "bar"}), "unrecognised arguments: bar", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number throws an exception for incorrect arguments number for one argument and three provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(1).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "A", "B", "C"}), "unrecognised arguments: B C", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "42", "54", "65"}), "unrecognised arguments: 54 65", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "0.5", "1.125", "2.375"}), "unrecognised arguments: 1.125 2.375", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "baz"}), "unrecognised arguments: bar baz", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as a number throws an exception for incorrect arguments number for two arguments and three provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(2).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "A", "B", "C"}), "unrecognised arguments: C", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "42", "54", "65"}), "unrecognised arguments: 65", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "0.5", "1.125", "2.375"}), "unrecognised arguments: 2.375", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "baz"}), "unrecognised arguments: baz", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as zero_or_one consumes single argument and yields it as a single item", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(argparse::zero_or_one).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); + + CHECK(parsed.get_value("o") == T('A')); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "42"}); + + CHECK(parsed.get_value("o") == T(42)); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}); + + CHECK(parsed.get_value("o") == T(0.5)); + } + else + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "foo"}); + + CHECK(parsed.get_value("o") == T("foo")); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as zero_or_one yields default value if no argument is provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").nargs(argparse::zero_or_one).default_(T('A')); + + auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); + + CHECK(parsed.get_value("o") == T('A')); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").nargs(argparse::zero_or_one).default_(T(10)); + + auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); + + CHECK(parsed.get_value("o") == T(10)); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").nargs(argparse::zero_or_one).default_(T(0.0625)); + + auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); + + CHECK(parsed.get_value("o") == T(0.0625)); + } + else + { + parser.add_argument("-o").nargs(argparse::zero_or_one).default_("foo"s); + + auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); + + CHECK(parsed.get_value("o") == "foo"); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as zero_or_one yields const value if option string is present and no argument is provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").nargs(argparse::zero_or_one).const_(T('A')); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-o"}); + + CHECK(parsed.get_value("o") == T('A')); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").nargs(argparse::zero_or_one).const_(T(5)); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-o"}); + + CHECK(parsed.get_value("o") == T(5)); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").nargs(argparse::zero_or_one).const_(T(0.875)); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-o"}); + + CHECK(parsed.get_value("o") == T(0.875)); + } + else + { + parser.add_argument("-o").nargs(argparse::zero_or_one).const_("foo"s); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-o"}); + + CHECK(parsed.get_value("o") == "foo"); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as zero_or_more yields an empty list if no arguments provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(argparse::zero_or_more).template type(); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "-o"}); + + CHECK(parsed.get_value>("o") == std::vector()); +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as zero_or_more consumes single argument and yields it as a list", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(argparse::zero_or_more).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); + + CHECK(parsed.get_value>("o") == std::vector{'A'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "42"}); + + CHECK(parsed.get_value>("o") == std::vector{42}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}); + + CHECK(parsed.get_value>("o") == std::vector{0.5}); + } + else + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "foo"}); + + CHECK(parsed.get_value>("o") == std::vector{"foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as zero_or_more consumes all available arguments and yields them as a list", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(argparse::zero_or_more).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "A", "C", "E"}); + + CHECK(parsed.get_value>("o") == std::vector{'A', 'C', 'E'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "42", "54", "65"}); + + CHECK(parsed.get_value>("o") == std::vector{42, 54, 65}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "0.5", "1.125", "2.375"}); + + CHECK(parsed.get_value>("o") == std::vector{0.5, 1.125, 2.375}); + } + else + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "baz"}); + + CHECK(parsed.get_value>("o") == std::vector{"foo", "bar", "baz"}); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as one_or_more throws an exception if no arguments provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(argparse::one_or_more).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "-o"}), "argument -o: expected at least one argument", argparse::parsing_error); +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as one_or_more consumes single argument and yields it as a list", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(argparse::one_or_more).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); + + CHECK(parsed.get_value>("o") == std::vector{'A'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "42"}); + + CHECK(parsed.get_value>("o") == std::vector{42}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}); + + CHECK(parsed.get_value>("o") == std::vector{0.5}); + } + else + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "foo"}); + + CHECK(parsed.get_value>("o") == std::vector{"foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with nargs set as one_or_more consumes all available arguments and yields them as a list", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(argparse::one_or_more).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "A", "C", "E"}); + + CHECK(parsed.get_value>("o") == std::vector{'A', 'C', 'E'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "42", "54", "65"}); + + CHECK(parsed.get_value>("o") == std::vector{42, 54, 65}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "0.5", "1.125", "2.375"}); + + CHECK(parsed.get_value>("o") == std::vector{0.5, 1.125, 2.375}); + } + else + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "baz"}); + + CHECK(parsed.get_value>("o") == std::vector{"foo", "bar", "baz"}); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as a number for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(1).template type(); + + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "A"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "C"})); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(1).template type(); + + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "11"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(1).template type(); + + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.125"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.25"})); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(1).template type(); + + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "foo"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as a number for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(2).template type(); + + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "A", "A"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "C", "C"})); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(2).template type(); + + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "11", "11"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "22", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(2).template type(); + + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "0.125", "0.125"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "0.25", "0.25"})); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(2).template type(); + + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "foo"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "bar", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as a number for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(3).template type(); + + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "A", "A", "A"})); + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "C", "C", "C"})); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(3).template type(); + + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "11", "11", "11"})); + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "22", "22", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(3).template type(); + + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "0.125", "0.125", "0.125"})); + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "0.25", "0.25", "0.25"})); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(3).template type(); + + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "foo", "foo"})); + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "bar", "bar", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as zero_or_one for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_one).template type(); + + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "A"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "C"})); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_one).template type(); + + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "11"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_one).template type(); + + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.125"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.25"})); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_one).template type(); + + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "foo"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as zero_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "A"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "C"})); + } + else if constexpr (std::is_integral_v) + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "11"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.125"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.25"})); + } + else + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "foo"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as zero_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "A", "A"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "C", "C"})); + } + else if constexpr (std::is_integral_v) + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "11", "11"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "22", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "0.125", "0.125"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "0.25", "0.25"})); + } + else + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "foo"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "bar", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as zero_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "A", "A", "A"})); + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "C", "C", "C"})); + } + else if constexpr (std::is_integral_v) + { + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "11", "11", "11"})); + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "22", "22", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "0.125", "0.125", "0.125"})); + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "0.25", "0.25", "0.25"})); + } + else + { + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "foo", "foo"})); + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "bar", "bar", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as one_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::one_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "A"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "C"})); + } + else if constexpr (std::is_integral_v) + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "11"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.125"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "0.25"})); + } + else + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "foo"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "-o", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as one_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::one_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "A", "A"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "C", "C"})); + } + else if constexpr (std::is_integral_v) + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "11", "11"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "22", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "0.125", "0.125"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "0.25", "0.25"})); + } + else + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "foo"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "-o", "bar", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set consumes the number of arguments for nargs set as one_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::one_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "A", "A", "A"})); + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "C", "C", "C"})); + } + else if constexpr (std::is_integral_v) + { + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "11", "11", "11"})); + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "22", "22", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "0.125", "0.125", "0.125"})); + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "0.25", "0.25", "0.25"})); + } + else + { + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "foo", "foo"})); + CHECK_NOTHROW(parser.parse_args(5, cstr_arr{"prog", "-o", "bar", "bar", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as a number for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(1).template type(); + + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); + + CHECK(parsed.get_value>("o") == std::vector{'A'}); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(1).template type(); + + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "11"}); + + CHECK(parsed.get_value>("o") == std::vector{11}); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(1).template type(); + + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "0.125"}); + + CHECK(parsed.get_value>("o") == std::vector{0.125}); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(1).template type(); + + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "foo"}); + + CHECK(parsed.get_value>("o") == std::vector{"foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as a number for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(2).template type(); + + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "A", "C"}); + + CHECK(parsed.get_value>("o") == std::vector{'A', 'C'}); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(2).template type(); + + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "11", "22"}); + + CHECK(parsed.get_value>("o") == std::vector{11, 22}); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(2).template type(); + + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "0.125", "0.25"}); + + CHECK(parsed.get_value>("o") == std::vector{0.125, 0.25}); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(2).template type(); + + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "bar"}); + + CHECK(parsed.get_value>("o") == std::vector{"foo", "bar"}); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as a number for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(3).template type(); + + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "A", "C", "A"}); + + CHECK(parsed.get_value>("o") == std::vector{'A', 'C', 'A'}); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(3).template type(); + + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "11", "22", "11"}); + + CHECK(parsed.get_value>("o") == std::vector{11, 22, 11}); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(3).template type(); + + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "0.125", "0.25", "0.125"}); + + CHECK(parsed.get_value>("o") == std::vector{0.125, 0.25, 0.125}); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(3).template type(); + + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "foo"}); + + CHECK(parsed.get_value>("o") == std::vector{"foo", "bar", "foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as zero_or_one for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_one).template type(); + + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); + + CHECK(parsed.get_value("o") == T('A')); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_one).template type(); + + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "11"}); + + CHECK(parsed.get_value("o") == T(11)); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_one).template type(); + + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "0.125"}); + + CHECK(parsed.get_value("o") == T(0.125)); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_one).template type(); + + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "foo"}); + + CHECK(parsed.get_value("o") == T("foo")); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as zero_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); + + CHECK(parsed.get_value>("o") == std::vector{'A'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "11"}); + + CHECK(parsed.get_value>("o") == std::vector{11}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "0.125"}); + + CHECK(parsed.get_value>("o") == std::vector{0.125}); + } + else + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "foo"}); + + CHECK(parsed.get_value>("o") == std::vector{"foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as zero_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "A", "A"}); + + CHECK(parsed.get_value>("o") == std::vector{'A', 'A'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "11", "11"}); + + CHECK(parsed.get_value>("o") == std::vector{11, 11}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "0.125", "0.125"}); + + CHECK(parsed.get_value>("o") == std::vector{0.125, 0.125}); + } + else + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "foo"}); + + CHECK(parsed.get_value>("o") == std::vector{"foo", "foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as zero_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "A", "A", "A"}); + + CHECK(parsed.get_value>("o") == std::vector{'A', 'A', 'A'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "11", "11", "11"}); + + CHECK(parsed.get_value>("o") == std::vector{11, 11, 11}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "0.125", "0.125", "0.125"}); + + CHECK(parsed.get_value>("o") == std::vector{0.125, 0.125, 0.125}); + } + else + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "foo", "foo"}); + + CHECK(parsed.get_value>("o") == std::vector{"foo", "foo", "foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as one_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::one_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "A"}); + + CHECK(parsed.get_value>("o") == std::vector{'A'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "11"}); + + CHECK(parsed.get_value>("o") == std::vector{11}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "0.125"}); + + CHECK(parsed.get_value>("o") == std::vector{0.125}); + } + else + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "-o", "foo"}); + + CHECK(parsed.get_value>("o") == std::vector{"foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as one_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::one_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "A", "A"}); + + CHECK(parsed.get_value>("o") == std::vector{'A', 'A'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "11", "11"}); + + CHECK(parsed.get_value>("o") == std::vector{11, 11}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "0.125", "0.125"}); + + CHECK(parsed.get_value>("o") == std::vector{0.125, 0.125}); + } + else + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "foo"}); + + CHECK(parsed.get_value>("o") == std::vector{"foo", "foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set yields the arguments for nargs set as one_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::one_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "A", "A", "A"}); + + CHECK(parsed.get_value>("o") == std::vector{'A', 'A', 'A'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "11", "11", "11"}); + + CHECK(parsed.get_value>("o") == std::vector{11, 11, 11}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "0.125", "0.125", "0.125"}); + + CHECK(parsed.get_value>("o") == std::vector{0.125, 0.125, 0.125}); + } + else + { + auto const parsed = parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "foo", "foo"}); + + CHECK(parsed.get_value>("o") == std::vector{"foo", "foo", "foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as a number for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(1).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(1).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(1).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(1).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as a number for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(2).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "A", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(2).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "11", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(2).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "0.125", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(2).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as a number for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(3).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "A", "C", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(3).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "11", "22", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(3).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "0.125", "0.25", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(3).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as zero_or_one for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_one).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_one).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_one).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_one).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as zero_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as zero_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "A", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "11", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "0.125", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as zero_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::zero_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "A", "C", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "11", "22", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "0.125", "0.25", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as one_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::one_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as one_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::one_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "A", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "11", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "0.125", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing an optional argument with choices set throws an exception on incorrect value for nargs set as one_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("-o").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("-o").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("-o").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); + } + else + { + parser.add_argument("-o").choices({"foo"s, "bar"s}).nargs(argparse::one_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "A", "C", "B"}), "argument -o: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "11", "22", "33"}), "argument -o: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "0.125", "0.25", "0.5"}), "argument -o: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "baz"}), "argument -o: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE("An optional argument does not consume another optional argument for simple argument") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o"); + parser.add_argument("-p"); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "-p"}), "argument -o: expected one argument", argparse::parsing_error); +} + +TEST_CASE("An optional argument does not consume another optional argument for argument with nargs set as number 1") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(1); + parser.add_argument("-p"); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "-p"}), "argument -o: expected 1 argument", argparse::parsing_error); +} + +TEST_CASE("An optional argument does not consume another optional argument for argument with nargs set as number 2") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(2); + parser.add_argument("-p"); + + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "-o", "foo", "-p"}), "argument -o: expected 2 arguments", argparse::parsing_error); +} + +TEST_CASE("An optional argument does not consume another optional argument for argument with nargs set as number 3") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(3); + parser.add_argument("-p"); + + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "-o", "foo", "bar", "-p"}), "argument -o: expected 3 arguments", argparse::parsing_error); +} + +TEST_CASE("An optional argument does not consume another optional argument for argument with nargs set as zero_or_one") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(argparse::zero_or_one); + parser.add_argument("-p"); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "-p"}), "argument -p: expected one argument", argparse::parsing_error); +} + +TEST_CASE("An optional argument does not consume another optional argument for argument with nargs set as zero_or_more") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(argparse::zero_or_more); + parser.add_argument("-p"); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "-p"}), "argument -p: expected one argument", argparse::parsing_error); +} + +TEST_CASE("An optional argument does not consume another optional argument for argument with nargs set as one_or_more") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(argparse::one_or_more); + parser.add_argument("-p"); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "-p"}), "argument -o: expected at least one argument", argparse::parsing_error); +} + +TEST_CASE("An optional argument does not consume arguments past the -- pseudo argument for simple argument") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o"); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "--"}), "argument -o: expected one argument", argparse::parsing_error); +} + +TEST_CASE("An optional argument does not consume arguments past the -- pseudo argument for argument with nargs set as number 1") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(1); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "--"}), "argument -o: expected 1 argument", argparse::parsing_error); +} + +TEST_CASE("An optional argument does not consume arguments past the -- pseudo argument for argument with nargs set as number 2") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(2); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "--"}), "argument -o: expected 2 arguments", argparse::parsing_error); +} + +TEST_CASE("An optional argument does not consume arguments past the -- pseudo argument for argument with nargs set as number 3") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(3); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "--"}), "argument -o: expected 3 arguments", argparse::parsing_error); +} + +TEST_CASE("An optional argument does not consume arguments past the -- pseudo argument for argument with nargs set as zero_or_one") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(argparse::zero_or_one); + + auto args = parser.parse_args(3, cstr_arr{"prog", "-o", "--"}); + + CHECK(!args.get("o")); +} + +TEST_CASE("An optional argument does not consume arguments past the -- pseudo argument for argument with nargs set as zero_or_more") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(argparse::zero_or_more); + + auto args = parser.parse_args(3, cstr_arr{"prog", "-o", "--"}); + + CHECK(args.get_value>("o") == std::vector()); +} + +TEST_CASE("An optional argument does not consume arguments past the -- pseudo argument for argument with nargs set as one_or_more") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(argparse::one_or_more); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "-o", "--"}), "argument -o: expected at least one argument", argparse::parsing_error); +} + +TEST_CASE("An optional argument does not consume arguments past the -- pseudo argument for argument with nargs set as zero_or_more and followed by a positional argument") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o").nargs(argparse::zero_or_more); + parser.add_argument("pos"); + + auto args = parser.parse_args(4, cstr_arr{"prog", "-o", "--", "val"}); + + CHECK(args.get_value>("o") == std::vector()); + CHECK(args.get_value("pos") == "val"); +} + +TEST_CASE("Parsing joined short options does not throw for arguments with store true action") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-a").action(argparse::store_true); + parser.add_argument("-b").action(argparse::store_true); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "-ab"})); +} + +TEST_CASE("Parsing joined short options does not throw for arguments with store false action") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-a").action(argparse::store_false); + parser.add_argument("-b").action(argparse::store_false); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "-ab"})); +} + +TEST_CASE("Parsing joined short options does not throw for arguments with store const action") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-a").action(argparse::store_const).const_(10); + parser.add_argument("-b").action(argparse::store_const).const_(20); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "-ab"})); +} + +TEST_CASE("Parsing joined short options with store true action yields true for each of them") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("-a").action(argparse::store_true); + parser.add_argument("-b").action(argparse::store_true); + + auto args = parser.parse_args(2, cstr_arr{"prog", "-ab"}); + + CHECK(args.get_value("a") == true); + CHECK(args.get_value("b") == true); +} + +TEST_CASE("Parsing joined short options with store false action yields false for each of them") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("-a").action(argparse::store_false); + parser.add_argument("-b").action(argparse::store_false); + + auto args = parser.parse_args(2, cstr_arr{"prog", "-ab"}); + + CHECK(args.get_value("a") == false); + CHECK(args.get_value("b") == false); +} + +TEST_CASE("Parsing joined short options with store const action yields const value") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("-a").action(argparse::store_const).const_(10); + parser.add_argument("-b").action(argparse::store_const).const_(20); + + auto args = parser.parse_args(2, cstr_arr{"prog", "-ab"}); + + CHECK(args.get_value("a") == 10); + CHECK(args.get_value("b") == 20); +} + +TEST_CASE("Parsing long option with joined argument does not throw") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("--long-opt"); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "--long-opt=value"})); +} + +TEST_CASE("Parsing long option with joined argument yields its value") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("--long"); + + auto args = parser.parse_args(2, cstr_arr{"prog", "--long=value"}); + + CHECK(args.get_value("long") == "value"); +} + +TEST_CASE("Parsing long options with same prefix correctly recognises them plane options") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("--same").action(argparse::store_true); + parser.add_argument("--same-prefix").action(argparse::store_true); + + auto args = parser.parse_args(2, cstr_arr{"prog", "--same-prefix"}); + + CHECK(args.get_value("same") == false); +} + +TEST_CASE("Parsing long options with same prefix correctly recognises them options with joined argument") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("--same"); + parser.add_argument("--same-prefix"); + + auto args = parser.parse_args(2, cstr_arr{"prog", "--same-prefix=value"}); + + CHECK(!args.get("same")); +} + +TEST_CASE("Parsing short option with joined argument does not throw") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("-o"); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "-ovalue"})); +} + +TEST_CASE("Parsing short option with joined argument yields its value") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("-o"); + + auto args = parser.parse_args(2, cstr_arr{"prog", "-ovalue"}); + + CHECK(args.get_value("o") == "value"); +} + +TEST_CASE("Parsing joined short options and short option joined with argument does not throw order ao") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("-a").action(argparse::store_true); + parser.add_argument("-o"); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "-aovalue"})); +} + +TEST_CASE("Parsing joined short options and short option joined with argument does not throw order oa") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("-o"); + parser.add_argument("-a").action(argparse::store_true); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "-aovalue"})); +} + +TEST_CASE("Parsing joined short options and short option joined with argument yields their values order ao") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("-a").action(argparse::store_true); + parser.add_argument("-o"); + + auto args = parser.parse_args(2, cstr_arr{"prog", "-aovalue"}); + + CHECK(args.get_value("a") == true); + CHECK(args.get_value("o") == "value"); +} + +TEST_CASE("Parsing joined short options and short option joined with argument yields their values order oa") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("-o"); + parser.add_argument("-a").action(argparse::store_true); + + auto args = parser.parse_args(2, cstr_arr{"prog", "-aovalue"}); + + CHECK(args.get_value("a") == true); + CHECK(args.get_value("o") == "value"); +} + +TEST_CASE("Parsing long options does not affect short options") +{ + auto parser = argparse::ArgumentParser().add_help(false); + parser.add_argument("-b").action(argparse::store_true); + parser.add_argument("--bar").action(argparse::store_true); + parser.add_argument("-a").action(argparse::store_true); + parser.add_argument("-r").action(argparse::store_true); + + auto args = parser.parse_args(2, cstr_arr{"prog", "--bar"}); + + CHECK(args.get_value("b") == false); + CHECK(args.get_value("a") == false); + CHECK(args.get_value("r") == false); + CHECK(args.get_value("bar") == true); +} + +TEST_CASE("Parsing long options does not affect short options") +{ + auto parser = argparse::ArgumentParser().add_help(false); + parser.add_argument("-b").action(argparse::store_true); + parser.add_argument("--bar"); + parser.add_argument("-a").action(argparse::store_true); + parser.add_argument("-r").action(argparse::store_true); + + auto args = parser.parse_args(2, cstr_arr{"prog", "--bar=bar"}); + + CHECK(args.get_value("b") == false); + CHECK(args.get_value("a") == false); + CHECK(args.get_value("r") == false); + CHECK(args.get_value("bar") == "bar"); +} + +TEST_CASE("Parsing joined flags does not affect long options") +{ + auto parser = argparse::ArgumentParser().add_help(false); + parser.add_argument("--bar").action(argparse::store_true); + parser.add_argument("-b").action(argparse::store_true); + parser.add_argument("-a").action(argparse::store_true); + parser.add_argument("-r").action(argparse::store_true); + + auto args = parser.parse_args(2, cstr_arr{"prog", "-bar"}); + + CHECK(args.get_value("bar") == false); + CHECK(args.get_value("b") == true); + CHECK(args.get_value("a") == true); + CHECK(args.get_value("r") == true); +} diff --git a/test/unittest/test_parsing_positional.cpp b/test/unittest/test_parsing_positional.cpp new file mode 100644 index 00000000..816fb21f --- /dev/null +++ b/test/unittest/test_parsing_positional.cpp @@ -0,0 +1,1916 @@ +#include "argparse.h" + +#include "cstring_array.h" +#include "custom_a.h" +#include "custom_b.h" + +#include "doctest.h" + +#include +#include + + +using namespace std::string_literals; + +namespace bar +{ +inline auto operator==(Custom const & lhs, Custom const & rhs) -> bool +{ + return lhs.m_text == rhs.m_text; +} +} + +TEST_CASE("Parsing a positional argument yields its value") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("p1"); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "v1"}); + + CHECK(parsed.get_value("p1") == "v1"); +} + +TEST_CASE_TEMPLATE("Parsing a positional argument yields its requested type", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, foo::Custom, bar::Custom) +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("pos").type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "A"}); + + CHECK(parsed.get_value("pos") == T(65)); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "65"}); + + CHECK(parsed.get_value("pos") == T(65)); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "1.125"}); + + CHECK(parsed.get_value("pos") == T(1.125)); + } + else + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "bar"}); + + CHECK(parsed.get_value("pos") == T("bar")); + } +} + +TEST_CASE("Parsing a positional argument with invalid value throws an exception") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "not-a-number"}), "argument pos: invalid value: 'not-a-number'", argparse::parsing_error); + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "10gibberish"}), "argument pos: invalid value: '10gibberish'", argparse::parsing_error); +} + +TEST_CASE("Parsing missing positional argument throws an exception for one missing argument") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("p1"); + + CHECK_THROWS_WITH_AS(parser.parse_args(1, cstr_arr{"prog"}), "the following arguments are required: p1", argparse::parsing_error); +} + +TEST_CASE("Parsing missing positional argument throws an exception for two missing arguments") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("p1"); + parser.add_argument("p2"); + + CHECK_THROWS_WITH_AS(parser.parse_args(1, cstr_arr{"prog"}), "the following arguments are required: p1 p2", argparse::parsing_error); +} + +TEST_CASE("Parsing missing positional argument throws an exception for three missing arguments") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("p1"); + parser.add_argument("p2"); + parser.add_argument("p3"); + + CHECK_THROWS_WITH_AS(parser.parse_args(1, cstr_arr{"prog"}), "the following arguments are required: p1 p2 p3", argparse::parsing_error); +} + +TEST_CASE("Parsing unrecognised positional argument throws an exception for one unrecognised argument") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("p1"); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "v1", "v2"}), "unrecognised arguments: v2", argparse::parsing_error); +} + +TEST_CASE("Parsing unrecognised positional argument throws an exception for two unrecognised arguments") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("p1"); + + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "v1", "v2", "v3"}), "unrecognised arguments: v2 v3", argparse::parsing_error); +} + +TEST_CASE("Parsing unrecognised positional argument throws an exception for three unrecognised arguments") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("p1"); + CHECK_THROWS_WITH_AS(parser.parse_args(5, cstr_arr{"prog", "v1", "v2", "v3", "v4"}), "unrecognised arguments: v2 v3 v4", argparse::parsing_error); +} + +TEST_CASE("The resulting attribute name is based on for positional argument on its name") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("foo"); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "val"}); + + CHECK(parsed.get("foo")); +} + +TEST_CASE("The resulting attribute name is based on for positional argument on dest parameter") +{ + auto parser = argparse::ArgumentParser(); + parser.add_argument("foo").dest("bar"); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "val"}); + + CHECK(parsed.get("bar")); +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set accepts one of the values", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string, foo::Custom, bar::Custom) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).template type(); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "A"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "C"})); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(23), T(34)}).template type(); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "23"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "34"})); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(1.5)}).template type(); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.125"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "1.5"})); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).template type(); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "foo"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string, foo::Custom, bar::Custom) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(23), T(34)}).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "3"}), "argument pos: invalid choice: 3 (choose from 23, 34)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(1.5)}).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 1.5)", argparse::parsing_error); + } + else if constexpr (std::is_same_v) + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "baz"}), "argument pos: invalid choice: (choose from , )", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number consumes the number of arguments for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(1).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "A"})); + } + else if constexpr (std::is_integral_v) + { + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "42"})); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.5"})); + } + else + { + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "foo"})); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number consumes the number of arguments for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(2).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "A", "C"})); + } + else if constexpr (std::is_integral_v) + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "42", "54"})); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "0.5", "1.125"})); + } + else + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "foo", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number consumes the number of arguments for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(3).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "A", "C", "E"})); + } + else if constexpr (std::is_integral_v) + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "42", "54", "65"})); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "0.5", "1.125", "2.375"})); + } + else + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "baz"})); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number yields a list of arguments for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(1).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "B"}); + + CHECK(parsed.get_value>("pos") == std::vector{'B'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "42"}); + + CHECK(parsed.get_value>("pos") == std::vector{42}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "0.5"}); + + CHECK(parsed.get_value>("pos") == std::vector{0.5}); + } + else + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "foo"}); + + CHECK(parsed.get_value>("pos") == std::vector{"foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number yields a list of arguments for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(2).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "B", "D"}); + + CHECK(parsed.get_value>("pos") == std::vector{'B', 'D'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "42", "54"}); + + CHECK(parsed.get_value>("pos") == std::vector{42, 54}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "0.5", "1.125"}); + + CHECK(parsed.get_value>("pos") == std::vector{0.5, 1.125}); + } + else + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "foo", "bar"}); + + CHECK(parsed.get_value>("pos") == std::vector{"foo", "bar"}); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number yields a list of arguments for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(3).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "B", "D", "F"}); + + CHECK(parsed.get_value>("pos") == std::vector{'B', 'D', 'F'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "42", "54", "65"}); + + CHECK(parsed.get_value>("pos") == std::vector{42, 54, 65}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "0.5", "1.125", "2.375"}); + + CHECK(parsed.get_value>("pos") == std::vector{0.5, 1.125, 2.375}); + } + else + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "baz"}); + + CHECK(parsed.get_value>("pos") == std::vector{"foo", "bar", "baz"}); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number throws an exception for incorrect arguments number for one argument and no provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(1).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(1, cstr_arr{"prog"}), "the following arguments are required: pos", argparse::parsing_error); +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number throws an exception for incorrect arguments number for two arguments and one provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(2).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "A"}), "the following arguments are required: pos", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "42"}), "the following arguments are required: pos", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "0.5"}), "the following arguments are required: pos", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "foo"}), "the following arguments are required: pos", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number throws an exception for incorrect arguments number for three arguments and two provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(3).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "A", "B"}), "the following arguments are required: pos", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "42", "54"}), "the following arguments are required: pos", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "0.5", "1.125"}), "the following arguments are required: pos", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "foo", "bar"}), "the following arguments are required: pos", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number throws an exception for incorrect arguments number for one argument and two provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(1).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "A", "B"}), "unrecognised arguments: B", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "42", "54"}), "unrecognised arguments: 54", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "0.5", "1.125"}), "unrecognised arguments: 1.125", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "foo", "bar"}), "unrecognised arguments: bar", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number throws an exception for incorrect arguments number for one arguments and three provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(1).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "A", "B", "C"}), "unrecognised arguments: B C", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "42", "54", "65"}), "unrecognised arguments: 54 65", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "0.5", "1.125", "2.375"}), "unrecognised arguments: 1.125 2.375", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "baz"}), "unrecognised arguments: bar baz", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as a number throws an exception for incorrect arguments number for two arguments and three provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(2).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "A", "B", "C"}), "unrecognised arguments: C", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "42", "54", "65"}), "unrecognised arguments: 65", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "0.5", "1.125", "2.375"}), "unrecognised arguments: 2.375", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "baz"}), "unrecognised arguments: baz", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as zero_or_one consumes single argument and yields it as a single item", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(argparse::zero_or_one).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "A"}); + + CHECK(parsed.get_value("pos") == T('A')); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "42"}); + + CHECK(parsed.get_value("pos") == T(42)); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "0.5"}); + + CHECK(parsed.get_value("pos") == T(0.5)); + } + else + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "foo"}); + + CHECK(parsed.get_value("pos") == T("foo")); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as zero_or_one yields default value if no argument is provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").nargs(argparse::zero_or_one).default_(T('A')); + + auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); + + CHECK(parsed.get_value("pos") == T('A')); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").nargs(argparse::zero_or_one).default_(T(10)); + + auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); + + CHECK(parsed.get_value("pos") == T(10)); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").nargs(argparse::zero_or_one).default_(T(0.0625)); + + auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); + + CHECK(parsed.get_value("pos") == T(0.0625)); + } + else + { + parser.add_argument("pos").nargs(argparse::zero_or_one).default_("foo"s); + + auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); + + CHECK(parsed.get_value("pos") == T("foo")); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as zero_or_more yields an empty list if no arguments provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(argparse::zero_or_more).template type(); + + auto const parsed = parser.parse_args(1, cstr_arr{"prog"}); + + CHECK(parsed.get_value>("pos") == std::vector()); +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as zero_or_more consumes single argument and yields it as a list", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(argparse::zero_or_more).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "A"}); + + CHECK(parsed.get_value>("pos") == std::vector{'A'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "42"}); + + CHECK(parsed.get_value>("pos") == std::vector{42}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "0.5"}); + + CHECK(parsed.get_value>("pos") == std::vector{0.5}); + } + else + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "foo"}); + + CHECK(parsed.get_value>("pos") == std::vector{"foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as zero_or_more consumes all available arguments and yields them as a list", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(argparse::zero_or_more).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "A", "G", "J"}); + + CHECK(parsed.get_value>("pos") == std::vector{'A', 'G', 'J'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "42", "54", "65"}); + + CHECK(parsed.get_value>("pos") == std::vector{42, 54, 65}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "0.5", "1.125", "2.375"}); + + CHECK(parsed.get_value>("pos") == std::vector{0.5, 1.125, 2.375}); + } + else + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "baz"}); + + CHECK(parsed.get_value>("pos") == std::vector{"foo", "bar", "baz"}); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as one_or_more throws an exception if no arguments provided", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(argparse::one_or_more).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(1, cstr_arr{"prog"}), "the following arguments are required: pos", argparse::parsing_error); +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as one_or_more consumes single argument and yields it as a list", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(argparse::one_or_more).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "A"}); + + CHECK(parsed.get_value>("pos") == std::vector{'A'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "42"}); + + CHECK(parsed.get_value>("pos") == std::vector{42}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "0.5"}); + + CHECK(parsed.get_value>("pos") == std::vector{0.5}); + } + else + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "foo"}); + + CHECK(parsed.get_value>("pos") == std::vector{"foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with nargs set as one_or_more consumes all available arguments and yields them as a list", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("pos").nargs(argparse::one_or_more).template type(); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "A", "G", "J"}); + + CHECK(parsed.get_value>("pos") == std::vector{'A', 'G', 'J'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "42", "54", "65"}); + + CHECK(parsed.get_value>("pos") == std::vector{42, 54, 65}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "0.5", "1.125", "2.375"}); + + CHECK(parsed.get_value>("pos") == std::vector{0.5, 1.125, 2.375}); + } + else + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "baz"}); + + CHECK(parsed.get_value>("pos") == std::vector{"foo", "bar", "baz"}); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as a number for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(1).template type(); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "A"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "C"})); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(1).template type(); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "11"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(1).template type(); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.125"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.25"})); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(1).template type(); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "foo"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as a number for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(2).template type(); + + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "A", "A"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "C", "C"})); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(2).template type(); + + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "11", "11"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "22", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(2).template type(); + + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "0.125", "0.125"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "0.25", "0.25"})); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(2).template type(); + + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "foo", "foo"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "bar", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as a number for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(3).template type(); + + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "A", "A", "A"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "C", "C", "C"})); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(3).template type(); + + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "11", "11", "11"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "22", "22", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(3).template type(); + + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "0.125", "0.125", "0.125"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "0.25", "0.25", "0.25"})); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(3).template type(); + + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "foo", "foo", "foo"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "bar", "bar", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as zero_or_one for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_one).template type(); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "A"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "C"})); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_one).template type(); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "11"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_one).template type(); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.125"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.25"})); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_one).template type(); + + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "foo"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as zero_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "A"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "C"})); + } + else if constexpr (std::is_integral_v) + { + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "11"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.125"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.25"})); + } + else + { + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "foo"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as zero_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "A", "A"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "C", "C"})); + } + else if constexpr (std::is_integral_v) + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "11", "11"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "22", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "0.125", "0.125"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "0.25", "0.25"})); + } + else + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "foo", "foo"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "bar", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as zero_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "A", "A", "A"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "C", "C", "C"})); + } + else if constexpr (std::is_integral_v) + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "11", "11", "11"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "22", "22", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "0.125", "0.125", "0.125"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "0.25", "0.25", "0.25"})); + } + else + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "foo", "foo", "foo"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "bar", "bar", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as one_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::one_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "A"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "C"})); + } + else if constexpr (std::is_integral_v) + { + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "11"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.125"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "0.25"})); + } + else + { + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "foo"})); + CHECK_NOTHROW(parser.parse_args(2, cstr_arr{"prog", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as one_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::one_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "A", "A"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "C", "C"})); + } + else if constexpr (std::is_integral_v) + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "11", "11"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "22", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "0.125", "0.125"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "0.25", "0.25"})); + } + else + { + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "foo", "foo"})); + CHECK_NOTHROW(parser.parse_args(3, cstr_arr{"prog", "bar", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set consumes the number of arguments for nargs set as one_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::one_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "A", "A", "A"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "C", "C", "C"})); + } + else if constexpr (std::is_integral_v) + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "11", "11", "11"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "22", "22", "22"})); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "0.125", "0.125", "0.125"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "0.25", "0.25", "0.25"})); + } + else + { + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "foo", "foo", "foo"})); + CHECK_NOTHROW(parser.parse_args(4, cstr_arr{"prog", "bar", "bar", "bar"})); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as a number for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(1).template type(); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "A"}); + + CHECK(parsed.get_value>("pos") == std::vector{'A'}); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(1).template type(); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "11"}); + + CHECK(parsed.get_value>("pos") == std::vector{11}); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(1).template type(); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "0.125"}); + + CHECK(parsed.get_value>("pos") == std::vector{0.125}); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(1).template type(); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "foo"}); + + CHECK(parsed.get_value>("pos") == std::vector{"foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as a number for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(2).template type(); + + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "A", "C"}); + + CHECK(parsed.get_value>("pos") == std::vector{'A', 'C'}); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(2).template type(); + + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "11", "22"}); + + CHECK(parsed.get_value>("pos") == std::vector{11, 22}); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(2).template type(); + + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "0.125", "0.25"}); + + CHECK(parsed.get_value>("pos") == std::vector{0.125, 0.25}); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(2).template type(); + + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "foo", "bar"}); + + CHECK(parsed.get_value>("pos") == std::vector{"foo", "bar"}); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as a number for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(3).template type(); + + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "A", "C", "A"}); + + CHECK(parsed.get_value>("pos") == std::vector{'A', 'C', 'A'}); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(3).template type(); + + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "11", "22", "11"}); + + CHECK(parsed.get_value>("pos") == std::vector{11, 22, 11}); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(3).template type(); + + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "0.125", "0.25", "0.125"}); + + CHECK(parsed.get_value>("pos") == std::vector{0.125, 0.25, 0.125}); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(3).template type(); + + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "foo"}); + + CHECK(parsed.get_value>("pos") == std::vector{"foo", "bar", "foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as zero_or_one for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_one).template type(); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "A"}); + + CHECK(parsed.get_value("pos") == T('A')); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_one).template type(); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "11"}); + + CHECK(parsed.get_value("pos") == T(11)); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_one).template type(); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "0.125"}); + + CHECK(parsed.get_value("pos") == T(0.125)); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_one).template type(); + + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "foo"}); + + CHECK(parsed.get_value("pos") == T("foo")); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as zero_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "A"}); + + CHECK(parsed.get_value>("pos") == std::vector{'A'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "11"}); + + CHECK(parsed.get_value>("pos") == std::vector{11}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "0.125"}); + + CHECK(parsed.get_value>("pos") == std::vector{0.125}); + } + else + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "foo"}); + + CHECK(parsed.get_value>("pos") == std::vector{"foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as zero_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "A", "A"}); + + CHECK(parsed.get_value>("pos") == std::vector{'A', 'A'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "11", "11"}); + + CHECK(parsed.get_value>("pos") == std::vector{11, 11}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "0.125", "0.125"}); + + CHECK(parsed.get_value>("pos") == std::vector{0.125, 0.125}); + } + else + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "foo", "foo"}); + + CHECK(parsed.get_value>("pos") == std::vector{"foo", "foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as zero_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "A", "A", "A"}); + + CHECK(parsed.get_value>("pos") == std::vector{'A', 'A', 'A'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "11", "11", "11"}); + + CHECK(parsed.get_value>("pos") == std::vector{11, 11, 11}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "0.125", "0.125", "0.125"}); + + CHECK(parsed.get_value>("pos") == std::vector{0.125, 0.125, 0.125}); + } + else + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "foo", "foo", "foo"}); + + CHECK(parsed.get_value>("pos") == std::vector{"foo", "foo", "foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as one_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::one_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "A"}); + + CHECK(parsed.get_value>("pos") == std::vector{'A'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "11"}); + + CHECK(parsed.get_value>("pos") == std::vector{11}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "0.125"}); + + CHECK(parsed.get_value>("pos") == std::vector{0.125}); + } + else + { + auto const parsed = parser.parse_args(2, cstr_arr{"prog", "foo"}); + + CHECK(parsed.get_value>("pos") == std::vector{"foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as one_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::one_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "A", "A"}); + + CHECK(parsed.get_value>("pos") == std::vector{'A', 'A'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "11", "11"}); + + CHECK(parsed.get_value>("pos") == std::vector{11, 11}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "0.125", "0.125"}); + + CHECK(parsed.get_value>("pos") == std::vector{0.125, 0.125}); + } + else + { + auto const parsed = parser.parse_args(3, cstr_arr{"prog", "foo", "foo"}); + + CHECK(parsed.get_value>("pos") == std::vector{"foo", "foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set yields the arguments for nargs set as one_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::one_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "A", "A", "A"}); + + CHECK(parsed.get_value>("pos") == std::vector{'A', 'A', 'A'}); + } + else if constexpr (std::is_integral_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "11", "11", "11"}); + + CHECK(parsed.get_value>("pos") == std::vector{11, 11, 11}); + } + else if constexpr (std::is_floating_point_v) + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "0.125", "0.125", "0.125"}); + + CHECK(parsed.get_value>("pos") == std::vector{0.125, 0.125, 0.125}); + } + else + { + auto const parsed = parser.parse_args(4, cstr_arr{"prog", "foo", "foo", "foo"}); + + CHECK(parsed.get_value>("pos") == std::vector{"foo", "foo", "foo"}); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as a number for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(1).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(1).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(1).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(1).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as a number for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(2).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "A", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(2).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "11", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(2).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "0.125", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(2).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "foo", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as a number for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(3).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "A", "C", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(3).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "11", "22", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(3).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "0.125", "0.25", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(3).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as zero_or_one for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_one).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_one).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_one).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_one).template type(); + + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as zero_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as zero_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "A", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "11", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "0.125", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "foo", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as zero_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::zero_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::zero_or_more).template type(); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::zero_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "A", "C", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "11", "22", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "0.125", "0.25", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as one_or_more for one argument", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::one_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(2, cstr_arr{"prog", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as one_or_more for two arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::one_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "A", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "11", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "0.125", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(3, cstr_arr{"prog", "foo", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE_TEMPLATE("Parsing a positional argument with choices set throws an exception on incorrect value for nargs set as one_or_more for three arguments", T, char, signed char, unsigned char, short int, unsigned short int, int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, float, double, long double, std::string) +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + parser.add_argument("pos").choices({T('A'), T('C')}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_integral_v) + { + parser.add_argument("pos").choices({T(11), T(22)}).nargs(argparse::one_or_more).template type(); + } + else if constexpr (std::is_floating_point_v) + { + parser.add_argument("pos").choices({T(0.125), T(0.25)}).nargs(argparse::one_or_more).template type(); + } + else + { + parser.add_argument("pos").choices({T("foo"), T("bar")}).nargs(argparse::one_or_more).template type(); + } + + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "A", "C", "B"}), "argument pos: invalid choice: B (choose from A, C)", argparse::parsing_error); + } + else if constexpr (std::is_integral_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "11", "22", "33"}), "argument pos: invalid choice: 33 (choose from 11, 22)", argparse::parsing_error); + } + else if constexpr (std::is_floating_point_v) + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "0.125", "0.25", "0.5"}), "argument pos: invalid choice: 0.5 (choose from 0.125, 0.25)", argparse::parsing_error); + } + else + { + CHECK_THROWS_WITH_AS(parser.parse_args(4, cstr_arr{"prog", "foo", "bar", "baz"}), "argument pos: invalid choice: \"baz\" (choose from \"foo\", \"bar\")", argparse::parsing_error); + } +} + +TEST_CASE("Parsing missing positional argument with nargs set throws an exception for one missing argument") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("p1").nargs(2); + + CHECK_THROWS_WITH_AS(parser.parse_args(1, cstr_arr{"prog"}), "the following arguments are required: p1", argparse::parsing_error); +} + +TEST_CASE("Parsing missing positional argument with nargs set throws an exception for two missing arguments") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("p1").nargs(2); + parser.add_argument("p2").nargs(2); + + CHECK_THROWS_WITH_AS(parser.parse_args(1, cstr_arr{"prog"}), "the following arguments are required: p1 p2", argparse::parsing_error); +} + +TEST_CASE("Parsing missing positional argument with nargs set throws an exception for three missing arguments") +{ + auto parser = argparse::ArgumentParser().handle(argparse::Handle::none); + parser.add_argument("p1").nargs(2); + parser.add_argument("p2").nargs(2); + parser.add_argument("p3").nargs(2); + + CHECK_THROWS_WITH_AS(parser.parse_args(1, cstr_arr{"prog"}), "the following arguments are required: p1 p2 p3", argparse::parsing_error); +}