argparser/tests/parser.cpp
2023-05-17 10:17:56 +02:00

566 lines
20 KiB
C++

#include "argparser/argparser.h"
#include "gtest/gtest.h"
// TODO: test whitespace in tuples and arrays
// TODO: test empty values for everything
// TODO: test option->has(result), flag->has(result) and arg->has(result)
// TODO: test enum types and commas
// TODO: fuzz testing (blocked on clang 16 being available on arch)
class Parser : public ::testing::Test {
protected:
argparser::parser p{};
argparser::type_handle_impl<uint32_t> uintType;
Parser() = default;
~Parser() override = default;
void SetUp() override {
uintType = p.basic_type<uint32_t>("uint");
}
void TearDown() override {
}
};
TEST_F(Parser, SingleOption) {
auto fooOption = p.option("--foo", uintType);
auto parsed = p.parse({"--foo", "123"});
auto foo = fooOption->get(parsed);
EXPECT_EQ(foo, 123);
}
TEST_F(Parser, OptionWithEqualsSign) {
auto fooOption = p.option("--foo", uintType);
auto parsed = p.parse({"--foo=123"});
auto foo = fooOption->get(parsed);
EXPECT_EQ(foo, 123);
}
TEST_F(Parser, MultipleOptions) {
auto fooOption = p.option("--foo", uintType);
auto barOption = p.option("--bar", uintType);
auto parsed = p.parse({"--foo", "234", "--bar", "345"});
auto foo = fooOption->get(parsed);
auto bar = barOption->get(parsed);
EXPECT_EQ(foo, 234);
EXPECT_EQ(bar, 345);
}
TEST_F(Parser, MultipleOptionsDifferentOrder) {
auto fooOption = p.option("--foo", uintType);
auto barOption = p.option("--bar", uintType);
auto parsed = p.parse({"--bar", "345", "--foo", "234"});
auto foo = fooOption->get(parsed);
auto bar = barOption->get(parsed);
EXPECT_EQ(foo, 234);
EXPECT_EQ(bar, 345);
}
TEST_F(Parser, OptionsAreNotRequiredByDefault) {
auto fooOption = p.option("--foo", uintType);
auto barOption = p.option("--bar", uintType);
auto parsed = p.parse({"--foo", "234"});
auto foo = fooOption->get(parsed);
auto has_bar = barOption->has(parsed);
EXPECT_EQ(foo, 234);
EXPECT_EQ(has_bar, false);
}
TEST_F(Parser, RequiredOption) {
auto _1 = p.option("--foo", uintType);
[[maybe_unused]] auto _2 = p.option("--bar", uintType)->required();
EXPECT_THROW(auto _3 = p.parse({"--foo", "234"});, argparser::errors::missing_option_error);
}
TEST_F(Parser, MissingValue) {
auto _1 = p.option("--foo", uintType);
EXPECT_THROW(auto _2 = p.parse({"--foo"});, argparser::errors::missing_option_value_error);
}
TEST_F(Parser, MissingValueWithNextOption) {
auto _1 = p.option("--foo", uintType);
auto _2 = p.option("--bar", uintType);
EXPECT_THROW(auto _3 = p.parse({"--foo", "--bar", "123"});, argparser::errors::missing_option_value_error);
}
TEST_F(Parser, InvalidValue) {
auto _1 = p.option("--foo", uintType);
EXPECT_THROW(auto _2 = p.parse({"--foo", "-12"});, argparser::errors::type_parsing_error);
}
TEST_F(Parser, InvalidEmptyValue) {
auto _1 = p.option("--foo", uintType);
EXPECT_THROW(auto _2 = p.parse({"--foo", ""});, argparser::errors::type_parsing_error);
}
TEST_F(Parser, OptionPassedMultipleTimesReturnsLastValue) {
auto fooOption = p.option("--foo", uintType);
auto parsed = p.parse({"--foo", "23", "--foo", "45"});
EXPECT_EQ(fooOption->get(parsed), 45);
}
TEST_F(Parser, OptionNameMustStartWithTwoDashes) {
EXPECT_THROW(auto _1 = p.option("foo", uintType);, argparser::errors::invalid_option_name_error);
}
TEST_F(Parser, DefaultValue) {
auto fooOption = p.option("--foo", uintType)->default_value(123);
auto parsed = p.parse({});
EXPECT_EQ(fooOption->get(parsed), 123);
EXPECT_EQ(fooOption->has(parsed), false);
}
TEST_F(Parser, RepeatableOption) {
auto fooOption = p.repeatable_option("--foo", uintType);
auto parsed = p.parse({"--foo", "123", "--foo", "234"});
auto foo = fooOption->get(parsed);
EXPECT_EQ(foo.size(), 2);
EXPECT_EQ(foo[0], 123);
EXPECT_EQ(foo[1], 234);
}
TEST_F(Parser, RepeatableOptionDefaultValue) {
auto fooOption = p.repeatable_option("--foo", uintType)->default_value({1, 2, 3});
auto parsed = p.parse({});
auto foo = fooOption->get(parsed);
EXPECT_EQ(foo.size(), 3);
EXPECT_EQ(foo[0], 1);
EXPECT_EQ(foo[1], 2);
EXPECT_EQ(foo[2], 3);
}
TEST_F(Parser, RepeatableOptionLimits) {
auto fooFlag = p.repeatable_option("--foo", uintType)->min(2)->max(4);
auto parsed = p.parse({"--foo", "1", "--foo", "2"});
auto val = fooFlag->get(parsed);
EXPECT_EQ(val.size(), 2);
EXPECT_EQ(val[0], 1);
EXPECT_EQ(val[1], 2);
parsed = p.parse({"--foo", "1", "--foo", "2", "--foo", "3"});
val = fooFlag->get(parsed);
EXPECT_EQ(val.size(), 3);
EXPECT_EQ(val[0], 1);
EXPECT_EQ(val[1], 2);
EXPECT_EQ(val[2], 3);
parsed = p.parse({"--foo", "1", "--foo", "2", "--foo", "3", "--foo", "4"});
val = fooFlag->get(parsed);
EXPECT_EQ(val.size(), 4);
EXPECT_EQ(val[0], 1);
EXPECT_EQ(val[1], 2);
EXPECT_EQ(val[2], 3);
EXPECT_EQ(val[3], 4);
EXPECT_THROW(auto _1 = p.parse({});, argparser::errors::wrong_option_count_error);
EXPECT_THROW(auto _2 = p.parse({"--foo", "1"});, argparser::errors::wrong_option_count_error);
EXPECT_THROW(auto _3 = p.parse({"--foo", "1", "--foo", "2", "--foo", "3", "--foo", "4", "--foo", "5"});, argparser::errors::wrong_option_count_error);
EXPECT_THROW(auto _4 = p.parse({"--foo", "1", "--foo", "2", "--foo", "3", "--foo", "4", "--foo", "5", "--foo", "6"});, argparser::errors::wrong_option_count_error);
}
TEST_F(Parser, Flag) {
auto fooFlag = p.flag("--foo");
auto parsed = p.parse({"--foo"});
EXPECT_EQ(fooFlag->get(parsed), true);
parsed = p.parse({});
EXPECT_EQ(fooFlag->get(parsed), false);
}
TEST_F(Parser, FlagInverted) {
auto fooFlag = p.flag("--foo")->invert();
auto parsed = p.parse({"--foo"});
EXPECT_EQ(fooFlag->get(parsed), false);
parsed = p.parse({});
EXPECT_EQ(fooFlag->get(parsed), true);
}
TEST_F(Parser, RepeatableFLag) {
auto fooFlag = p.repeatable_flag("--foo");
auto parsed = p.parse({});
EXPECT_EQ(fooFlag->get(parsed), 0);
parsed = p.parse({"--foo"});
EXPECT_EQ(fooFlag->get(parsed), 1);
parsed = p.parse({"--foo", "--foo", "--foo", "--foo", "--foo"});
EXPECT_EQ(fooFlag->get(parsed), 5);
}
TEST_F(Parser, RepeatableFlagLimits) {
auto fooFlag = p.repeatable_flag("--foo")->min(2)->max(4);
auto parsed = p.parse({"--foo", "--foo"});
EXPECT_EQ(fooFlag->get(parsed), 2);
parsed = p.parse({"--foo", "--foo", "--foo"});
EXPECT_EQ(fooFlag->get(parsed), 3);
parsed = p.parse({"--foo", "--foo", "--foo", "--foo"});
EXPECT_EQ(fooFlag->get(parsed), 4);
EXPECT_THROW(auto _1 = p.parse({});, argparser::errors::wrong_option_count_error);
EXPECT_THROW(auto _2 = p.parse({"--foo"});, argparser::errors::wrong_option_count_error);
EXPECT_THROW(auto _3 = p.parse({"--foo", "--foo", "--foo", "--foo", "--foo"});, argparser::errors::wrong_option_count_error);
EXPECT_THROW(auto _4 = p.parse({"--foo", "--foo", "--foo", "--foo", "--foo", "--foo"});, argparser::errors::wrong_option_count_error);
}
TEST_F(Parser, OptionAndFlagNamesMustBeUnique) {
EXPECT_THROW({
auto _1 = p.option("--optopt", uintType);
auto _2 = p.option("--optopt", uintType);
},
argparser::errors::duplicate_option_name);
EXPECT_THROW({
auto _1 = p.flag("--flagflag");
auto _2 = p.flag("--flagflag");
},
argparser::errors::duplicate_option_name);
EXPECT_THROW({
auto _1 = p.option("--optflag", uintType);
auto _2 = p.flag("--optflag");
},
argparser::errors::duplicate_option_name);
EXPECT_THROW({
auto _1 = p.option("--optrepflag", uintType);
auto _2 = p.repeatable_flag("--optrepflag");
},
argparser::errors::duplicate_option_name);
EXPECT_THROW({
auto _1 = p.flag("--flagopt");
auto _2 = p.option("--flagopt", uintType);
},
argparser::errors::duplicate_option_name);
}
TEST_F(Parser, OptionWithOnlyShortName) {
auto fooOpt = p.option("-f", uintType);
argparser::parse_result pr;
uint32_t fooVal;
EXPECT_NO_THROW(pr = p.parse({"-f", "123"}));
EXPECT_NO_THROW(fooVal = fooOpt->get(pr));
EXPECT_EQ(fooVal, 123);
}
TEST_F(Parser, RepeatableOptionWithOnlyShortName) {
auto fooOpt = p.repeatable_option("-f", uintType);
argparser::parse_result pr;
std::vector<uint32_t> fooVal;
EXPECT_NO_THROW(pr = p.parse({"-f", "123"}));
EXPECT_NO_THROW(fooVal = fooOpt->get(pr));
EXPECT_EQ(fooVal, (decltype(fooVal){123}));
}
TEST_F(Parser, FlagWithOnlyShortName) {
auto fooFlag = p.flag("-f");
argparser::parse_result pr;
bool fooVal;
EXPECT_NO_THROW(pr = p.parse({"-f"}));
EXPECT_NO_THROW(fooVal = fooFlag->get(pr));
EXPECT_EQ(fooVal, true);
}
TEST_F(Parser, RepeatableFlagWithOnlyShortName) {
auto fooFlag = p.flag("-f");
argparser::parse_result pr;
unsigned int fooVal;
EXPECT_NO_THROW(pr = p.parse({"-f"}));
EXPECT_NO_THROW(fooVal = fooFlag->get(pr));
EXPECT_EQ(fooVal, 1);
}
TEST_F(Parser, OptionWithLongAndShortName) {
auto fooOpt = p.option("--foo", "-f", uintType);
argparser::parse_result pr;
uint32_t fooVal;
EXPECT_NO_THROW(pr = p.parse({"-f", "123"}));
EXPECT_NO_THROW(fooVal = fooOpt->get(pr));
EXPECT_EQ(fooVal, 123);
EXPECT_NO_THROW(pr = p.parse({"--foo", "123"}));
EXPECT_NO_THROW(fooVal = fooOpt->get(pr));
EXPECT_EQ(fooVal, 123);
}
TEST_F(Parser, OptionWithShortAndLongName) {
auto fooOpt = p.option("-f", "--foo", uintType);
argparser::parse_result pr;
uint32_t fooVal;
EXPECT_NO_THROW(pr = p.parse({"-f", "123"}));
EXPECT_NO_THROW(fooVal = fooOpt->get(pr));
EXPECT_EQ(fooVal, 123);
EXPECT_NO_THROW(pr = p.parse({"--foo", "123"}));
EXPECT_NO_THROW(fooVal = fooOpt->get(pr));
EXPECT_EQ(fooVal, 123);
}
TEST_F(Parser, RepeatableOptionWithLongAndShortName) {
auto fooOpt = p.repeatable_option("--foo", "-f", uintType);
argparser::parse_result pr;
std::vector<uint32_t> fooVal;
EXPECT_NO_THROW(pr = p.parse({"-f", "123"}));
EXPECT_NO_THROW(fooVal = fooOpt->get(pr));
EXPECT_EQ(fooVal, (decltype(fooVal){123}));
EXPECT_NO_THROW(pr = p.parse({"--foo", "123"}));
EXPECT_NO_THROW(fooVal = fooOpt->get(pr));
EXPECT_EQ(fooVal, (decltype(fooVal){123}));
EXPECT_NO_THROW(pr = p.parse({"--foo", "123", "-f", "234"}));
EXPECT_NO_THROW(fooVal = fooOpt->get(pr));
EXPECT_EQ(fooVal, (decltype(fooVal){123, 234}));
EXPECT_NO_THROW(pr = p.parse({"-f", "123", "--foo", "234"}));
EXPECT_NO_THROW(fooVal = fooOpt->get(pr));
EXPECT_EQ(fooVal, (decltype(fooVal){123, 234}));
}
TEST_F(Parser, RepeatableOptionWithShortAndLongName) {
auto fooOpt = p.repeatable_option("-f", "--foo", uintType);
argparser::parse_result pr;
std::vector<uint32_t> fooVal;
EXPECT_NO_THROW(pr = p.parse({"-f", "123"}));
EXPECT_NO_THROW(fooVal = fooOpt->get(pr));
EXPECT_EQ(fooVal, (decltype(fooVal){123}));
EXPECT_NO_THROW(pr = p.parse({"--foo", "123"}));
EXPECT_NO_THROW(fooVal = fooOpt->get(pr));
EXPECT_EQ(fooVal, (decltype(fooVal){123}));
EXPECT_NO_THROW(pr = p.parse({"--foo", "123", "-f", "234"}));
EXPECT_NO_THROW(fooVal = fooOpt->get(pr));
EXPECT_EQ(fooVal, (decltype(fooVal){123, 234}));
EXPECT_NO_THROW(pr = p.parse({"-f", "123", "--foo", "234"}));
EXPECT_NO_THROW(fooVal = fooOpt->get(pr));
EXPECT_EQ(fooVal, (decltype(fooVal){123, 234}));
}
TEST_F(Parser, FlagWithLongAndSHortName) {
auto fooFlag = p.flag("--foo", "-f");
argparser::parse_result pr;
bool fooVal;
EXPECT_NO_THROW(pr = p.parse({"-f"}));
EXPECT_NO_THROW(fooVal = fooFlag->get(pr));
EXPECT_EQ(fooVal, true);
EXPECT_NO_THROW(pr = p.parse({"--foo"}));
EXPECT_NO_THROW(fooVal = fooFlag->get(pr));
EXPECT_EQ(fooVal, true);
}
TEST_F(Parser, FlagWithShortAndLongName) {
auto fooFlag = p.flag("-f", "--foo");
argparser::parse_result pr;
bool fooVal;
EXPECT_NO_THROW(pr = p.parse({"-f"}));
EXPECT_NO_THROW(fooVal = fooFlag->get(pr));
EXPECT_EQ(fooVal, true);
EXPECT_NO_THROW(pr = p.parse({"--foo"}));
EXPECT_NO_THROW(fooVal = fooFlag->get(pr));
EXPECT_EQ(fooVal, true);
}
TEST_F(Parser, RepeatableFlagWithLongAndShortName) {
auto fooFlag = p.repeatable_flag("--foo", "-f");
argparser::parse_result pr;
unsigned int fooVal;
EXPECT_NO_THROW(pr = p.parse({"-f"}));
EXPECT_NO_THROW(fooVal = fooFlag->get(pr));
EXPECT_EQ(fooVal, 1);
EXPECT_NO_THROW(pr = p.parse({"--foo"}));
EXPECT_NO_THROW(fooVal = fooFlag->get(pr));
EXPECT_EQ(fooVal, 1);
EXPECT_NO_THROW(pr = p.parse({"-f", "--foo"}));
EXPECT_NO_THROW(fooVal = fooFlag->get(pr));
EXPECT_EQ(fooVal, 2);
EXPECT_NO_THROW(pr = p.parse({"--foo", "-f"}));
EXPECT_NO_THROW(fooVal = fooFlag->get(pr));
EXPECT_EQ(fooVal, 2);
}
TEST_F(Parser, RepeatableFlagWithShortAndLongName) {
auto fooFlag = p.repeatable_flag("-f", "--foo");
argparser::parse_result pr;
unsigned int fooVal;
EXPECT_NO_THROW(pr = p.parse({"-f"}));
EXPECT_NO_THROW(fooVal = fooFlag->get(pr));
EXPECT_EQ(fooVal, 1);
EXPECT_NO_THROW(pr = p.parse({"--foo"}));
EXPECT_NO_THROW(fooVal = fooFlag->get(pr));
EXPECT_EQ(fooVal, 1);
EXPECT_NO_THROW(pr = p.parse({"-f", "--foo"}));
EXPECT_NO_THROW(fooVal = fooFlag->get(pr));
EXPECT_EQ(fooVal, 2);
EXPECT_NO_THROW(pr = p.parse({"--foo", "-f"}));
EXPECT_NO_THROW(fooVal = fooFlag->get(pr));
EXPECT_EQ(fooVal, 2);
}
TEST_F(Parser, ShortOptionCombinedWithValue) {
auto fooOpt = p.option("-f", uintType);
argparser::parse_result pr;
uint32_t fooVal;
EXPECT_NO_THROW(pr = p.parse({"-f123"}));
EXPECT_NO_THROW(fooVal = fooOpt->get(pr));
EXPECT_EQ(fooVal, 123);
}
TEST_F(Parser, MultipleShortFlags) {
auto flagA = p.flag("-a");
auto flagB = p.flag("-b");
auto flagC = p.flag("-c");
argparser::parse_result pr;
EXPECT_NO_THROW(pr = p.parse({"-cab"}));
EXPECT_EQ(flagA->get(pr), true);
EXPECT_EQ(flagB->get(pr), true);
EXPECT_EQ(flagC->get(pr), true);
}
TEST_F(Parser, MultipleShortFlagsCombinedWithShortOptionWithValue) {
auto flagA = p.flag("-a");
auto flagB = p.flag("-b");
auto flagC = p.flag("-c");
auto fooOpt = p.option("-f", uintType);
argparser::parse_result pr;
EXPECT_NO_THROW(pr = p.parse({"-cabf123"}));
EXPECT_EQ(flagA->get(pr), true);
EXPECT_EQ(flagB->get(pr), true);
EXPECT_EQ(flagC->get(pr), true);
EXPECT_EQ(fooOpt->get(pr), 123);
}
TEST_F(Parser, SingleArgument) {
auto fooArg = p.arg("foo", uintType);
auto parsed = p.parse({"123"});
EXPECT_EQ(fooArg->get(parsed), 123);
}
TEST_F(Parser, MissingArgumentThrows) {
auto fooArg = p.arg("foo", uintType);
EXPECT_THROW(auto _ = p.parse({});, argparser::errors::missing_argument_error);
}
TEST_F(Parser, MultipleArguments) {
auto fooArg = p.arg("foo", uintType);
auto barArg = p.arg("bar", uintType);
auto parsed = p.parse({"123", "234"});
EXPECT_EQ(fooArg->get(parsed), 123);
EXPECT_EQ(barArg->get(parsed), 234);
}
TEST_F(Parser, MixedArgumentsAndOptionsAndFlags) {
auto fooArg = p.arg("foo", uintType);
auto barArg = p.arg("bar", uintType);
auto asdfOpt = p.option("--asdf", uintType);
auto qwertyFlag = p.flag("--qwerty");
auto parsed = p.parse({"123", "--asdf", "1", "234", "--qwerty"});
EXPECT_EQ(fooArg->get(parsed), 123);
EXPECT_EQ(barArg->get(parsed), 234);
EXPECT_EQ(asdfOpt->get(parsed), 1);
EXPECT_EQ(qwertyFlag->get(parsed), true);
parsed = p.parse({"--asdf", "123", "234", "345"});
EXPECT_EQ(fooArg->get(parsed), 234);
EXPECT_EQ(barArg->get(parsed), 345);
EXPECT_EQ(asdfOpt->get(parsed), 123);
EXPECT_EQ(qwertyFlag->get(parsed), false);
}
TEST_F(Parser, OptionalArgument) {
auto fooArg = p.optional_arg("foo", uintType);
auto parsed = p.parse({"123"});
EXPECT_EQ(fooArg->get(parsed).has_value(), true);
EXPECT_EQ(fooArg->get(parsed).value(), 123);
EXPECT_EQ(fooArg->has(parsed), true);
parsed = p.parse({});
EXPECT_EQ(fooArg->get(parsed).has_value(), false);
EXPECT_EQ(fooArg->has(parsed), false);
}
TEST_F(Parser, OptionalArgumentDefaultValue) {
auto fooArg = p.optional_arg("foo", uintType)->default_value(99);
auto parsed = p.parse({"123"});
EXPECT_EQ(fooArg->get(parsed), 123);
EXPECT_EQ(fooArg->has(parsed), true);
parsed = p.parse({});
EXPECT_EQ(fooArg->get(parsed), 99);
EXPECT_EQ(fooArg->has(parsed), false);
}
TEST_F(Parser, RepeatedArgument) {
auto fooArg = p.repeatable_arg("foo", uintType);
auto parsed = p.parse({"123", "234", "345", "456"});
auto val = fooArg->get(parsed);
EXPECT_EQ(val.size(), 4);
EXPECT_EQ(val[0], 123);
EXPECT_EQ(val[1], 234);
EXPECT_EQ(val[2], 345);
EXPECT_EQ(val[3], 456);
}
TEST_F(Parser, RepeatedArgumentLimits) {
auto fooArg = p.repeatable_arg("foo", uintType)->min(2)->max(4);
argparser::parse_result parsed;
EXPECT_NO_THROW(parsed = p.parse({"1", "2"}););
EXPECT_EQ(fooArg->get(parsed), (std::vector<uint32_t>{1, 2}));
EXPECT_NO_THROW(parsed = p.parse({"1", "2", "3"}););
EXPECT_EQ(fooArg->get(parsed), (std::vector<uint32_t>{1, 2, 3}));
EXPECT_NO_THROW(parsed = p.parse({"1", "2", "3", "4"}););
EXPECT_EQ(fooArg->get(parsed), (std::vector<uint32_t>{1, 2, 3, 4}));
EXPECT_THROW(parsed = p.parse({}), argparser::errors::missing_argument_error);
EXPECT_THROW(parsed = p.parse({"1"}), argparser::errors::missing_argument_error);
EXPECT_THROW(parsed = p.parse({"1", "2", "3", "4", "5"}), argparser::errors::too_many_arguments_error);
EXPECT_THROW(parsed = p.parse({"1", "2", "3", "4", "5", "6"}), argparser::errors::too_many_arguments_error);
EXPECT_THROW(parsed = p.parse({"1", "2", "3", "4", "5", "6", "7"}), argparser::errors::too_many_arguments_error);
}
TEST_F(Parser, MixedArguments) {
auto boolType = p.enum_type<bool>("bool", {{"true", true}, {"false", false}});
auto tupleType = p.tuple_type("tuple", uintType, uintType);
auto argA = p.repeatable_arg("a", uintType);
auto argB = p.optional_arg("b", boolType);
auto argC = p.arg("c", tupleType);
auto argD = p.repeatable_arg("d", uintType);
auto parsed = p.parse({"1", "2", "3", "true", "1,2", "4", "5"});
auto valA = argA->get(parsed);
auto valB = argB->get(parsed);
auto valC = argC->get(parsed);
auto valD = argD->get(parsed);
EXPECT_EQ(valA.size(), 3);
EXPECT_EQ(valA[0], 1);
EXPECT_EQ(valA[1], 2);
EXPECT_EQ(valA[2], 3);
EXPECT_TRUE(valB.has_value());
EXPECT_EQ(valB.value(), true);
EXPECT_EQ(valC, (std::make_tuple<uint32_t, uint32_t>(1, 2)));
EXPECT_EQ(valD, (decltype(valD){4, 5}));
}
TEST_F(Parser, ArgumentWrongType) {
auto boolType = p.enum_type<bool>("bool", {{"true", true}, {"false", false}});
auto fooArg = p.arg("foo", boolType);
EXPECT_THROW(auto _ = p.parse({"123", "true"});, argparser::errors::type_parsing_error);
}
TEST_F(Parser, RemainingArguments) {
auto fooArg = p.arg("foo", uintType);
p.enable_remaining_args();
argparser::parse_result pr;
EXPECT_NO_THROW(pr = p.parse({"123", "234", "456"}));
EXPECT_EQ(fooArg->get(pr), 123);
EXPECT_EQ(pr.remaining(), (std::vector<std::string>{"234", "456"}));
}
TEST_F(Parser, OptionsAndFlagsAsRemainingArguments) {
auto fooOpt = p.option("--foo", uintType);
auto barFlag = p.flag("--bar");
p.enable_remaining_args();
argparser::parse_result pr;
EXPECT_NO_THROW(pr = p.parse({"123", "--foo", "456", "--bar"}));
EXPECT_EQ(pr.remaining(), (std::vector<std::string>{"123", "--foo", "456", "--bar"}));
EXPECT_FALSE(fooOpt->has(pr));
EXPECT_FALSE(barFlag->has(pr));
}
TEST_F(Parser, RemainingArgumentsWithDoubleDash) {
auto fooOpt = p.option("--foo", uintType);
auto barFlag = p.flag("--bar");
auto arg = p.arg("arg", uintType);
p.enable_remaining_args();
argparser::parse_result pr;
EXPECT_NO_THROW(pr = p.parse({"123", "--", "--foo", "456", "--bar"}));
EXPECT_EQ(pr.remaining(), (std::vector<std::string>{"--foo", "456", "--bar"}));
EXPECT_FALSE(fooOpt->has(pr));
EXPECT_FALSE(barFlag->has(pr));
EXPECT_EQ(arg->get(pr), 123);
}