From 68cdd625b4b60b6790ee96acf181f4e509b94175 Mon Sep 17 00:00:00 2001 From: Riyyi Date: Mon, 6 Sep 2021 00:08:04 +0200 Subject: [PATCH] Util+Test: Add parsing of multi-value options --- src/util/argparser.cpp | 17 +++++++ src/util/argparser.h | 1 + test/testutilargparser.cpp | 102 +++++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+) diff --git a/src/util/argparser.cpp b/src/util/argparser.cpp index 664a7cd..e4060b7 100644 --- a/src/util/argparser.cpp +++ b/src/util/argparser.cpp @@ -293,4 +293,21 @@ void ArgParser::addOption(std::string& value, char shortName, const char* longNa addOption(std::move(option)); } +void ArgParser::addOption(std::vector& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName, Required requiresArgument) +{ + Option option { + shortName, + longName, + argumentName, + usageString, + manString, + requiresArgument, + [&value](const char* a) -> bool { + value.push_back(a); + return true; + } + }; + addOption(std::move(option)); +} + } // namespace Util diff --git a/src/util/argparser.h b/src/util/argparser.h index ae5b38e..34613d6 100644 --- a/src/util/argparser.h +++ b/src/util/argparser.h @@ -47,6 +47,7 @@ public: void addOption(Option&& option); void addOption(bool& value, char shortName, const char* longName, const char* usageString, const char* manString); void addOption(std::string& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName = "", Required requiresArgument = Required::No); + void addOption(std::vector& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName = "", Required requiresArgument = Required::No); void setOptionIndex(int index) { m_optionIndex = index; } void setExitOnFirstError(bool state) { m_exitOnFirstError = state; } diff --git a/test/testutilargparser.cpp b/test/testutilargparser.cpp index 89dee86..60241b4 100644 --- a/test/testutilargparser.cpp +++ b/test/testutilargparser.cpp @@ -1,4 +1,5 @@ #include +#include #include "macro.h" #include "testcase.h" @@ -299,6 +300,105 @@ TEST_CASE(SingleNonRequiredStringOptions) // ----------------------------------------- +TEST_CASE(VectorStringOptions) +{ + // Required vector string short option, not given + std::vector vectorOpt1 = {}; + auto result = runParser({}, [&](auto& parser) { + parser.addOption(vectorOpt1, 'v', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes); + }); + EXPECT_EQ(result, true); + EXPECT_EQ(vectorOpt1.size(), 0); + + // Required vector string short option, empty given + vectorOpt1 = {}; + result = runParser({ "-v" }, [&](auto& parser) { + parser.addOption(vectorOpt1, 'v', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes); + }); + EXPECT_EQ(result, false); + EXPECT_EQ(vectorOpt1.size(), 0); + + // Required vector string short option, one given + vectorOpt1 = {}; + result = runParser({ "-v", "a vector argument!" }, [&](auto& parser) { + parser.addOption(vectorOpt1, 'v', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes); + }); + EXPECT_EQ(result, true); + EXPECT_EQ(vectorOpt1.size(), 1); + if (vectorOpt1.size() == 1) { + EXPECT_EQ(vectorOpt1[0], "a vector argument!"); + } + + // Required vector string short option, two given + vectorOpt1 = {}; + result = runParser({ "-v", "hello", "-v", "world" }, [&](auto& parser) { + parser.addOption(vectorOpt1, 'v', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes); + }); + EXPECT_EQ(result, true); + EXPECT_EQ(vectorOpt1.size(), 2); + if (vectorOpt1.size() == 2) { + EXPECT_EQ(vectorOpt1[0], "hello"); + EXPECT_EQ(vectorOpt1[1], "world"); + } + + // Required vector string short option, two given directly after + vectorOpt1 = {}; + result = runParser({ "-vhello", "-vworld" }, [&](auto& parser) { + parser.addOption(vectorOpt1, 'v', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes); + }); + EXPECT_EQ(result, true); + EXPECT_EQ(vectorOpt1.size(), 2); + if (vectorOpt1.size() == 2) { + EXPECT_EQ(vectorOpt1[0], "hello"); + EXPECT_EQ(vectorOpt1[1], "world"); + } + + // Required vector string long option, empty given + vectorOpt1 = {}; + result = runParser({ "--vector" }, [&](auto& parser) { + parser.addOption(vectorOpt1, '\0', "vector", nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes); + }); + EXPECT_EQ(result, false); + EXPECT_EQ(vectorOpt1.size(), 0); + + // Required vector string long option, one given + vectorOpt1 = {}; + result = runParser({ "--vector", "a vector argument!" }, [&](auto& parser) { + parser.addOption(vectorOpt1, '\0', "vector", nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes); + }); + EXPECT_EQ(result, true); + EXPECT_EQ(vectorOpt1.size(), 1); + if (vectorOpt1.size() == 1) { + EXPECT_EQ(vectorOpt1[0], "a vector argument!"); + } + + // Required vector string long option, two given + vectorOpt1 = {}; + result = runParser({ "--vector", "hello", "--vector", "world" }, [&](auto& parser) { + parser.addOption(vectorOpt1, '\0', "vector", nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes); + }); + EXPECT_EQ(result, true); + EXPECT_EQ(vectorOpt1.size(), 2); + if (vectorOpt1.size() == 2) { + EXPECT_EQ(vectorOpt1[0], "hello"); + EXPECT_EQ(vectorOpt1[1], "world"); + } + + // Required vector string long option, two given directly after + vectorOpt1 = {}; + result = runParser({ "--vector=hello", "--vector=world" }, [&](auto& parser) { + parser.addOption(vectorOpt1, '\0', "vector", nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes); + }); + EXPECT_EQ(result, true); + EXPECT_EQ(vectorOpt1.size(), 2); + if (vectorOpt1.size() == 2) { + EXPECT_EQ(vectorOpt1[0], "hello"); + EXPECT_EQ(vectorOpt1[1], "world"); + } +} + +// ----------------------------------------- + TEST_CASE(MultipleOptions) { // Both short options, second is required, with a non-option argument in-between @@ -313,6 +413,8 @@ TEST_CASE(MultipleOptions) EXPECT_EQ(stringOpt1, "a-string-value"); } +// ----------------------------------------- + TEST_CASE(NonOptionMode) { // Bool short options, missing