mirror of
https://git.lynn.is/Gwen/argparser.git
synced 2024-05-02 16:03:46 +02:00
779 lines
29 KiB
C++
779 lines
29 KiB
C++
#include "argparser/argparser.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
// TODO: test empty input for all types
|
|
|
|
|
|
TEST(Types, AutomaticUint8Type) {
|
|
argparser::parser p{};
|
|
argparser::type_handle_impl<uint8_t> uint8Type;
|
|
argparser::parse_result pr;
|
|
argparser::single_arg_handle<uint8_t> arg;
|
|
uint8_t val;
|
|
EXPECT_NO_THROW({
|
|
uint8Type = p.basic_type<uint8_t>("uint8");
|
|
arg = p.arg("a", uint8Type);
|
|
pr = p.parse({"250"});
|
|
val = arg->get(pr);
|
|
});
|
|
EXPECT_EQ(val, 250);
|
|
}
|
|
|
|
TEST(Types, AutomaticInt8Type) {
|
|
argparser::parser p{};
|
|
argparser::type_handle_impl<int8_t> int8Type;
|
|
argparser::parse_result pr;
|
|
argparser::single_arg_handle<int8_t> arg;
|
|
int8_t val;
|
|
EXPECT_NO_THROW({
|
|
int8Type = p.basic_type<int8_t>("int8");
|
|
arg = p.arg("a", int8Type);
|
|
pr = p.parse({"-126"});
|
|
val = arg->get(pr);
|
|
});
|
|
EXPECT_EQ(val, -126);
|
|
}
|
|
|
|
TEST(Types, AutomaticUint16Type) {
|
|
argparser::parser p{};
|
|
argparser::type_handle_impl<uint16_t> uint16Type;
|
|
argparser::parse_result pr;
|
|
argparser::single_arg_handle<uint16_t> arg;
|
|
uint16_t val;
|
|
EXPECT_NO_THROW({
|
|
uint16Type = p.basic_type<uint16_t>("uint16");
|
|
arg = p.arg("a", uint16Type);
|
|
pr = p.parse({"65530"});
|
|
val = arg->get(pr);
|
|
});
|
|
EXPECT_EQ(val, 65530);
|
|
}
|
|
|
|
TEST(Types, AutomaticInt16Type) {
|
|
argparser::parser p{};
|
|
argparser::type_handle_impl<int16_t> int16Type;
|
|
argparser::parse_result pr;
|
|
argparser::single_arg_handle<int16_t> arg;
|
|
int16_t val;
|
|
EXPECT_NO_THROW({
|
|
int16Type = p.basic_type<int16_t>("int16");
|
|
arg = p.arg("a", int16Type);
|
|
pr = p.parse({"-32760"});
|
|
val = arg->get(pr);
|
|
});
|
|
EXPECT_EQ(val, -32760);
|
|
}
|
|
|
|
TEST(Types, AutomaticUint32Type) {
|
|
argparser::parser p{};
|
|
argparser::type_handle_impl<uint32_t> uint32Type;
|
|
argparser::parse_result pr;
|
|
argparser::single_arg_handle<uint32_t> arg;
|
|
uint32_t val;
|
|
EXPECT_NO_THROW({
|
|
uint32Type = p.basic_type<uint32_t>("uint32");
|
|
arg = p.arg("a", uint32Type);
|
|
pr = p.parse({"4294967290"});
|
|
val = arg->get(pr);
|
|
});
|
|
EXPECT_EQ(val, 4294967290);
|
|
}
|
|
|
|
TEST(Types, AutomaticInt32Type) {
|
|
argparser::parser p{};
|
|
argparser::type_handle_impl<int32_t> int32Type;
|
|
argparser::parse_result pr;
|
|
argparser::single_arg_handle<int32_t> arg;
|
|
int32_t val;
|
|
EXPECT_NO_THROW({
|
|
int32Type = p.basic_type<int32_t>("int32");
|
|
arg = p.arg("a", int32Type);
|
|
pr = p.parse({"-2147483645"});
|
|
val = arg->get(pr);
|
|
});
|
|
EXPECT_EQ(val, -2147483645);
|
|
}
|
|
|
|
TEST(Types, AutomaticUint64Type) {
|
|
argparser::parser p{};
|
|
argparser::type_handle_impl<uint64_t> uint64Type;
|
|
argparser::parse_result pr;
|
|
argparser::single_arg_handle<uint64_t> arg;
|
|
uint64_t val;
|
|
EXPECT_NO_THROW({
|
|
uint64Type = p.basic_type<uint64_t>("uint64");
|
|
arg = p.arg("a", uint64Type);
|
|
pr = p.parse({"18446744073709551612"});
|
|
val = arg->get(pr);
|
|
});
|
|
EXPECT_EQ(val, 18446744073709551612ull);
|
|
}
|
|
|
|
TEST(Types, AutomaticInt64Type) {
|
|
argparser::parser p{};
|
|
argparser::type_handle_impl<int64_t> int64Type;
|
|
argparser::parse_result pr;
|
|
argparser::single_arg_handle<int64_t> arg;
|
|
int64_t val;
|
|
EXPECT_NO_THROW({
|
|
int64Type = p.basic_type<int64_t>("int64");
|
|
arg = p.arg("a", int64Type);
|
|
pr = p.parse({"-9223372036854775803"});
|
|
val = arg->get(pr);
|
|
});
|
|
EXPECT_EQ(val, -9223372036854775803);
|
|
}
|
|
|
|
TEST(Types, AutomaticFloatType) {
|
|
argparser::parser p{};
|
|
argparser::type_handle_impl<float> floatType;
|
|
argparser::parse_result pr;
|
|
argparser::single_arg_handle<float> arg;
|
|
float val;
|
|
EXPECT_NO_THROW({
|
|
floatType = p.basic_type<float>("float");
|
|
arg = p.arg("a", floatType);
|
|
pr = p.parse({"23.45"});
|
|
val = arg->get(pr);
|
|
});
|
|
EXPECT_EQ(val, 23.45f);
|
|
}
|
|
|
|
TEST(Types, AutomaticDoubleType) {
|
|
argparser::parser p{};
|
|
argparser::type_handle_impl<double> doubleType;
|
|
argparser::parse_result pr;
|
|
argparser::single_arg_handle<double> arg;
|
|
double val;
|
|
EXPECT_NO_THROW({
|
|
doubleType = p.basic_type<double>("double");
|
|
arg = p.arg("a", doubleType);
|
|
pr = p.parse({"23.45"});
|
|
val = arg->get(pr);
|
|
});
|
|
EXPECT_EQ(val, 23.45);
|
|
}
|
|
|
|
TEST(Types, AutomaticStringType) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string>("string");
|
|
auto arg = p.arg("a", stringType);
|
|
argparser::parse_result pr;
|
|
EXPECT_NO_THROW(pr = p.parse({"foo bar"}));
|
|
EXPECT_EQ(arg->get(pr), "foo bar");
|
|
EXPECT_NO_THROW(pr = p.parse({"'foo bar'"}));
|
|
EXPECT_EQ(arg->get(pr), "foo bar");
|
|
EXPECT_NO_THROW(pr = p.parse({"\"foo bar\""}));
|
|
EXPECT_EQ(arg->get(pr), "foo bar");
|
|
}
|
|
|
|
TEST(Types, AutomaticStringTypeBareEmptyString) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string, argparser::internal::parse_opt::BareString>("string");
|
|
auto arg = p.arg("a", stringType);
|
|
argparser::parse_result pr;
|
|
EXPECT_NO_THROW(pr = p.parse({""}));
|
|
EXPECT_EQ(arg->get(pr), "");
|
|
}
|
|
|
|
TEST(Types, AutomaticStringTypeSingleQuotedEmptyString) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string, argparser::internal::parse_opt::SingleQuotedString>("string");
|
|
auto arg = p.arg("a", stringType);
|
|
argparser::parse_result pr;
|
|
EXPECT_NO_THROW(pr = p.parse({"''"}));
|
|
EXPECT_EQ(arg->get(pr), "");
|
|
EXPECT_THROW(pr = p.parse({""}), argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
TEST(Types, AutomaticStringTypeDoubleQuotedEmptyString) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string, argparser::internal::parse_opt::DoubleQuotedString>("string");
|
|
auto arg = p.arg("a", stringType);
|
|
argparser::parse_result pr;
|
|
EXPECT_NO_THROW(pr = p.parse({"\"\""}));
|
|
EXPECT_EQ(arg->get(pr), "");
|
|
EXPECT_THROW(pr = p.parse({""}), argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
TEST(Types, AutomaticStringTypeBrokenQuote) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string>("string");
|
|
auto arg = p.arg("a", stringType);
|
|
argparser::parse_result pr;
|
|
EXPECT_THROW(pr = p.parse({"'foobar"}), argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(pr = p.parse({"\"foobar"}), argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(pr = p.parse({"foo'bar"}), argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(pr = p.parse({"foo\"bar"}), argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(pr = p.parse({"foobar'"}), argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(pr = p.parse({"foobar\""}), argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
TEST(Types, AutomaticStringTypeBareComma) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string>("string");
|
|
auto arg = p.arg("a", stringType);
|
|
argparser::parse_result pr;
|
|
EXPECT_NO_THROW(pr = p.parse({"foo,bar"}));
|
|
EXPECT_EQ(arg->get(pr), "foo,bar");
|
|
}
|
|
|
|
TEST(Types, AutomaticStringTypeNoBareCommaInTuple) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string>("string");
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto tupleType = p.tuple_type("tuple", stringType, uintType);
|
|
auto arg = p.arg("a", tupleType);
|
|
argparser::parse_result pr;
|
|
EXPECT_THROW(pr = p.parse({"tuple(foo,bar, 2)"}), argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
TEST(Types, AutomaticStringTypeBareWithWhitespaceInTuple) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string>("string");
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto tupleType = p.tuple_type("tuple", stringType, uintType);
|
|
auto arg = p.arg("a", tupleType);
|
|
argparser::parse_result pr;
|
|
EXPECT_NO_THROW(pr = p.parse({"tuple( foo bar , 2)"}));
|
|
EXPECT_EQ(arg->get(pr), std::make_tuple(" foo bar ", 2));
|
|
}
|
|
|
|
TEST(Types, AutomaticStringTypeExplicitAny) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string, argparser::internal::parse_opt::AnyString>("string");
|
|
auto arg = p.arg("a", stringType);
|
|
argparser::parse_result pr;
|
|
EXPECT_NO_THROW(pr = p.parse({"foo bar"}));
|
|
EXPECT_EQ(arg->get(pr), "foo bar");
|
|
EXPECT_NO_THROW(pr = p.parse({"'foo bar'"}));
|
|
EXPECT_EQ(arg->get(pr), "foo bar");
|
|
EXPECT_NO_THROW(pr = p.parse({"\"foo bar\""}));
|
|
EXPECT_EQ(arg->get(pr), "foo bar");
|
|
}
|
|
|
|
TEST(Types, AutomaticStringOnlyBare) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string, argparser::internal::parse_opt::BareString>("string");
|
|
auto arg = p.arg("a", stringType);
|
|
argparser::parse_result pr;
|
|
EXPECT_NO_THROW(pr = p.parse({"foo bar"}));
|
|
EXPECT_EQ(arg->get(pr), "foo bar");
|
|
EXPECT_THROW(pr = p.parse({"'foo bar'"}), argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(pr = p.parse({"\"foo bar\""}), argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
TEST(Types, AutomaticStringOnlySingleQuoted) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string, argparser::internal::parse_opt::SingleQuotedString>("string");
|
|
auto arg = p.arg("a", stringType);
|
|
argparser::parse_result pr;
|
|
EXPECT_NO_THROW(pr = p.parse({"'foo bar'"}));
|
|
EXPECT_EQ(arg->get(pr), "foo bar");
|
|
EXPECT_THROW(pr = p.parse({"foo bar"}), argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(pr = p.parse({"\"foo bar\""}), argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
TEST(Types, AutomaticStringOnlyDoubleQuoted) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string, argparser::internal::parse_opt::DoubleQuotedString>("string");
|
|
auto arg = p.arg("a", stringType);
|
|
argparser::parse_result pr;
|
|
EXPECT_NO_THROW(pr = p.parse({"\"foo bar\""}));
|
|
EXPECT_EQ(arg->get(pr), "foo bar");
|
|
EXPECT_THROW(pr = p.parse({"foo bar"}), argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(pr = p.parse({"'foo bar'"}), argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
TEST(Types, AutomaticStringOnlyQuoted) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string, argparser::internal::parse_opt::SingleQuotedString | argparser::internal::parse_opt::DoubleQuotedString>("string");
|
|
auto arg = p.arg("a", stringType);
|
|
argparser::parse_result pr;
|
|
EXPECT_NO_THROW(pr = p.parse({"\"foo bar\""}));
|
|
EXPECT_EQ(arg->get(pr), "foo bar");
|
|
EXPECT_NO_THROW(pr = p.parse({"'foo bar'"}));
|
|
EXPECT_EQ(arg->get(pr), "foo bar");
|
|
EXPECT_THROW(pr = p.parse({"foo bar"}), argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
TEST(Types, AutomaticStringOnlyBareOrSingleQuoted) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string, argparser::internal::parse_opt::SingleQuotedString | argparser::internal::parse_opt::BareString>("string");
|
|
auto arg = p.arg("a", stringType);
|
|
argparser::parse_result pr;
|
|
EXPECT_NO_THROW(pr = p.parse({"'foo bar'"}));
|
|
EXPECT_EQ(arg->get(pr), "foo bar");
|
|
EXPECT_NO_THROW(pr = p.parse({"foo bar"}));
|
|
EXPECT_EQ(arg->get(pr), "foo bar");
|
|
EXPECT_THROW(pr = p.parse({"\"foo bar\""}), argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
TEST(Types, AutomaticStringOnlyBareOrDoubleQuoted) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string, argparser::internal::parse_opt::DoubleQuotedString | argparser::internal::parse_opt::BareString>("string");
|
|
auto arg = p.arg("a", stringType);
|
|
argparser::parse_result pr;
|
|
EXPECT_NO_THROW(pr = p.parse({"\"foo bar\""}));
|
|
EXPECT_EQ(arg->get(pr), "foo bar");
|
|
EXPECT_NO_THROW(pr = p.parse({"foo bar"}));
|
|
EXPECT_EQ(arg->get(pr), "foo bar");
|
|
EXPECT_THROW(pr = p.parse({"'foo bar'"}), argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
|
|
TEST(Types, AutomaticStringTypeUnquotedInTuple) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string>("string");
|
|
auto tupleType = p.tuple_type("tuple", stringType, stringType);
|
|
auto arg = p.arg("a", tupleType);
|
|
auto pr = p.parse({"(foo bar, asdf)"});
|
|
auto val = arg->get(pr);
|
|
EXPECT_EQ(val, std::make_tuple("foo bar", " asdf"));
|
|
}
|
|
|
|
TEST(Types, AutomaticStringTypeTrim) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string, argparser::internal::parse_opt::TrimString>("string");
|
|
auto arg = p.arg("a", stringType);
|
|
auto pr = p.parse({" foo "});
|
|
EXPECT_EQ(arg->get(pr), "foo");
|
|
pr = p.parse({"' foo '"});
|
|
EXPECT_EQ(arg->get(pr), "foo");
|
|
pr = p.parse({"\" foo \""});
|
|
EXPECT_EQ(arg->get(pr), "foo");
|
|
}
|
|
|
|
TEST(Types, AutomaticStringTypeTrimOnlyWhitespace) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string, argparser::internal::parse_opt::TrimString>("string");
|
|
auto arg = p.arg("a", stringType);
|
|
auto pr = p.parse({" "});
|
|
EXPECT_EQ(arg->get(pr), "");
|
|
pr = p.parse({"' '"});
|
|
EXPECT_EQ(arg->get(pr), "");
|
|
pr = p.parse({"\" \""});
|
|
EXPECT_EQ(arg->get(pr), "");
|
|
}
|
|
|
|
TEST(Types, AutomaticStringTypeTrimUnquoted) {
|
|
argparser::parser p{};
|
|
auto stringType = p.basic_type<std::string, argparser::internal::parse_opt::TrimBareString>("string");
|
|
auto arg = p.arg("a", stringType);
|
|
auto pr = p.parse({" foo "});
|
|
EXPECT_EQ(arg->get(pr), "foo");
|
|
pr = p.parse({"' foo '"});
|
|
EXPECT_EQ(arg->get(pr), " foo ");
|
|
pr = p.parse({"\" foo \""});
|
|
EXPECT_EQ(arg->get(pr), " foo ");
|
|
}
|
|
|
|
|
|
TEST(Types, EnumType) {
|
|
argparser::parser p;
|
|
auto boolType = p.enum_type<bool>("bool", {{"true", true},
|
|
{"yes", true},
|
|
{"false", false},
|
|
{"no", false}});
|
|
auto fooOption = p.option("--foo", boolType);
|
|
auto parsed = p.parse({"--foo", "true"});
|
|
EXPECT_EQ(fooOption->get(parsed), true);
|
|
parsed = p.parse({"--foo", "false"});
|
|
EXPECT_EQ(fooOption->get(parsed), false);
|
|
parsed = p.parse({"--foo", "yes"});
|
|
EXPECT_EQ(fooOption->get(parsed), true);
|
|
parsed = p.parse({"--foo", "no"});
|
|
EXPECT_EQ(fooOption->get(parsed), false);
|
|
}
|
|
|
|
TEST(Types, EnumTypeEmptyError) {
|
|
argparser::parser p;
|
|
EXPECT_THROW(p.enum_type("enum1", {}), argparser::errors::empty_enum_map_error);
|
|
EXPECT_THROW(p.enum_type<bool>("enum1", {}), argparser::errors::empty_enum_map_error);
|
|
}
|
|
|
|
TEST(Types, EnumTypeLongestMatching) {
|
|
argparser::parser p;
|
|
auto enumType = p.enum_type<int>("enum", {
|
|
{"a", 1},
|
|
{"ab", 2},
|
|
});
|
|
auto fooOption = p.option("--foo", enumType);
|
|
auto parsed = p.parse({"--foo", "a"});
|
|
EXPECT_EQ(fooOption->get(parsed), 1);
|
|
parsed = p.parse({"--foo", "ab"});
|
|
EXPECT_EQ(fooOption->get(parsed), 2);
|
|
}
|
|
|
|
TEST(Types, EnumTypeLongestMatchingReverseOrder) {
|
|
argparser::parser p;
|
|
auto enumType = p.enum_type<int>("enum", {
|
|
{"ab", 2},
|
|
{"a", 1},
|
|
});
|
|
auto fooOption = p.option("--foo", enumType);
|
|
auto parsed = p.parse({"--foo", "a"});
|
|
EXPECT_EQ(fooOption->get(parsed), 1);
|
|
parsed = p.parse({"--foo", "ab"});
|
|
EXPECT_EQ(fooOption->get(parsed), 2);
|
|
}
|
|
|
|
TEST(Types, EnumTypeInvalidValue) {
|
|
argparser::parser p;
|
|
auto enumType = p.enum_type<int>("enum", {{"a", 1}, {"b", 2}, {"c", 3}});
|
|
auto _1 = p.option("--foo", enumType);
|
|
EXPECT_THROW(auto _ = p.parse({"--foo", "x"}), argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _ = p.parse({"--foo", "aa"}), argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
TEST(Types, StringEnumType) {
|
|
argparser::parser p;
|
|
auto enumType = p.enum_type("enum", {"foo", "bar"});
|
|
auto fooOption = p.option("--foo", enumType);
|
|
auto parsed = p.parse({"--foo", "foo"});
|
|
EXPECT_EQ(fooOption->get(parsed), "foo");
|
|
parsed = p.parse({"--foo", "bar"});
|
|
EXPECT_EQ(fooOption->get(parsed), "bar");
|
|
}
|
|
|
|
TEST(Types, UnionType) {
|
|
argparser::parser p;
|
|
auto enumType1 = p.enum_type("enum", {"foo", "bar"});
|
|
auto enumType2 = p.enum_type<bool>("bool", {{"true", true}, {"false", false}});
|
|
auto unionType = p.union_type("enum-or-bool", enumType1, enumType2);
|
|
auto fooOption = p.option("--foo", unionType);
|
|
auto parsed = p.parse({"--foo", "bar"});
|
|
auto val = fooOption->get(parsed);
|
|
EXPECT_EQ(std::holds_alternative<std::string>(val), true);
|
|
EXPECT_EQ(std::get<std::string>(val), "bar");
|
|
parsed = p.parse({"--foo", "true"});
|
|
val = fooOption->get(parsed);
|
|
EXPECT_EQ(std::holds_alternative<bool>(val), true);
|
|
EXPECT_EQ(std::get<bool>(val), true);
|
|
}
|
|
|
|
TEST(Types, UnionTypeWithSameUnderlyingBaseType) {
|
|
argparser::parser p;
|
|
auto enumType1 = p.enum_type("enum", {"foo", "bar"});
|
|
auto enumType2 = p.enum_type("enum", {"hello", "world"});
|
|
auto unionType = p.union_type("enum-or-bool", enumType1, enumType2);
|
|
auto fooOption = p.option("--foo", unionType);
|
|
auto parsed = p.parse({"--foo", "bar"});
|
|
auto val = fooOption->get(parsed);
|
|
EXPECT_EQ(val, "bar");
|
|
parsed = p.parse({"--foo", "hello"});
|
|
val = fooOption->get(parsed);
|
|
EXPECT_EQ(val, "hello");
|
|
}
|
|
|
|
TEST(Types, UnionTypeError) {
|
|
argparser::parser p;
|
|
auto enumType1 = p.enum_type("enum", {"foo", "bar"});
|
|
auto enumType2 = p.enum_type<bool>("bool", {{"true", true}, {"false", false}});
|
|
auto unionType = p.union_type("union", enumType1, enumType2);
|
|
auto fooOption = p.option("--foo", unionType);
|
|
EXPECT_THROW(auto _ = p.parse({"--foo", "123"}), argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
TEST(Types, UnionTypeErrorOnAmbiguity) {
|
|
argparser::parser p;
|
|
auto enumType1 = p.enum_type<int>("enum1", {{"foo", 1}, {"bar", 2}});
|
|
auto enumType2 = p.enum_type<bool>("enum2", {{"bar", true}, {"hello-world", false}});
|
|
auto unionType = p.union_type("union", enumType1, enumType2);
|
|
auto fooOption = p.option("--foo", unionType);
|
|
EXPECT_THROW(auto _1 = p.parse({"--foo", "bar"});, argparser::errors::ambiguous_parse_error);
|
|
auto enumType3 = p.enum_type<int>("enum3", {{"bar", 1}, {"hello-world", 2}});
|
|
auto unionType2 = p.union_type("union", enumType1, enumType3);
|
|
auto barOption = p.option("--bar", unionType2);
|
|
EXPECT_THROW(auto _1 = p.parse({"--bar", "bar"});, argparser::errors::ambiguous_parse_error);
|
|
}
|
|
|
|
TEST(Types, UnionTypeNoAmbiguityErrorIfPossibleValuesIdentical) {
|
|
argparser::parser p;
|
|
auto enumType1 = p.enum_type<int>("enum1", {{"foo", 1}, {"bar", 2}});
|
|
auto enumType2 = p.enum_type<int>("enum2", {{"foo", 1}, {"foobar", 3}});
|
|
auto unionType = p.union_type("union", enumType1, enumType2);
|
|
auto fooOption = p.option("--foo", unionType);
|
|
argparser::parse_result parsed;
|
|
EXPECT_NO_THROW(parsed = p.parse({"--foo", "foo"}));
|
|
ASSERT_EQ(fooOption->get(parsed), 1);
|
|
}
|
|
|
|
TEST(Types, ListType) {
|
|
argparser::parser p;
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto listType = p.list_type("uint[]", uintType);
|
|
auto fooOption = p.option("--foo", listType);
|
|
auto parsed = p.parse({"--foo", "[1,2,3,4]"});
|
|
auto val = fooOption->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);
|
|
}
|
|
|
|
TEST(Types, ListTypeWithoutBracketsAtRoot) {
|
|
argparser::parser p;
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto listType = p.list_type("uint[]", uintType);
|
|
auto fooOption = p.option("--foo", listType);
|
|
auto parsed = p.parse({"--foo", "1,2,3,4"});
|
|
auto val = fooOption->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);
|
|
}
|
|
|
|
TEST(Types, ListTypeTrailingComma) {
|
|
argparser::parser p;
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto listType = p.list_type("uint[]", uintType);
|
|
auto fooOption = p.option("--foo", listType);
|
|
auto parsed = p.parse({"--foo", "[1,2,3,]"});
|
|
auto val = fooOption->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,2,3,"});
|
|
val = fooOption->get(parsed);
|
|
EXPECT_EQ(val.size(), 3);
|
|
EXPECT_EQ(val[0], 1);
|
|
EXPECT_EQ(val[1], 2);
|
|
EXPECT_EQ(val[2], 3);
|
|
}
|
|
|
|
TEST(Types, ListTypeOnlyOneTrailingComma) {
|
|
argparser::parser p;
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto listType = p.list_type("uint[]", uintType);
|
|
auto fooOption = p.option("--foo", listType);
|
|
EXPECT_THROW(auto _1 = p.parse({"--foo", "[1,2,3,,]"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "1,2,3,,"});, argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
TEST(Types, ListTypeNoPrecedingComma) {
|
|
argparser::parser p;
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto listType = p.list_type("uint[]", uintType);
|
|
auto fooOption = p.option("--foo", listType);
|
|
EXPECT_THROW(auto _1 = p.parse({"--foo", "[,1,2,3]"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", ",1,2,3"});, argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
TEST(Types, ListTypeNoDoubleComma) {
|
|
argparser::parser p;
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto listType = p.list_type("uint[]", uintType);
|
|
auto fooOption = p.option("--foo", listType);
|
|
EXPECT_THROW(auto _1 = p.parse({"--foo", "[1,,2,3]"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "[1, ,2,3]"});, argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
TEST(Types, ListTypeInvalidBrackets) {
|
|
argparser::parser p;
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto listType = p.list_type("uint[]", uintType);
|
|
auto fooOption = p.option("--foo", listType);
|
|
EXPECT_THROW(auto _1 = p.parse({"--foo", "[1,2,3"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "1,2,3]"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "1[,2,3"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "1,[2,3"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "1,2],3"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "1,2,]3"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "[1,2],3"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "[1,2,]3"});, argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
TEST(Types, TupleType) {
|
|
argparser::parser p;
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto boolType = p.enum_type<bool>("bool", {{"true", true}, {"false", false}});
|
|
auto tupleType = p.tuple_type("tuple", uintType, uintType, boolType);
|
|
auto fooOption = p.option("--foo", tupleType);
|
|
auto parsed = p.parse({"--foo", "(1,2,true)"});
|
|
auto val = fooOption->get(parsed);
|
|
EXPECT_EQ(std::get<0>(val), 1);
|
|
EXPECT_EQ(std::get<1>(val), 2);
|
|
EXPECT_EQ(std::get<2>(val), true);
|
|
}
|
|
TEST(Types, TupleTypeWithoutParenthesesAtRoot) {
|
|
argparser::parser p;
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto tupleType = p.tuple_type("tuple", uintType, uintType, uintType);
|
|
auto fooOption = p.option("--foo", tupleType);
|
|
auto parsed = p.parse({"--foo", "1,2,3"});
|
|
auto val = fooOption->get(parsed);
|
|
EXPECT_EQ(std::get<0>(val), 1);
|
|
EXPECT_EQ(std::get<1>(val), 2);
|
|
EXPECT_EQ(std::get<2>(val), 3);
|
|
}
|
|
|
|
TEST(Types, TupleTypeInvalidParentheses) {
|
|
argparser::parser p;
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto tupleType = p.tuple_type("tuple", uintType, uintType, uintType);
|
|
auto fooOption = p.option("--foo", tupleType);
|
|
EXPECT_THROW(auto _1 = p.parse({"--foo", "(1,2,3"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "1,2,3)"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "1(,2,3"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "1,(2,3"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "1,2),3"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "1,2,)3"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "(1,2),3"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "(1,2,)3"});, argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
TEST(Types, TupleTypeNoInvalidComma) {
|
|
argparser::parser p;
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto tupleType = p.tuple_type("tuple", uintType, uintType, uintType);
|
|
auto fooOption = p.option("--foo", tupleType);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "(1,2,3,)"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "(,1,2,3)"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "(1,,2,3)"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "(1, ,2,3)"});, argparser::errors::type_parsing_error);
|
|
EXPECT_THROW(auto _2 = p.parse({"--foo", "1,2,3,"});, argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
struct SomeStruct {
|
|
uint32_t foo;
|
|
uint32_t bar;
|
|
bool foobar;
|
|
};
|
|
|
|
TEST(Types, TupleTypeWithCustomType) {
|
|
argparser::parser p;
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto boolType = p.enum_type<bool>("bool", {{"true", true}, {"false", false}});
|
|
auto tupleType = p.tuple_type<SomeStruct>("tuple", uintType, uintType, boolType);
|
|
auto fooOption = p.option("--foo", tupleType);
|
|
auto parsed = p.parse({"--foo", "(1,2,true)"});
|
|
auto val = fooOption->get(parsed);
|
|
EXPECT_EQ(val.foo, 1);
|
|
EXPECT_EQ(val.bar, 2);
|
|
EXPECT_EQ(val.foobar, true);
|
|
}
|
|
|
|
TEST(Types, TupleWithCustomTypeAndCustomConstructor) {
|
|
argparser::parser p;
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto boolType = p.enum_type<bool>("bool", {{"true", true}, {"false", false}});
|
|
auto tupleType = p.tuple_type<SomeStruct>(
|
|
"tuple",
|
|
std::make_tuple(uintType, uintType, boolType),
|
|
[](uint32_t a, uint32_t b, bool c) {
|
|
return SomeStruct{a * 2, b * 3, !c};
|
|
});
|
|
auto fooOption = p.option("--foo", tupleType);
|
|
auto parsed = p.parse({"--foo", "(1,2,true)"});
|
|
auto val = fooOption->get(parsed);
|
|
EXPECT_EQ(val.foo, 2);
|
|
EXPECT_EQ(val.bar, 6);
|
|
EXPECT_EQ(val.foobar, false);
|
|
}
|
|
|
|
TEST(Types, TupleWithSharedPointerAndConstructor) {
|
|
argparser::parser p;
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto boolType = p.enum_type<bool>("bool", {{"true", true}, {"false", false}});
|
|
auto tupleType = p.tuple_type<std::shared_ptr<SomeStruct>>(
|
|
"tuple",
|
|
std::make_tuple(uintType, uintType, boolType),
|
|
[](uint32_t a, uint32_t b, bool c) {
|
|
return std::make_shared<SomeStruct>(a, b, c);
|
|
});
|
|
auto fooOption = p.option("--foo", tupleType);
|
|
auto parsed = p.parse({"--foo", "(1,2,true)"});
|
|
auto val = fooOption->get(parsed);
|
|
EXPECT_EQ(val->foo, 1);
|
|
EXPECT_EQ(val->bar, 2);
|
|
EXPECT_EQ(val->foobar, true);
|
|
}
|
|
|
|
class SomeVirtualClass {
|
|
public:
|
|
virtual int foo() = 0;
|
|
};
|
|
class SomeClass : public SomeVirtualClass {
|
|
public:
|
|
SomeClass(int a, int b) : a(a), b(b) {}
|
|
int a{};
|
|
int b{};
|
|
int foo() override {
|
|
return a + b;
|
|
}
|
|
};
|
|
|
|
TEST(Types, TupleWithSharedPointerToVirtualClass) {
|
|
argparser::parser p;
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto tupleType = p.tuple_type<std::shared_ptr<SomeVirtualClass>>(
|
|
"tuple",
|
|
std::make_tuple(uintType, uintType),
|
|
[](uint32_t a, uint32_t b) {
|
|
return std::make_shared<SomeClass>(a, b);
|
|
});
|
|
auto fooOption = p.option("--foo", tupleType);
|
|
auto parsed = p.parse({"--foo", "(1,2)"});
|
|
auto val = fooOption->get(parsed);
|
|
EXPECT_EQ(val->foo(), 3);
|
|
}
|
|
|
|
TEST(Types, TuplesCanBeNamePrefixed) {
|
|
argparser::parser p;
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto boolType = p.enum_type<bool>("bool", {{"true", true}, {"false", false}});
|
|
auto tupleType = p.tuple_type("tuple", uintType, uintType, boolType);
|
|
auto fooOption = p.option("--foo", tupleType);
|
|
auto parsed = p.parse({"--foo", "tuple(1,2,true)"});
|
|
auto val = fooOption->get(parsed);
|
|
EXPECT_EQ(std::get<0>(val), 1);
|
|
EXPECT_EQ(std::get<1>(val), 2);
|
|
EXPECT_EQ(std::get<2>(val), true);
|
|
}
|
|
|
|
TEST(Types, TupleNamePrefixMustBeCorrect) {
|
|
argparser::parser p;
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto boolType = p.enum_type<bool>("bool", {{"true", true}, {"false", false}});
|
|
auto tupleType = p.tuple_type("tuple", uintType, uintType, boolType);
|
|
auto fooOption = p.option("--foo", tupleType);
|
|
EXPECT_THROW(auto _1 = p.parse({"--foo", "foobar(1,2,true)"});, argparser::errors::type_parsing_error);
|
|
}
|
|
|
|
TEST(Types, ComplexNestedTypes) {
|
|
argparser::parser p;
|
|
auto uintType = p.basic_type<uint32_t>("uint");
|
|
auto tupleType = p.tuple_type("uint-tuple", uintType, uintType, uintType);
|
|
auto enumType = p.enum_type("enum", {"foo", "bar", "hello", "world"});
|
|
auto unionType = p.union_type("union", tupleType, enumType);
|
|
auto listType = p.list_type("uint-tuple-list", unionType);
|
|
auto fooOption = p.option("--foo", listType);
|
|
auto parsed = p.parse({"--foo", "[foo,(1,2,3),hello,world,(2,3,4),(4,5,6)]"});
|
|
auto val = fooOption->get(parsed);
|
|
using tuplet = std::tuple<uint32_t, uint32_t, uint32_t>;
|
|
EXPECT_EQ(val.size(), 6);
|
|
EXPECT_TRUE(std::holds_alternative<std::string>(val[0]));
|
|
EXPECT_EQ(std::get<std::string>(val[0]), "foo");
|
|
EXPECT_TRUE(std::holds_alternative<tuplet>(val[1]));
|
|
EXPECT_EQ(std::get<0>(std::get<tuplet>(val[1])), 1);
|
|
EXPECT_EQ(std::get<1>(std::get<tuplet>(val[1])), 2);
|
|
EXPECT_EQ(std::get<2>(std::get<tuplet>(val[1])), 3);
|
|
EXPECT_TRUE(std::holds_alternative<std::string>(val[2]));
|
|
EXPECT_EQ(std::get<std::string>(val[2]), "hello");
|
|
EXPECT_TRUE(std::holds_alternative<std::string>(val[3]));
|
|
EXPECT_EQ(std::get<std::string>(val[3]), "world");
|
|
EXPECT_TRUE(std::holds_alternative<tuplet>(val[4]));
|
|
EXPECT_EQ(std::get<0>(std::get<tuplet>(val[4])), 2);
|
|
EXPECT_EQ(std::get<1>(std::get<tuplet>(val[4])), 3);
|
|
EXPECT_EQ(std::get<2>(std::get<tuplet>(val[4])), 4);
|
|
EXPECT_TRUE(std::holds_alternative<tuplet>(val[5]));
|
|
EXPECT_EQ(std::get<0>(std::get<tuplet>(val[5])), 4);
|
|
EXPECT_EQ(std::get<1>(std::get<tuplet>(val[5])), 5);
|
|
EXPECT_EQ(std::get<2>(std::get<tuplet>(val[5])), 6);
|
|
}
|