Util+Test: Add code snapshot from the riyyi/manafiles project
Add all utility and unit test code from the riyyi/manafiles project at commit 6f0e3d6063ab75ad81899135689569e440ddb813, link at: github.com/riyyi/manafiles/tree/6f0e3d6063ab75ad81899135689569e440ddb813
This commit is contained in:
@@ -0,0 +1,949 @@
|
||||
#include <functional> // function
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "macro.h"
|
||||
#include "testcase.h"
|
||||
#include "testsuite.h"
|
||||
#include "util/argparser.h"
|
||||
|
||||
bool runParser(std::vector<const char*> arguments, std::function<void(Util::ArgParser&)> initializer = {})
|
||||
{
|
||||
stdout = Test::TestSuite::the().outputNull();
|
||||
|
||||
Util::ArgParser parser;
|
||||
if (initializer) {
|
||||
initializer(parser);
|
||||
}
|
||||
|
||||
arguments.insert(arguments.begin(), "app");
|
||||
auto result = parser.parse(arguments.size(), arguments.data());
|
||||
|
||||
stdout = Test::TestSuite::the().outputStd();
|
||||
return result;
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(NoArguments)
|
||||
{
|
||||
auto result = runParser({});
|
||||
EXPECT_EQ(result, true);
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(NonExistentArguments)
|
||||
{
|
||||
auto result = runParser({ "-n", "-e" });
|
||||
EXPECT_EQ(result, false);
|
||||
|
||||
result = runParser({ "--non", "--existent" });
|
||||
EXPECT_EQ(result, false);
|
||||
|
||||
result = runParser({ "-n", "-e", "--non", "--existent" });
|
||||
EXPECT_EQ(result, false);
|
||||
|
||||
result = runParser({ "no", "handling" });
|
||||
EXPECT_EQ(result, false);
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(RequiredStringArguments)
|
||||
{
|
||||
// Single required string argument
|
||||
std::string stringArg1 = "";
|
||||
auto result = runParser({ "my-required-argument" }, [&](auto& parser) {
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringArg1, "my-required-argument");
|
||||
|
||||
// Single required string argument, not given
|
||||
stringArg1 = "";
|
||||
result = runParser({}, [&](auto& parser) {
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, false);
|
||||
EXPECT_EQ(stringArg1, "");
|
||||
|
||||
// Multiple required string arguments
|
||||
stringArg1 = "";
|
||||
std::string stringArg2 = "";
|
||||
std::string stringArg3 = "";
|
||||
result = runParser({ "my", "required", "argument" }, [&](auto& parser) {
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
parser.addArgument(stringArg2, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
parser.addArgument(stringArg3, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringArg1, "my");
|
||||
EXPECT_EQ(stringArg2, "required");
|
||||
EXPECT_EQ(stringArg3, "argument");
|
||||
|
||||
// Multiple required string arguments, not given
|
||||
stringArg1 = "";
|
||||
stringArg2 = "";
|
||||
stringArg3 = "";
|
||||
result = runParser({}, [&](auto& parser) {
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
parser.addArgument(stringArg2, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
parser.addArgument(stringArg3, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, false);
|
||||
EXPECT_EQ(stringArg1, "");
|
||||
EXPECT_EQ(stringArg2, "");
|
||||
EXPECT_EQ(stringArg3, "");
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(OptionalStringArguments)
|
||||
{
|
||||
// Single optional string argument
|
||||
std::string stringArg1 = "";
|
||||
auto result = runParser({ "my-optional-argument" }, [&](auto& parser) {
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringArg1, "my-optional-argument");
|
||||
|
||||
// Single optional string argument, not given
|
||||
stringArg1 = "";
|
||||
result = runParser({}, [&](auto& parser) {
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringArg1, "");
|
||||
|
||||
// Multiple optional string arguments
|
||||
stringArg1 = "";
|
||||
std::string stringArg2 = "";
|
||||
std::string stringArg3 = "";
|
||||
result = runParser({ "my", "optional", "argument" }, [&](auto& parser) {
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
parser.addArgument(stringArg2, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
parser.addArgument(stringArg3, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringArg1, "my");
|
||||
EXPECT_EQ(stringArg2, "optional");
|
||||
EXPECT_EQ(stringArg3, "argument");
|
||||
|
||||
// Multiple optional string arguments, not given
|
||||
stringArg1 = "";
|
||||
stringArg2 = "";
|
||||
stringArg3 = "";
|
||||
result = runParser({}, [&](auto& parser) {
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
parser.addArgument(stringArg2, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
parser.addArgument(stringArg3, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringArg1, "");
|
||||
EXPECT_EQ(stringArg2, "");
|
||||
EXPECT_EQ(stringArg3, "");
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(NonRequiredStringArguments)
|
||||
{
|
||||
// Single non-required string argument
|
||||
std::string stringArg1 = "";
|
||||
auto result = runParser({ "my-non-required-argument" }, [&](auto& parser) {
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringArg1, "my-non-required-argument");
|
||||
|
||||
// Single non-required string argument, not given
|
||||
stringArg1 = "";
|
||||
result = runParser({}, [&](auto& parser) {
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringArg1, "");
|
||||
|
||||
// Multiple non-required string arguments
|
||||
stringArg1 = "";
|
||||
std::string stringArg2 = "";
|
||||
std::string stringArg3 = "";
|
||||
result = runParser({ "my", "non-required", "argument" }, [&](auto& parser) {
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
parser.addArgument(stringArg2, nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
parser.addArgument(stringArg3, nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringArg1, "my");
|
||||
EXPECT_EQ(stringArg2, "non-required");
|
||||
EXPECT_EQ(stringArg3, "argument");
|
||||
|
||||
// Multiple non-required string arguments, not given
|
||||
stringArg1 = "";
|
||||
stringArg2 = "";
|
||||
stringArg3 = "";
|
||||
result = runParser({}, [&](auto& parser) {
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
parser.addArgument(stringArg2, nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
parser.addArgument(stringArg3, nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringArg1, "");
|
||||
EXPECT_EQ(stringArg2, "");
|
||||
EXPECT_EQ(stringArg3, "");
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(VectorStringArguments)
|
||||
{
|
||||
// Required vector string argument, not given
|
||||
std::vector<std::string> vectorArg1 = {};
|
||||
auto result = runParser({}, [&](auto& parser) {
|
||||
parser.addArgument(vectorArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, false);
|
||||
EXPECT_EQ(vectorArg1.size(), 0);
|
||||
|
||||
// Required vector string argument, one given
|
||||
vectorArg1 = {};
|
||||
result = runParser({ "foo" }, [&](auto& parser) {
|
||||
parser.addArgument(vectorArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(vectorArg1.size(), 1);
|
||||
if (vectorArg1.size() == 1) {
|
||||
EXPECT_EQ(vectorArg1[0], "foo");
|
||||
}
|
||||
|
||||
// Required vector string argument, two given
|
||||
vectorArg1 = {};
|
||||
result = runParser({ "hello", "world" }, [&](auto& parser) {
|
||||
parser.addArgument(vectorArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(vectorArg1.size(), 2);
|
||||
if (vectorArg1.size() == 2) {
|
||||
EXPECT_EQ(vectorArg1[0], "hello");
|
||||
EXPECT_EQ(vectorArg1[1], "world");
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(CombinationOfNonRequiredArguments)
|
||||
{
|
||||
// Optional arguments, one given
|
||||
int intArg1 = 0;
|
||||
double doubleArg1 = 0;
|
||||
std::string stringArg1 = "";
|
||||
auto result = runParser({ "optional argument" }, [&](auto& parser) {
|
||||
parser.addArgument(intArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
parser.addArgument(doubleArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(intArg1, 0);
|
||||
EXPECT_EQ(doubleArg1, 0);
|
||||
EXPECT_EQ(stringArg1, "optional argument");
|
||||
|
||||
// Optional arguments, two given
|
||||
intArg1 = 0;
|
||||
doubleArg1 = 0;
|
||||
stringArg1 = "";
|
||||
result = runParser({ "999.999", "optional argument" }, [&](auto& parser) {
|
||||
parser.addArgument(intArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
parser.addArgument(doubleArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(intArg1, 0);
|
||||
EXPECT_EQ(doubleArg1, 999.999);
|
||||
EXPECT_EQ(stringArg1, "optional argument");
|
||||
|
||||
// Optional arguments, two given, one valid
|
||||
intArg1 = 0;
|
||||
doubleArg1 = 0;
|
||||
stringArg1 = "";
|
||||
result = runParser({ "999,999", "optional argument" }, [&](auto& parser) {
|
||||
parser.addArgument(intArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
parser.addArgument(doubleArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
});
|
||||
EXPECT_EQ(result, false);
|
||||
EXPECT_EQ(intArg1, 0);
|
||||
EXPECT_EQ(doubleArg1, 0);
|
||||
EXPECT_EQ(stringArg1, "999,999");
|
||||
|
||||
// Optional arguments, two given, both valid but wrong order
|
||||
stringArg1 = "";
|
||||
intArg1 = 0;
|
||||
doubleArg1 = 0;
|
||||
result = runParser({ "999.999", "optional argument" }, [&](auto& parser) {
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
parser.addArgument(intArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
parser.addArgument(doubleArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
});
|
||||
EXPECT_EQ(result, false);
|
||||
EXPECT_EQ(stringArg1, "999.999");
|
||||
EXPECT_EQ(intArg1, 0);
|
||||
EXPECT_EQ(doubleArg1, 0);
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(BoolOptions)
|
||||
{
|
||||
// Short option
|
||||
bool boolOpt1 = false;
|
||||
auto result = runParser({ "-b" }, [&](auto& parser) {
|
||||
parser.addOption(boolOpt1, 'b', nullptr, nullptr, nullptr);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(boolOpt1, true);
|
||||
|
||||
// Short option, not given
|
||||
boolOpt1 = false;
|
||||
result = runParser({}, [&](auto& parser) {
|
||||
parser.addOption(boolOpt1, 'b', nullptr, nullptr, nullptr);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(boolOpt1, false);
|
||||
|
||||
// Long option
|
||||
boolOpt1 = false;
|
||||
result = runParser({ "--bool" }, [&](auto& parser) {
|
||||
parser.addOption(boolOpt1, '\0', "bool", nullptr, nullptr);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(boolOpt1, true);
|
||||
|
||||
// Long option, not given
|
||||
boolOpt1 = false;
|
||||
result = runParser({}, [&](auto& parser) {
|
||||
parser.addOption(boolOpt1, '\0', "bool", nullptr, nullptr);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(boolOpt1, false);
|
||||
|
||||
// Allow both short and long option, provide short
|
||||
boolOpt1 = false;
|
||||
result = runParser({ "-b" }, [&](auto& parser) {
|
||||
parser.addOption(boolOpt1, 'b', "bool", nullptr, nullptr);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(boolOpt1, true);
|
||||
|
||||
// Allow both short and long option, provide long
|
||||
boolOpt1 = false;
|
||||
result = runParser({ "--bool" }, [&](auto& parser) {
|
||||
parser.addOption(boolOpt1, 'b', "bool", nullptr, nullptr);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(boolOpt1, true);
|
||||
|
||||
// Allow both short and long option, provide both
|
||||
boolOpt1 = false;
|
||||
result = runParser({ "-b", "--bool" }, [&](auto& parser) {
|
||||
parser.addOption(boolOpt1, 'b', "bool", nullptr, nullptr);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(boolOpt1, true);
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(SingleRequiredStringOptions)
|
||||
{
|
||||
// Single required string short option
|
||||
std::string stringOpt1 = "";
|
||||
auto result = runParser({ "-s", "my-required-argument" }, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, 's', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "my-required-argument");
|
||||
|
||||
// Single required string short option, given directly after
|
||||
stringOpt1 = "";
|
||||
result = runParser({ "-smy-required-argument" }, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, 's', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "my-required-argument");
|
||||
|
||||
// Single required string short option, empty given
|
||||
stringOpt1 = "";
|
||||
result = runParser({ "-s" }, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, 's', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, false);
|
||||
EXPECT_EQ(stringOpt1, "");
|
||||
|
||||
// Single required string short option, not given
|
||||
stringOpt1 = "";
|
||||
result = runParser({}, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, 's', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "");
|
||||
|
||||
// Single required string long option
|
||||
stringOpt1 = "";
|
||||
result = runParser({ "--string", "my-required-argument" }, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, '\0', "string", nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "my-required-argument");
|
||||
|
||||
// Single required string long option, given directly after
|
||||
stringOpt1 = "";
|
||||
result = runParser({ "--string=my-required-argument" }, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, '\0', "string", nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "my-required-argument");
|
||||
|
||||
// Single required string long option, empty given
|
||||
stringOpt1 = "";
|
||||
result = runParser({ "--string" }, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, '\0', "string", nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, false);
|
||||
EXPECT_EQ(stringOpt1, "");
|
||||
|
||||
// Single required string long option, not given
|
||||
stringOpt1 = "";
|
||||
result = runParser({}, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, '\0', "string", nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "");
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(SingleOptionalStringOptions)
|
||||
{
|
||||
// Single optional string short option
|
||||
std::string stringOpt1 = "";
|
||||
std::string stringArg1 = "";
|
||||
auto result = runParser({ "-s", "my-optional-argument" }, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, 's', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "");
|
||||
EXPECT_EQ(stringArg1, "my-optional-argument");
|
||||
|
||||
// Single optional string short option, given directly after
|
||||
stringOpt1 = "";
|
||||
result = runParser({ "-smy-optional-argument" }, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, 's', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "my-optional-argument");
|
||||
|
||||
// Single optional string short option, empty given
|
||||
stringOpt1 = "";
|
||||
result = runParser({ "-s" }, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, 's', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "");
|
||||
|
||||
// Single optional string short option, not given
|
||||
stringOpt1 = "";
|
||||
result = runParser({}, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, 's', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "");
|
||||
|
||||
// Single optional string long option
|
||||
stringOpt1 = "";
|
||||
stringArg1 = "";
|
||||
result = runParser({ "--string", "my-optional-argument" }, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, '\0', "string", nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "");
|
||||
EXPECT_EQ(stringArg1, "my-optional-argument");
|
||||
|
||||
// Single optional string long option, given directly after
|
||||
stringOpt1 = "";
|
||||
result = runParser({ "--string=my-optional-argument" }, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, '\0', "string", nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "my-optional-argument");
|
||||
|
||||
// Single optional string long option, empty given
|
||||
stringOpt1 = "";
|
||||
result = runParser({ "--string" }, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, '\0', "string", nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "");
|
||||
|
||||
// Single optional string long option, not given
|
||||
stringOpt1 = "";
|
||||
result = runParser({}, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, '\0', "string", nullptr, nullptr, nullptr, Util::ArgParser::Required::Optional);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "");
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(SingleNonRequiredStringOptions)
|
||||
{
|
||||
// Single non-required string short option
|
||||
std::string stringOpt1 = "";
|
||||
std::string stringArg1 = "";
|
||||
auto result = runParser({ "-s", "my-non-required-argument" }, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, 's', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "");
|
||||
EXPECT_EQ(stringArg1, "my-non-required-argument");
|
||||
|
||||
// Single non-required string short option, given directly after
|
||||
stringOpt1 = "";
|
||||
result = runParser({ "-smy-non-required-argument" }, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, 's', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
});
|
||||
EXPECT_EQ(result, false);
|
||||
EXPECT_EQ(stringOpt1, "");
|
||||
|
||||
// Single non-required string short option, empty given
|
||||
stringOpt1 = "";
|
||||
result = runParser({ "-s" }, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, 's', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "");
|
||||
|
||||
// Single non-required string short option, not given
|
||||
stringOpt1 = "";
|
||||
result = runParser({}, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, 's', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "");
|
||||
|
||||
// Single non-required string long option
|
||||
stringOpt1 = "";
|
||||
stringArg1 = "";
|
||||
result = runParser({ "--string", "my-non-required-argument" }, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, '\0', "string", nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
parser.addArgument(stringArg1, nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "");
|
||||
EXPECT_EQ(stringArg1, "my-non-required-argument");
|
||||
|
||||
// Single non-required string long option, given directly after
|
||||
stringOpt1 = "";
|
||||
result = runParser({ "--string=my-non-required-argument" }, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, '\0', "string", nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
});
|
||||
EXPECT_EQ(result, false);
|
||||
EXPECT_EQ(stringOpt1, "");
|
||||
|
||||
// Single non-required string long option, empty given
|
||||
stringOpt1 = "";
|
||||
result = runParser({ "--string" }, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, '\0', "string", nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "");
|
||||
|
||||
// Single non-required string long option, not given
|
||||
stringOpt1 = "";
|
||||
result = runParser({}, [&](auto& parser) {
|
||||
parser.addOption(stringOpt1, '\0', "string", nullptr, nullptr, nullptr, Util::ArgParser::Required::No);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(stringOpt1, "");
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(NumberOptions)
|
||||
{
|
||||
// Required int short option
|
||||
int intOpt1 = 0;
|
||||
auto result = runParser({ "-i", "2147483647" }, [&](auto& parser) {
|
||||
parser.addOption(intOpt1, 'i', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(intOpt1, 2147483647);
|
||||
|
||||
// Required int short option, overflown value given
|
||||
intOpt1 = 0;
|
||||
result = runParser({ "-i", "2147483648" }, [&](auto& parser) {
|
||||
parser.addOption(intOpt1, 'i', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, false);
|
||||
EXPECT_EQ(intOpt1, 0);
|
||||
|
||||
// Required int short option, empty given
|
||||
intOpt1 = 0;
|
||||
result = runParser({ "-i" }, [&](auto& parser) {
|
||||
parser.addOption(intOpt1, 'i', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, false);
|
||||
EXPECT_EQ(intOpt1, 0);
|
||||
|
||||
// Required unsigned int short option
|
||||
unsigned int unsignedIntOpt1 = 0;
|
||||
result = runParser({ "-u", "4294967295" }, [&](auto& parser) {
|
||||
parser.addOption(unsignedIntOpt1, 'u', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(unsignedIntOpt1, 4294967295);
|
||||
|
||||
// Required unsigned int short option, overflown value given
|
||||
unsignedIntOpt1 = 0;
|
||||
result = runParser({ "-u", "4294967296" }, [&](auto& parser) {
|
||||
parser.addOption(unsignedIntOpt1, 'u', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, false);
|
||||
EXPECT_EQ(unsignedIntOpt1, 0);
|
||||
|
||||
// Required unsigned int short option, empty given
|
||||
unsignedIntOpt1 = 0;
|
||||
result = runParser({ "-u" }, [&](auto& parser) {
|
||||
parser.addOption(unsignedIntOpt1, 'u', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, false);
|
||||
EXPECT_EQ(unsignedIntOpt1, 0);
|
||||
|
||||
// Required double short option
|
||||
double doubleOpt1 = 0;
|
||||
result = runParser({ "-d", "999.999" }, [&](auto& parser) {
|
||||
parser.addOption(doubleOpt1, 'd', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(doubleOpt1, 999.999);
|
||||
|
||||
// Required double short option, empty given
|
||||
doubleOpt1 = 0;
|
||||
result = runParser({ "-d" }, [&](auto& parser) {
|
||||
parser.addOption(doubleOpt1, 'd', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
});
|
||||
EXPECT_EQ(result, false);
|
||||
EXPECT_EQ(doubleOpt1, 0);
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(VectorStringOptions)
|
||||
{
|
||||
// Required vector string short option, not given
|
||||
std::vector<std::string> 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.at(0), "hello");
|
||||
EXPECT_EQ(vectorOpt1.at(1), "world");
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(MultipleOptions)
|
||||
{
|
||||
// Both short options, second is required, with a non-option parameter in-between
|
||||
bool boolOpt1 = false;
|
||||
std::string stringOpt1 = "";
|
||||
std::vector<std::string> vectorArg1 = {};
|
||||
auto result = runParser({ "-b", "something", "-s", "a-string-value" }, [&](auto& parser) {
|
||||
parser.addOption(boolOpt1, 'b', nullptr, nullptr, nullptr);
|
||||
parser.addOption(stringOpt1, 's', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||
parser.addArgument(vectorArg1, nullptr, nullptr, nullptr);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(boolOpt1, true);
|
||||
EXPECT_EQ(stringOpt1, "a-string-value");
|
||||
EXPECT_EQ(vectorArg1.size(), 1);
|
||||
if (vectorArg1.size() == 1) {
|
||||
EXPECT_EQ(vectorArg1.at(0), "something");
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(StopOnDoubleDashOption)
|
||||
{
|
||||
// Bool short options, missing
|
||||
// Expected: The bool options are interpreted as non-option parameters
|
||||
bool boolOpt1 = false;
|
||||
bool boolOpt2 = false;
|
||||
std::vector<std::string> vectorArg1 = {};
|
||||
auto result = runParser({ "--", "-b", "-c" }, [&](auto& parser) {
|
||||
parser.addOption(boolOpt1, 'b', nullptr, nullptr, nullptr);
|
||||
parser.addOption(boolOpt2, 'c', nullptr, nullptr, nullptr);
|
||||
parser.addArgument(vectorArg1, nullptr, nullptr, nullptr);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(boolOpt1, false);
|
||||
EXPECT_EQ(boolOpt2, false);
|
||||
EXPECT_EQ(vectorArg1.size(), 2);
|
||||
if (vectorArg1.size() == 2) {
|
||||
EXPECT_EQ(vectorArg1.at(0), "-b");
|
||||
EXPECT_EQ(vectorArg1.at(1), "-c");
|
||||
}
|
||||
|
||||
// Bool short options, one given
|
||||
// Expected: boolOpt1 is set, one non-option parameter
|
||||
boolOpt1 = false;
|
||||
boolOpt2 = false;
|
||||
vectorArg1 = {};
|
||||
result = runParser({ "-b", "--", "-c" }, [&](auto& parser) {
|
||||
parser.addOption(boolOpt1, 'b', nullptr, nullptr, nullptr);
|
||||
parser.addOption(boolOpt2, 'c', nullptr, nullptr, nullptr);
|
||||
parser.addArgument(vectorArg1, nullptr, nullptr, nullptr);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(boolOpt1, true);
|
||||
EXPECT_EQ(boolOpt2, false);
|
||||
EXPECT_EQ(vectorArg1.size(), 1);
|
||||
if (vectorArg1.size() == 1) {
|
||||
EXPECT_EQ(vectorArg1.at(0), "-c");
|
||||
}
|
||||
|
||||
// Bool long options, missing
|
||||
// Expected: The bool options are interpreted as non-option parameters
|
||||
boolOpt1 = false;
|
||||
boolOpt2 = false;
|
||||
vectorArg1 = {};
|
||||
result = runParser({ "--", "--bool", "--cool" }, [&](auto& parser) {
|
||||
parser.addOption(boolOpt1, '\0', "bool", nullptr, nullptr);
|
||||
parser.addOption(boolOpt2, '\0', "cool", nullptr, nullptr);
|
||||
parser.addArgument(vectorArg1, nullptr, nullptr, nullptr);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(boolOpt1, false);
|
||||
EXPECT_EQ(boolOpt2, false);
|
||||
EXPECT_EQ(vectorArg1.size(), 2);
|
||||
if (vectorArg1.size() == 2) {
|
||||
EXPECT_EQ(vectorArg1.at(0), "--bool");
|
||||
EXPECT_EQ(vectorArg1.at(1), "--cool");
|
||||
}
|
||||
|
||||
// Bool long options, one given
|
||||
// Expected: boolOpt1 is set, one non-option parameter
|
||||
boolOpt1 = false;
|
||||
boolOpt2 = false;
|
||||
vectorArg1 = {};
|
||||
result = runParser({ "--bool", "--", "--cool" }, [&](auto& parser) {
|
||||
parser.addOption(boolOpt1, '\0', "bool", nullptr, nullptr);
|
||||
parser.addOption(boolOpt2, '\0', "cool", nullptr, nullptr);
|
||||
parser.addArgument(vectorArg1, nullptr, nullptr, nullptr);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(boolOpt1, true);
|
||||
EXPECT_EQ(boolOpt2, false);
|
||||
EXPECT_EQ(vectorArg1.size(), 1);
|
||||
if (vectorArg1.size() == 1) {
|
||||
EXPECT_EQ(vectorArg1.at(0), "--cool");
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(StopOnFirstNonOption)
|
||||
{
|
||||
// Do not stop on first non-option; arguments are in correct order
|
||||
// Expected: The bool options are set and one non-option parameter
|
||||
bool boolOpt1 = false;
|
||||
bool boolOpt2 = false;
|
||||
std::vector<std::string> vectorArg1 = {};
|
||||
auto result = runParser({ "-b", "-c", "stopping" }, [&](auto& parser) {
|
||||
parser.setStopParsingOnFirstNonOption(false);
|
||||
parser.addOption(boolOpt1, 'b', nullptr, nullptr, nullptr);
|
||||
parser.addOption(boolOpt2, 'c', nullptr, nullptr, nullptr);
|
||||
parser.addArgument(vectorArg1, nullptr, nullptr, nullptr);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(boolOpt1, true);
|
||||
EXPECT_EQ(boolOpt2, true);
|
||||
EXPECT_EQ(vectorArg1.size(), 1);
|
||||
if (vectorArg1.size() == 1) {
|
||||
EXPECT_EQ(vectorArg1.at(0), "stopping");
|
||||
}
|
||||
|
||||
// Do not stop on first non-option; arguments are in wrong order
|
||||
// Expected: The bool options are set and one non-option parameter
|
||||
boolOpt1 = false;
|
||||
boolOpt2 = false;
|
||||
vectorArg1 = {};
|
||||
result = runParser({ "-b", "stopping", "-c" }, [&](auto& parser) {
|
||||
parser.setStopParsingOnFirstNonOption(false);
|
||||
parser.addOption(boolOpt1, 'b', nullptr, nullptr, nullptr);
|
||||
parser.addOption(boolOpt2, 'c', nullptr, nullptr, nullptr);
|
||||
parser.addArgument(vectorArg1, nullptr, nullptr, nullptr);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(boolOpt1, true);
|
||||
EXPECT_EQ(boolOpt2, true);
|
||||
EXPECT_EQ(vectorArg1.size(), 1);
|
||||
if (vectorArg1.size() == 1) {
|
||||
EXPECT_EQ(vectorArg1.at(0), "stopping");
|
||||
}
|
||||
|
||||
// Stop on first non option, arguments are in correct order
|
||||
// Expected: The bool options are set and one non-option parameter
|
||||
boolOpt1 = false;
|
||||
boolOpt2 = false;
|
||||
vectorArg1 = {};
|
||||
result = runParser({ "-b", "-c", "stopping" }, [&](auto& parser) {
|
||||
parser.setStopParsingOnFirstNonOption(true);
|
||||
parser.addOption(boolOpt1, 'b', nullptr, nullptr, nullptr);
|
||||
parser.addOption(boolOpt2, 'c', nullptr, nullptr, nullptr);
|
||||
parser.addArgument(vectorArg1, nullptr, nullptr, nullptr);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(boolOpt1, true);
|
||||
EXPECT_EQ(boolOpt2, true);
|
||||
EXPECT_EQ(vectorArg1.size(), 1);
|
||||
if (vectorArg1.size() == 1) {
|
||||
EXPECT_EQ(vectorArg1.at(0), "stopping");
|
||||
}
|
||||
|
||||
// Stop on first non option, arguments are in wrong order
|
||||
// Expected: boolOpt1 is set and the rest are non-option parameters
|
||||
boolOpt1 = false;
|
||||
boolOpt2 = false;
|
||||
vectorArg1 = {};
|
||||
result = runParser({ "-b", "stopping", "-c" }, [&](auto& parser) {
|
||||
parser.setStopParsingOnFirstNonOption(true);
|
||||
parser.addOption(boolOpt1, 'b', nullptr, nullptr, nullptr);
|
||||
parser.addOption(boolOpt2, 'c', nullptr, nullptr, nullptr);
|
||||
parser.addArgument(vectorArg1, nullptr, nullptr, nullptr);
|
||||
});
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(boolOpt1, true);
|
||||
EXPECT_EQ(boolOpt2, false);
|
||||
EXPECT_EQ(vectorArg1.size(), 2);
|
||||
if (vectorArg1.size() == 2) {
|
||||
EXPECT_EQ(vectorArg1.at(0), "stopping");
|
||||
EXPECT_EQ(vectorArg1.at(1), "-c");
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(ExitOnFirstError)
|
||||
{
|
||||
// Do not stop on first error, one non-existing given
|
||||
// Expected: parsing fails, boolOpt1 is set
|
||||
bool boolOpt1 = false;
|
||||
auto result = runParser({ "--this-doesnt-exist", "--this-exist" }, [&](auto& parser) {
|
||||
parser.setExitOnFirstError(false);
|
||||
parser.addOption(boolOpt1, '\0', "this-exist", nullptr, nullptr);
|
||||
});
|
||||
EXPECT_EQ(result, false);
|
||||
EXPECT_EQ(boolOpt1, true);
|
||||
|
||||
// Stop on first error, one non-existing given
|
||||
// Expected: parsing fails, boolOpt1 is not set
|
||||
boolOpt1 = false;
|
||||
result = runParser({ "--this-doesnt-exist", "--this-exist" }, [&](auto& parser) {
|
||||
parser.setExitOnFirstError(true);
|
||||
parser.addOption(boolOpt1, '\0', "this-exist", nullptr, nullptr);
|
||||
});
|
||||
EXPECT_EQ(result, false);
|
||||
EXPECT_EQ(boolOpt1, false);
|
||||
}
|
||||
@@ -0,0 +1,517 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Riyyi
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <cstddef> // size_t
|
||||
#include <cstdint> // int8_t, int16_t, int32_t, int64_t, uint8_t, uint16_t, uint32_t
|
||||
#include <map>
|
||||
#include <sstream> // stringstream
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "macro.h"
|
||||
#include "testcase.h"
|
||||
#include "testsuite.h"
|
||||
#include "util/format/format.h"
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(FormatIntegral)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
// Signed
|
||||
|
||||
int8_t i8 = 127; // char
|
||||
result = Util::format("{}", i8);
|
||||
EXPECT_EQ(result, "127");
|
||||
|
||||
int16_t i16 = 32767;
|
||||
result = Util::format("{}", i16);
|
||||
EXPECT_EQ(result, "32767");
|
||||
|
||||
int32_t i32 = 68766; // int
|
||||
result = Util::format("{}", i32);
|
||||
EXPECT_EQ(result, "68766");
|
||||
|
||||
int64_t i64 = 237942768427; // long int
|
||||
result = Util::format("{}", i64);
|
||||
EXPECT_EQ(result, "237942768427");
|
||||
|
||||
// Unsigned
|
||||
|
||||
uint8_t u8 = 255; // unsigned char
|
||||
result = Util::format("{}", u8);
|
||||
EXPECT_EQ(result, "255");
|
||||
|
||||
uint16_t u16 = 65535;
|
||||
result = Util::format("{}", u16);
|
||||
EXPECT_EQ(result, "65535");
|
||||
|
||||
uint32_t u32 = 4294967295; // unsigned int
|
||||
result = Util::format("{}", u32);
|
||||
EXPECT_EQ(result, "4294967295");
|
||||
|
||||
size_t u64 = 18446744073709551615; // long unsigned int
|
||||
result = Util::format("{}", u64);
|
||||
EXPECT_EQ(result, "18446744073709551615");
|
||||
}
|
||||
|
||||
TEST_CASE(FormatFloatingPoint)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
float f32R = 245789.70000;
|
||||
result = Util::format("{}", f32R);
|
||||
EXPECT_EQ(result, "245789.703125");
|
||||
|
||||
float f32 = 45645.3233;
|
||||
result = Util::format("{}", f32);
|
||||
EXPECT_EQ(result, "45645.324219");
|
||||
|
||||
double f64 = 87522.300000000;
|
||||
result = Util::format("{}", f64);
|
||||
EXPECT_EQ(result, "87522.300000");
|
||||
|
||||
double pi = 3.14159265359;
|
||||
result = Util::format("{}", pi);
|
||||
EXPECT_EQ(result, "3.141593");
|
||||
}
|
||||
|
||||
TEST_CASE(FormatChar)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
char character = 'A';
|
||||
result = Util::format("{}", character);
|
||||
EXPECT_EQ(result, "A");
|
||||
|
||||
bool boolean = true;
|
||||
result = Util::format("{}", boolean);
|
||||
EXPECT_EQ(result, "true");
|
||||
|
||||
boolean = false;
|
||||
result = Util::format("{}", boolean);
|
||||
EXPECT_EQ(result, "false");
|
||||
}
|
||||
|
||||
TEST_CASE(FormatString)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
result = Util::format("");
|
||||
EXPECT_EQ(result, "");
|
||||
|
||||
const char* cString = "C string";
|
||||
result = Util::format("{}", cString);
|
||||
EXPECT_EQ(result, "C string");
|
||||
|
||||
std::string string = "string";
|
||||
result = Util::format("{}", string);
|
||||
EXPECT_EQ(result, "string");
|
||||
|
||||
std::string_view stringView = "string_view";
|
||||
result = Util::format("{}", stringView);
|
||||
EXPECT_EQ(result, "string_view");
|
||||
|
||||
result = Util::format("{} {}", "Hello", "World");
|
||||
EXPECT_EQ(result, "Hello World");
|
||||
|
||||
result = Util::format("{{escaped braces}}");
|
||||
EXPECT_EQ(result, "{escaped braces}");
|
||||
|
||||
result = Util::format("{{braces{}}}", "Something");
|
||||
EXPECT_EQ(result, "{bracesSomething}");
|
||||
}
|
||||
|
||||
TEST_CASE(FormatPointer)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
result = Util::format("{}", nullptr);
|
||||
EXPECT_EQ(result, "0x0");
|
||||
|
||||
int integer = 42;
|
||||
std::stringstream stream;
|
||||
stream << &integer;
|
||||
std::string pointer = stream.str();
|
||||
|
||||
result = Util::format("{}", &integer);
|
||||
EXPECT_EQ(result, pointer);
|
||||
}
|
||||
|
||||
TEST_CASE(FormatSpecifierIntegral)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
// Fill and Align
|
||||
result = Util::format("{:+<}", 12345);
|
||||
EXPECT_EQ(result, "12345");
|
||||
result = Util::format("{:+^}", 12345);
|
||||
EXPECT_EQ(result, "12345");
|
||||
result = Util::format("{:+>}", 12345);
|
||||
EXPECT_EQ(result, "12345");
|
||||
|
||||
// Sign
|
||||
result = Util::format("{:+}", 12345);
|
||||
EXPECT_EQ(result, "+12345");
|
||||
result = Util::format("{:+}", -12345);
|
||||
EXPECT_EQ(result, "-12345");
|
||||
result = Util::format("{:-}", 12345);
|
||||
EXPECT_EQ(result, "12345");
|
||||
result = Util::format("{:-}", -12345);
|
||||
EXPECT_EQ(result, "-12345");
|
||||
result = Util::format("{: }", 12345);
|
||||
EXPECT_EQ(result, " 12345");
|
||||
result = Util::format("{: }", -12345);
|
||||
EXPECT_EQ(result, "-12345");
|
||||
|
||||
// AlternativeForm
|
||||
result = Util::format("{:#}", 12345);
|
||||
EXPECT_EQ(result, "12345");
|
||||
|
||||
// ZeroPadding
|
||||
result = Util::format("{:0}", 12345);
|
||||
EXPECT_EQ(result, "12345");
|
||||
|
||||
// Width
|
||||
result = Util::format("{:10}", 12345);
|
||||
EXPECT_EQ(result, " 12345");
|
||||
|
||||
// Width + Fill and Align
|
||||
result = Util::format("{:+<10}", 12345);
|
||||
EXPECT_EQ(result, "12345+++++");
|
||||
result = Util::format("{:+^10}", 12345);
|
||||
EXPECT_EQ(result, "++12345+++");
|
||||
result = Util::format("{:+>10}", 12345);
|
||||
EXPECT_EQ(result, "+++++12345");
|
||||
|
||||
// Width + ZeroPadding
|
||||
result = Util::format("{:010}", 12345);
|
||||
EXPECT_EQ(result, "0000012345");
|
||||
|
||||
// Precision
|
||||
// Not possible on integral types
|
||||
|
||||
// Type
|
||||
result = Util::format("{:b}", 12345);
|
||||
EXPECT_EQ(result, "11000000111001");
|
||||
result = Util::format("{:B}", 12345);
|
||||
EXPECT_EQ(result, "11000000111001");
|
||||
result = Util::format("{:c}", 65);
|
||||
EXPECT_EQ(result, "A");
|
||||
result = Util::format("{:o}", 12345);
|
||||
EXPECT_EQ(result, "30071");
|
||||
result = Util::format("{:x}", 62432);
|
||||
EXPECT_EQ(result, "f3e0");
|
||||
result = Util::format("{:X}", 62432);
|
||||
EXPECT_EQ(result, "F3E0");
|
||||
|
||||
// Type + AlternativeForm
|
||||
result = Util::format("{:#b}", 12345);
|
||||
EXPECT_EQ(result, "0b11000000111001");
|
||||
result = Util::format("{:#B}", 12345);
|
||||
EXPECT_EQ(result, "0B11000000111001");
|
||||
result = Util::format("{:#c}", 65);
|
||||
EXPECT_EQ(result, "A");
|
||||
result = Util::format("{:#o}", 12345);
|
||||
EXPECT_EQ(result, "030071");
|
||||
result = Util::format("{:#x}", 62432);
|
||||
EXPECT_EQ(result, "0xf3e0");
|
||||
result = Util::format("{:#X}", 62432);
|
||||
EXPECT_EQ(result, "0XF3E0");
|
||||
}
|
||||
|
||||
TEST_CASE(FormatSpecifierIntegralCombination)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
// AlternativeForm + ZeroPadding + Width + Type
|
||||
// ------------------------------
|
||||
|
||||
result = Util::format("{:-#010d}", 402);
|
||||
EXPECT_EQ(result, "0000000402");
|
||||
|
||||
// AlternativeForm + Width + Type
|
||||
// ------------------------------
|
||||
|
||||
result = Util::format("{:#10x}", 402);
|
||||
EXPECT_EQ(result, " 0x192");
|
||||
|
||||
// + Fill and Align
|
||||
|
||||
result = Util::format("{:^<#10x}", 402);
|
||||
EXPECT_EQ(result, "0x192^^^^^");
|
||||
|
||||
result = Util::format("{:^^#10x}", 402);
|
||||
EXPECT_EQ(result, "^^0x192^^^");
|
||||
|
||||
result = Util::format("{:^>#10x}", 402);
|
||||
EXPECT_EQ(result, "^^^^^0x192");
|
||||
|
||||
// ------------------------------
|
||||
|
||||
// + Sign
|
||||
|
||||
result = Util::format("{:+#10x}", 402);
|
||||
EXPECT_EQ(result, " +0x192");
|
||||
|
||||
// + Fill and Align + Sign
|
||||
|
||||
result = Util::format("{:^<+#10x}", 402);
|
||||
EXPECT_EQ(result, "+0x192^^^^");
|
||||
|
||||
result = Util::format("{:^^+#10x}", 402);
|
||||
EXPECT_EQ(result, "^^+0x192^^");
|
||||
|
||||
result = Util::format("{:^>+#10x}", 402);
|
||||
EXPECT_EQ(result, "^^^^+0x192");
|
||||
|
||||
// ------------------------------
|
||||
|
||||
// + ZeroPadding
|
||||
|
||||
result = Util::format("{:#010x}", 402);
|
||||
EXPECT_EQ(result, "0x00000192");
|
||||
|
||||
// Fill and Align + ZeroPadding
|
||||
|
||||
result = Util::format("{:^<#010x}", 402);
|
||||
EXPECT_EQ(result, "0x19200000");
|
||||
|
||||
result = Util::format("{:^^#010x}", 402);
|
||||
EXPECT_EQ(result, "000x192000");
|
||||
|
||||
result = Util::format("{:^>#010x}", 402);
|
||||
EXPECT_EQ(result, "000000x192");
|
||||
|
||||
// ------------------------------
|
||||
|
||||
// + Sign + ZeroPadding
|
||||
|
||||
result = Util::format("{:+#010x}", 402);
|
||||
EXPECT_EQ(result, "+0x0000192");
|
||||
|
||||
// + Fill and Align + Sign + ZeroPadding
|
||||
|
||||
result = Util::format("{:^<+#010x}", 402);
|
||||
EXPECT_EQ(result, "+0x1920000");
|
||||
|
||||
result = Util::format("{:^^+#010x}", 402);
|
||||
EXPECT_EQ(result, "00+0x19200");
|
||||
|
||||
result = Util::format("{:^>+#010x}", 402);
|
||||
EXPECT_EQ(result, "0000+0x192");
|
||||
}
|
||||
|
||||
TEST_CASE(FormatSpecifierFloatingPoint)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
double f64 = 87522.300000000;
|
||||
result = Util::format("{:.1}", f64);
|
||||
EXPECT_EQ(result, "87522.3");
|
||||
|
||||
double pi = 3.14159265359;
|
||||
result = Util::format("{}", pi);
|
||||
EXPECT_EQ(result, "3.141593");
|
||||
|
||||
result = Util::format("{:.15}", pi);
|
||||
EXPECT_EQ(result, "3.141592653590000");
|
||||
}
|
||||
|
||||
TEST_CASE(FormatSpecifierChar)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
char character = 65;
|
||||
result = Util::format("{:b}", character);
|
||||
EXPECT_EQ(result, "1000001");
|
||||
result = Util::format("{:B}", character);
|
||||
EXPECT_EQ(result, "1000001");
|
||||
result = Util::format("{:d}", character);
|
||||
EXPECT_EQ(result, "65");
|
||||
result = Util::format("{:o}", character);
|
||||
EXPECT_EQ(result, "101");
|
||||
result = Util::format("{:x}", character);
|
||||
EXPECT_EQ(result, "41");
|
||||
result = Util::format("{:X}", character);
|
||||
EXPECT_EQ(result, "41");
|
||||
|
||||
bool boolean = true;
|
||||
result = Util::format("{:b}", boolean);
|
||||
EXPECT_EQ(result, "1");
|
||||
result = Util::format("{:B}", boolean);
|
||||
EXPECT_EQ(result, "1");
|
||||
result = Util::format("{:d}", boolean);
|
||||
EXPECT_EQ(result, "1");
|
||||
result = Util::format("{:o}", boolean);
|
||||
EXPECT_EQ(result, "1");
|
||||
result = Util::format("{:x}", boolean);
|
||||
EXPECT_EQ(result, "1");
|
||||
result = Util::format("{:X}", boolean);
|
||||
EXPECT_EQ(result, "1");
|
||||
|
||||
boolean = false;
|
||||
result = Util::format("{:b}", boolean);
|
||||
EXPECT_EQ(result, "0");
|
||||
result = Util::format("{:B}", boolean);
|
||||
EXPECT_EQ(result, "0");
|
||||
result = Util::format("{:d}", boolean);
|
||||
EXPECT_EQ(result, "0");
|
||||
result = Util::format("{:o}", boolean);
|
||||
EXPECT_EQ(result, "0");
|
||||
result = Util::format("{:x}", boolean);
|
||||
EXPECT_EQ(result, "0");
|
||||
result = Util::format("{:X}", boolean);
|
||||
EXPECT_EQ(result, "0");
|
||||
}
|
||||
|
||||
TEST_CASE(FormatSpecifierString)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
std::string string = "my string";
|
||||
|
||||
// Fill and Align
|
||||
result = Util::format("{:+<}", string);
|
||||
EXPECT_EQ(result, "my string");
|
||||
result = Util::format("{:+^}", string);
|
||||
EXPECT_EQ(result, "my string");
|
||||
result = Util::format("{:+>}", string);
|
||||
EXPECT_EQ(result, "my string");
|
||||
|
||||
// Sign
|
||||
// Not possible on string types
|
||||
|
||||
// AlternativeForm
|
||||
// Not possible on string types
|
||||
|
||||
// ZeroPadding
|
||||
// Not possible on string types
|
||||
|
||||
// Width
|
||||
result = Util::format("{:15}", string);
|
||||
EXPECT_EQ(result, "my string ");
|
||||
|
||||
// Width + Fill and Align
|
||||
result = Util::format("{:+<15}", string);
|
||||
EXPECT_EQ(result, "my string++++++");
|
||||
result = Util::format("{:+^15}", string);
|
||||
EXPECT_EQ(result, "+++my string+++");
|
||||
result = Util::format("{:+>15}", string);
|
||||
EXPECT_EQ(result, "++++++my string");
|
||||
|
||||
// Precision
|
||||
// Not possible on string types
|
||||
|
||||
// Type
|
||||
result = Util::format("{:s}", string);
|
||||
EXPECT_EQ(result, "my string");
|
||||
}
|
||||
|
||||
TEST_CASE(FormatSpecifierPointer)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
int integer = 42;
|
||||
std::stringstream stream;
|
||||
stream << &integer;
|
||||
std::string pointer = stream.str();
|
||||
|
||||
// Fill and Align
|
||||
result = Util::format("{:+<}", &integer);
|
||||
EXPECT_EQ(result, pointer);
|
||||
result = Util::format("{:+^}", &integer);
|
||||
EXPECT_EQ(result, pointer);
|
||||
result = Util::format("{:+>}", &integer);
|
||||
EXPECT_EQ(result, pointer);
|
||||
|
||||
// Sign
|
||||
// Not possible on string types
|
||||
|
||||
// AlternativeForm
|
||||
// Not possible on string types
|
||||
|
||||
// ZeroPadding
|
||||
// Not possible on string types
|
||||
|
||||
// Width
|
||||
result = Util::format("{:24}", &integer);
|
||||
EXPECT_EQ(result, std::string(24 - pointer.length(), ' ') + pointer);
|
||||
|
||||
// Width + Fill and Align
|
||||
result = Util::format("{:+<24}", &integer);
|
||||
EXPECT_EQ(result, pointer + std::string(24 - pointer.length(), '+'));
|
||||
result = Util::format("{:+^24}", &integer);
|
||||
EXPECT_EQ(result, std::string((24 - pointer.length()) / 2, '+') + pointer + std::string((24 - pointer.length()) / 2, '+'));
|
||||
result = Util::format("{:+>24}", &integer);
|
||||
EXPECT_EQ(result, std::string(24 - pointer.length(), '+') + pointer);
|
||||
|
||||
// Precision
|
||||
// Not possible on string types
|
||||
|
||||
// Type
|
||||
result = Util::format("{:p}", &integer);
|
||||
EXPECT_EQ(result, pointer);
|
||||
}
|
||||
|
||||
TEST_CASE(FormatContainers)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
std::vector<std::string> vector { "thing1", "thing2", "thing3" };
|
||||
result = Util::format("{}", vector);
|
||||
EXPECT_EQ(result, "{thing1,thing2,thing3}");
|
||||
result = Util::format("{:1}", vector);
|
||||
EXPECT_EQ(result, "{ thing1, thing2, thing3 }");
|
||||
result = Util::format("{:#4}", vector);
|
||||
EXPECT_EQ(result, R"({
|
||||
thing1,
|
||||
thing2,
|
||||
thing3
|
||||
})");
|
||||
result = Util::format("{:\t<#1}", vector);
|
||||
EXPECT_EQ(result, R"({
|
||||
thing1,
|
||||
thing2,
|
||||
thing3
|
||||
})");
|
||||
|
||||
std::map<std::string, int> map { { "thing3", 3 }, { "thing2", 2 }, { "thing1", 1 } };
|
||||
result = Util::format("{}", map);
|
||||
EXPECT_EQ(result, R"({"thing1":1,"thing2":2,"thing3":3})");
|
||||
result = Util::format("{:1}", map);
|
||||
EXPECT_EQ(result, R"({ "thing1": 1, "thing2": 2, "thing3": 3 })");
|
||||
result = Util::format("{:#4}", map);
|
||||
EXPECT_EQ(result, R"({
|
||||
"thing1": 1,
|
||||
"thing2": 2,
|
||||
"thing3": 3
|
||||
})");
|
||||
result = Util::format("{:\t<#1}", map);
|
||||
EXPECT_EQ(result, R"({
|
||||
"thing1": 1,
|
||||
"thing2": 2,
|
||||
"thing3": 3
|
||||
})");
|
||||
|
||||
// Multidimensional containers arent supported,
|
||||
// the user should write a customization point
|
||||
std::vector<std::vector<std::string>> twoDimensionalVector {
|
||||
{ "thing1", "thing2", "thing3" },
|
||||
{ "thing1", "thing2", "thing3" }
|
||||
};
|
||||
result = Util::format("{:#4}", twoDimensionalVector);
|
||||
EXPECT_EQ(result, R"({
|
||||
{thing1,thing2,thing3},
|
||||
{thing1,thing2,thing3}
|
||||
})");
|
||||
}
|
||||
|
||||
// Local Variables:
|
||||
// lsp-in-cpp-project-cache: nil
|
||||
// End:
|
||||
@@ -0,0 +1,570 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Riyyi
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <cstddef> // nullptr_t
|
||||
#include <cstdint> // uint32_t
|
||||
#include <functional> // function
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "macro.h"
|
||||
#include "testcase.h"
|
||||
#include "testsuite.h"
|
||||
#include "util/json/array.h"
|
||||
#include "util/json/job.h"
|
||||
#include "util/json/json.h"
|
||||
#include "util/json/lexer.h"
|
||||
#include "util/json/parser.h"
|
||||
#include "util/json/serializer.h"
|
||||
|
||||
#define DONT_PRINT_PARSER_ERRORS
|
||||
|
||||
#ifndef DONT_PRINT_PARSER_ERRORS
|
||||
#define EXEC(x) x
|
||||
#else
|
||||
#define EXEC(x) \
|
||||
stderr = Test::TestSuite::the().outputNull(); \
|
||||
x; \
|
||||
stderr = Test::TestSuite::the().outputErr();
|
||||
#endif
|
||||
|
||||
std::vector<Util::JSON::Token> lex(const std::string& input)
|
||||
{
|
||||
EXEC(
|
||||
Util::JSON::Job job(input);
|
||||
Util::JSON::Lexer lexer(&job);
|
||||
lexer.analyze(););
|
||||
return *job.tokens();
|
||||
}
|
||||
|
||||
Util::Json parse(const std::string& input)
|
||||
{
|
||||
EXEC(
|
||||
Util::JSON::Job job(input);
|
||||
Util::JSON::Lexer lexer(&job);
|
||||
lexer.analyze(););
|
||||
|
||||
if (!job.success()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EXEC(
|
||||
Util::JSON::Parser parser(&job);
|
||||
Util::Json json = parser.parse(););
|
||||
|
||||
if (!job.success()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
std::string serialize(const std::string& input, uint32_t indent = 0)
|
||||
{
|
||||
EXEC(
|
||||
auto json = Util::Json::parse(input););
|
||||
return json.dump(indent);
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(JsonLexer)
|
||||
{
|
||||
std::vector<Util::JSON::Token> tokens;
|
||||
|
||||
// Literal
|
||||
|
||||
tokens = lex("true");
|
||||
EXPECT_EQ(tokens.size(), 1);
|
||||
EXPECT_EQ(tokens[0].symbol, "true");
|
||||
EXPECT(tokens[0].type == Util::JSON::Token::Type::Literal);
|
||||
|
||||
tokens = lex("false");
|
||||
EXPECT_EQ(tokens.size(), 1);
|
||||
EXPECT_EQ(tokens[0].symbol, "false");
|
||||
EXPECT(tokens[0].type == Util::JSON::Token::Type::Literal);
|
||||
|
||||
tokens = lex("null");
|
||||
EXPECT_EQ(tokens.size(), 1);
|
||||
EXPECT_EQ(tokens[0].symbol, "null");
|
||||
EXPECT(tokens[0].type == Util::JSON::Token::Type::Literal);
|
||||
|
||||
// Number
|
||||
|
||||
tokens = lex("3.14");
|
||||
EXPECT_EQ(tokens.size(), 1);
|
||||
EXPECT_EQ(tokens[0].symbol, "3.14");
|
||||
EXPECT(tokens[0].type == Util::JSON::Token::Type::Number);
|
||||
|
||||
tokens = lex("-3.14e+2");
|
||||
EXPECT_EQ(tokens.size(), 1);
|
||||
EXPECT_EQ(tokens[0].symbol, "-3.14e+2");
|
||||
EXPECT(tokens[0].type == Util::JSON::Token::Type::Number);
|
||||
|
||||
tokens = lex("+3.14");
|
||||
EXPECT_EQ(tokens.size(), 1);
|
||||
EXPECT_EQ(tokens[0].symbol, "+");
|
||||
EXPECT(tokens[0].type == Util::JSON::Token::Type::None);
|
||||
|
||||
// String
|
||||
|
||||
tokens = lex(R"("a string")");
|
||||
EXPECT_EQ(tokens.size(), 1);
|
||||
EXPECT_EQ(tokens[0].symbol, "a string");
|
||||
EXPECT(tokens[0].type == Util::JSON::Token::Type::String);
|
||||
|
||||
tokens = lex(R"("a string""another string")");
|
||||
EXPECT_EQ(tokens.size(), 2);
|
||||
EXPECT_EQ(tokens[0].symbol, "a string");
|
||||
EXPECT_EQ(tokens[1].symbol, "another string");
|
||||
EXPECT(tokens[0].type == Util::JSON::Token::Type::String);
|
||||
|
||||
tokens = lex("\"a string\nwill break on the newline symbol\"");
|
||||
EXPECT_EQ(tokens.size(), 1);
|
||||
EXPECT_EQ(tokens[0].symbol, "a string");
|
||||
EXPECT(tokens[0].type == Util::JSON::Token::Type::String);
|
||||
|
||||
// Array
|
||||
|
||||
tokens = lex("[]");
|
||||
EXPECT_EQ(tokens.size(), 2);
|
||||
EXPECT_EQ(tokens[0].symbol, "[");
|
||||
EXPECT_EQ(tokens[1].symbol, "]");
|
||||
|
||||
tokens = lex("[\n\n\n]");
|
||||
EXPECT_EQ(tokens.size(), 2);
|
||||
EXPECT_EQ(tokens[0].symbol, "[");
|
||||
EXPECT_EQ(tokens[1].symbol, "]");
|
||||
|
||||
// Object
|
||||
|
||||
tokens = lex("{}");
|
||||
EXPECT_EQ(tokens.size(), 2);
|
||||
EXPECT_EQ(tokens[0].symbol, "{");
|
||||
EXPECT_EQ(tokens[1].symbol, "}");
|
||||
|
||||
tokens = lex("{\n\n\n}");
|
||||
EXPECT_EQ(tokens.size(), 2);
|
||||
EXPECT_EQ(tokens[0].symbol, "{");
|
||||
EXPECT_EQ(tokens[1].symbol, "}");
|
||||
}
|
||||
|
||||
TEST_CASE(JsonParser)
|
||||
{
|
||||
Util::Json json;
|
||||
|
||||
json = parse("null");
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = parse("true");
|
||||
EXPECT_EQ(json.size(), 1);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Bool);
|
||||
|
||||
json = parse("false");
|
||||
EXPECT_EQ(json.size(), 1);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Bool);
|
||||
|
||||
json = parse("3.14");
|
||||
EXPECT_EQ(json.size(), 1);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Number);
|
||||
|
||||
json = parse(R"("a string")");
|
||||
EXPECT_EQ(json.size(), 1);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::String);
|
||||
|
||||
// Array
|
||||
|
||||
json = parse("[");
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = parse("[ 123");
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = parse("[ 123,");
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = parse("[ 123, ]");
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = parse("[ 123 456 ]");
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = parse("[]");
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Array);
|
||||
|
||||
json = parse(R"([ "element", 3.14 ])");
|
||||
EXPECT_EQ(json.size(), 2);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Array);
|
||||
|
||||
// Object
|
||||
|
||||
json = parse("{");
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = parse(R"({ "name")");
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = parse(R"({ "name":)");
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = parse(R"({ "name":,)");
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = parse(R"({ "name":"value")");
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = parse(R"({ "name":"value",)");
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = parse(R"({ "name":"value", })");
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = parse(R"({ "name" "value" })");
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = parse(R"({ 123 })");
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = parse("{}");
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Object);
|
||||
|
||||
json = parse(R"({ "name": "value", "name2": 3.14 })");
|
||||
EXPECT_EQ(json.size(), 2);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Object);
|
||||
|
||||
// Multiple root elements
|
||||
|
||||
json = parse("54 false");
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = parse("3.14, 666");
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = parse("true\nfalse");
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
}
|
||||
|
||||
TEST_CASE(JsonToJsonValue)
|
||||
{
|
||||
Util::Json json;
|
||||
|
||||
json = {};
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = nullptr;
|
||||
EXPECT_EQ(json.size(), 0);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Null);
|
||||
|
||||
json = true;
|
||||
EXPECT_EQ(json.size(), 1);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Bool);
|
||||
|
||||
json = false;
|
||||
EXPECT_EQ(json.size(), 1);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Bool);
|
||||
|
||||
json = 666;
|
||||
EXPECT_EQ(json.size(), 1);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Number);
|
||||
|
||||
json = 3.14;
|
||||
EXPECT_EQ(json.size(), 1);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Number);
|
||||
|
||||
const char* characters = "my string";
|
||||
json = characters;
|
||||
EXPECT_EQ(json.size(), 1);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::String);
|
||||
|
||||
std::string string = "my string";
|
||||
json = string;
|
||||
EXPECT_EQ(json.size(), 1);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::String);
|
||||
|
||||
// Nested Array with multiple types
|
||||
json = { "element", 3.14, true, nullptr, { "nested element", { "more nesting", { 1, 2, 3, "yes" } } } };
|
||||
EXPECT_EQ(json.size(), 5);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Array);
|
||||
|
||||
// Nested Object with multiple types
|
||||
json = { { "name", "value" }, { "name2", 3.14 }, { "name3", true }, { "name4", nullptr }, { "name5", { { "nested name", "value" } } } };
|
||||
EXPECT_EQ(json.size(), 5);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Object);
|
||||
|
||||
// Array with singular type
|
||||
std::vector<std::string> vector = { "element", "element2", "element3" };
|
||||
json = vector;
|
||||
EXPECT_EQ(json.size(), 3);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Array);
|
||||
|
||||
// Object with singular type
|
||||
std::map<std::string, std::string> map = { { "name", "value" }, { "name2", "value2" } };
|
||||
json = map;
|
||||
EXPECT_EQ(json.size(), 2);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Object);
|
||||
|
||||
// Object with singular type
|
||||
std::unordered_map<std::string, std::string> unorderedMap = { { "name", "value" }, { "name2", "value2" } };
|
||||
json = unorderedMap;
|
||||
EXPECT_EQ(json.size(), 2);
|
||||
EXPECT_EQ(json.type(), Util::Json::Type::Object);
|
||||
}
|
||||
|
||||
TEST_CASE(JsonFromJsonValue)
|
||||
{
|
||||
Util::Json json;
|
||||
|
||||
json = nullptr;
|
||||
EXPECT_EQ(json.get<std::nullptr_t>(), nullptr);
|
||||
|
||||
json = true;
|
||||
EXPECT_EQ(json.get<bool>(), true);
|
||||
|
||||
json = false;
|
||||
EXPECT_EQ(json.get<bool>(), false);
|
||||
|
||||
json = 666;
|
||||
EXPECT_EQ(json.get<int>(), 666);
|
||||
|
||||
json = 3.14;
|
||||
EXPECT_EQ(json.get<double>(), 3.14);
|
||||
|
||||
std::string string;
|
||||
json = "my string";
|
||||
json.getTo(string);
|
||||
EXPECT_EQ(string, "my string");
|
||||
EXPECT_EQ(json.get<std::string>(), "my string");
|
||||
|
||||
// Array with singular type
|
||||
json = { "element", "element2" };
|
||||
EXPECT_EQ(json[0].get<std::string>(), "element");
|
||||
EXPECT_EQ(json.at(1).get<std::string>(), "element2");
|
||||
auto array = json.get<std::vector<std::string>>();
|
||||
EXPECT_EQ(array.size(), 2);
|
||||
EXPECT_EQ(array[0], "element");
|
||||
EXPECT_EQ(array[1], "element2");
|
||||
|
||||
// Array with multiple types
|
||||
json = { "string", 3.14, true, nullptr };
|
||||
EXPECT_EQ(json[0].get<std::string>(), "string");
|
||||
EXPECT_EQ(json.at(1).get<double>(), 3.14);
|
||||
EXPECT_EQ(json[2].get<bool>(), true);
|
||||
EXPECT_EQ(json[3].get<std::nullptr_t>(), nullptr);
|
||||
auto valueArray = json.get<std::vector<Util::Json>>();
|
||||
EXPECT_EQ(valueArray.size(), 4);
|
||||
EXPECT_EQ(valueArray[0].get<std::string>(), "string");
|
||||
EXPECT_EQ(valueArray[1].get<double>(), 3.14);
|
||||
EXPECT_EQ(valueArray[2].get<bool>(), true);
|
||||
EXPECT_EQ(valueArray[3].get<std::nullptr_t>(), nullptr);
|
||||
|
||||
// Nested Array with multiple types
|
||||
json = {
|
||||
"value",
|
||||
{
|
||||
"thing",
|
||||
666,
|
||||
},
|
||||
{
|
||||
{
|
||||
3.14,
|
||||
},
|
||||
}
|
||||
};
|
||||
EXPECT_EQ(json[0].get<std::string>(), "value");
|
||||
EXPECT_EQ(json.at(1)[0].get<std::string>(), "thing");
|
||||
EXPECT_EQ(json[1].at(1).get<int>(), 666);
|
||||
EXPECT_EQ(json[2][0][0].get<double>(), 3.14);
|
||||
|
||||
// Object with singular type
|
||||
json = { { "name", "value" }, { "name2", "value2" } };
|
||||
EXPECT_EQ(json["name"].get<std::string>(), "value");
|
||||
EXPECT_EQ(json.at("name2").get<std::string>(), "value2");
|
||||
auto object = json.get<std::map<std::string, std::string>>();
|
||||
EXPECT_EQ(object.size(), 2);
|
||||
EXPECT_EQ(object["name"], "value");
|
||||
EXPECT_EQ(object["name2"], "value2");
|
||||
auto unorderedObject = json.get<std::unordered_map<std::string, std::string>>();
|
||||
EXPECT_EQ(unorderedObject.size(), 2);
|
||||
EXPECT_EQ(unorderedObject["name"], "value");
|
||||
EXPECT_EQ(unorderedObject["name2"], "value2");
|
||||
|
||||
// Object with multiple types
|
||||
json = { { "name", "value" }, { "name2", 3.14 }, { "name3", true }, { "name4", nullptr } };
|
||||
EXPECT_EQ(json["name"].get<std::string>(), "value");
|
||||
EXPECT_EQ(json.at("name2").get<double>(), 3.14);
|
||||
EXPECT_EQ(json["name3"].get<bool>(), true);
|
||||
EXPECT_EQ(json["name4"].get<std::nullptr_t>(), nullptr);
|
||||
auto valueObject = json.get<std::map<std::string, Util::Json>>();
|
||||
EXPECT_EQ(valueObject.size(), 4);
|
||||
EXPECT_EQ(valueObject["name"].get<std::string>(), "value");
|
||||
EXPECT_EQ(valueObject["name2"].get<double>(), 3.14);
|
||||
EXPECT_EQ(valueObject["name3"].get<bool>(), true);
|
||||
EXPECT_EQ(valueObject["name4"].get<std::nullptr_t>(), nullptr);
|
||||
|
||||
// Nested Object with multiple types
|
||||
json = {
|
||||
{
|
||||
"name",
|
||||
"value",
|
||||
},
|
||||
{
|
||||
"nest 1-deep",
|
||||
{ {
|
||||
"number",
|
||||
1,
|
||||
} },
|
||||
},
|
||||
{
|
||||
"nest 2-deep",
|
||||
{ {
|
||||
"nest 1-deep",
|
||||
{ {
|
||||
"bool",
|
||||
true,
|
||||
} },
|
||||
} },
|
||||
},
|
||||
};
|
||||
EXPECT_EQ(json["name"].get<std::string>(), "value");
|
||||
EXPECT_EQ(json["nest 1-deep"]["number"].get<int>(), 1);
|
||||
EXPECT_EQ(json["nest 2-deep"]["nest 1-deep"]["bool"].get<bool>(), true);
|
||||
}
|
||||
|
||||
TEST_CASE(JsonImplicitConversion)
|
||||
{
|
||||
Util::Json array;
|
||||
array[0];
|
||||
EXPECT_EQ(array.type(), Util::Json::Type::Array);
|
||||
|
||||
Util::Json arrayEmplace;
|
||||
arrayEmplace.emplace_back("element");
|
||||
arrayEmplace.emplace_back({ "nested element" });
|
||||
EXPECT_EQ(arrayEmplace.type(), Util::Json::Type::Array);
|
||||
EXPECT_EQ(arrayEmplace[1].type(), Util::Json::Type::Array);
|
||||
|
||||
Util::Json object;
|
||||
object[""];
|
||||
EXPECT_EQ(object.type(), Util::Json::Type::Object);
|
||||
|
||||
Util::Json objectEmplace;
|
||||
objectEmplace.emplace("name", "value");
|
||||
objectEmplace.emplace("name2", { { "nested name", "value" } });
|
||||
EXPECT_EQ(objectEmplace.type(), Util::Json::Type::Object);
|
||||
EXPECT_EQ(objectEmplace["name2"].type(), Util::Json::Type::Object);
|
||||
}
|
||||
|
||||
TEST_CASE(JsonSerializer)
|
||||
{
|
||||
EXPECT_EQ(serialize(""), "null");
|
||||
EXPECT_EQ(serialize("null"), "null");
|
||||
EXPECT_EQ(serialize("true"), "true");
|
||||
EXPECT_EQ(serialize("false"), "false");
|
||||
EXPECT_EQ(serialize("3.14"), "3.14");
|
||||
EXPECT_EQ(serialize(R"("string")"), R"("string")");
|
||||
|
||||
EXPECT_EQ(serialize("\n\n\n"), "null");
|
||||
EXPECT_EQ(serialize("null\n"), "null");
|
||||
EXPECT_EQ(serialize("true\n"), "true");
|
||||
EXPECT_EQ(serialize("false\n"), "false");
|
||||
EXPECT_EQ(serialize("3.14\n"), "3.14");
|
||||
// clang-format off
|
||||
EXPECT_EQ(serialize(R"("string")" "\n"), R"("string")");
|
||||
// clang-format on
|
||||
|
||||
EXPECT_EQ(serialize("[\n\n\n]"), "[]");
|
||||
EXPECT_EQ(serialize("[null]"), "[null]");
|
||||
EXPECT_EQ(serialize("[true]"), "[true]");
|
||||
EXPECT_EQ(serialize("[false]"), "[false]");
|
||||
EXPECT_EQ(serialize("[3.14]"), "[3.14]");
|
||||
EXPECT_EQ(serialize(R"(["string"])"), R"(["string"])");
|
||||
|
||||
EXPECT_EQ(serialize("[\n\n\n]", 4), "[\n]");
|
||||
EXPECT_EQ(serialize("[null]", 4), "[\n null\n]");
|
||||
EXPECT_EQ(serialize("[true]", 4), "[\n true\n]");
|
||||
EXPECT_EQ(serialize("[false]", 4), "[\n false\n]");
|
||||
EXPECT_EQ(serialize("[3.14]", 4), "[\n 3.14\n]");
|
||||
// clang-format off
|
||||
EXPECT_EQ(serialize(R"(["string"])", 4), "[\n " R"("string")" "\n]");
|
||||
// clang-format on
|
||||
|
||||
// Check for trailing comma on last array element
|
||||
EXPECT_EQ(serialize(R"([1])"), R"([1])");
|
||||
EXPECT_EQ(serialize(R"([1,2])"), R"([1,2])");
|
||||
EXPECT_EQ(serialize(R"([1,2,3])"), R"([1,2,3])");
|
||||
|
||||
// Check for trailing comma on last object member
|
||||
EXPECT_EQ(serialize(R"({"n1":"v1"})"), R"({"n1":"v1"})");
|
||||
EXPECT_EQ(serialize(R"({"n1":"v1", "n2":"v2"})"), R"({"n1":"v1","n2":"v2"})");
|
||||
EXPECT_EQ(serialize(R"({"n1":"v1", "n2":"v2", "n3":"v3"})"), R"({"n1":"v1","n2":"v2","n3":"v3"})");
|
||||
|
||||
// clang-format off
|
||||
EXPECT_EQ(serialize(R"({
|
||||
"object member one": [
|
||||
"array element one"
|
||||
],
|
||||
"object member two": [
|
||||
"array element one",
|
||||
"array element two"
|
||||
],
|
||||
"object member three": [
|
||||
"array element one",
|
||||
2,
|
||||
3.0,
|
||||
4.56,
|
||||
true,
|
||||
false,
|
||||
null
|
||||
],
|
||||
"object member four": 3.14,
|
||||
"object member five": "value five",
|
||||
"object member six": null,
|
||||
"object member seven": { "no": 0 }
|
||||
})", 4), R"({
|
||||
"object member five": "value five",
|
||||
"object member four": 3.14,
|
||||
"object member one": [
|
||||
"array element one"
|
||||
],
|
||||
"object member seven": {
|
||||
"no": 0
|
||||
},
|
||||
"object member six": null,
|
||||
"object member three": [
|
||||
"array element one",
|
||||
2,
|
||||
3,
|
||||
4.56,
|
||||
true,
|
||||
false,
|
||||
null
|
||||
],
|
||||
"object member two": [
|
||||
"array element one",
|
||||
"array element two"
|
||||
]
|
||||
})");
|
||||
// clang-format on
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include <string>
|
||||
|
||||
#include "macro.h"
|
||||
#include "testcase.h"
|
||||
#include "testsuite.h"
|
||||
#include "util/shell.h"
|
||||
|
||||
bool runShell(const char* command, std::string* output = nullptr)
|
||||
{
|
||||
stdout = Test::TestSuite::the().outputNull();
|
||||
|
||||
Util::Shell $;
|
||||
auto exec = $(command);
|
||||
if (output) {
|
||||
*output = exec.output();
|
||||
}
|
||||
|
||||
stdout = Test::TestSuite::the().outputStd();
|
||||
return !exec.status() ? true : false;
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(ShellCommand)
|
||||
{
|
||||
// Pipe test, grep section of the echo command, return true
|
||||
std::string output = "";
|
||||
auto result = runShell("echo 'Hello World!' | grep --only-matching 'Hello'", &output);
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(output, "Hello\n");
|
||||
|
||||
// Return false
|
||||
result = runShell("exit 1");
|
||||
EXPECT_EQ(result, false);
|
||||
|
||||
// Return false
|
||||
result = runShell("failure() { return 1; }; failure");
|
||||
EXPECT_EQ(result, false);
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
#include <functional> // function
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "macro.h"
|
||||
#include "testcase.h"
|
||||
#include "testsuite.h"
|
||||
#include "util/system.h"
|
||||
|
||||
bool runSystem(std::function<Util::System(Util::System&)> commands, std::string* output = nullptr, std::string* error = nullptr)
|
||||
{
|
||||
Util::System system;
|
||||
auto exec = commands(system);
|
||||
if (output) {
|
||||
*output = exec.output();
|
||||
}
|
||||
if (error) {
|
||||
*error = exec.error();
|
||||
}
|
||||
|
||||
return !exec.status() ? true : false;
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
TEST_CASE(SystemCommand)
|
||||
{
|
||||
// Regular echo command, return true
|
||||
std::string output = "";
|
||||
std::string error = "";
|
||||
auto result = runSystem([&](auto& $) {
|
||||
return $("echo Hello World!")();
|
||||
}, &output, &error);
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(output, "Hello World!\n");
|
||||
EXPECT_EQ(error, "");
|
||||
|
||||
// Apend output of two echo commands, return true
|
||||
output = "";
|
||||
error = "";
|
||||
result = runSystem([&](auto& $) {
|
||||
return $("echo -n Hello ") + $("echo -n World!");
|
||||
}, &output, &error);
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(output, "Hello World!");
|
||||
EXPECT_EQ(error, "");
|
||||
|
||||
// Pipe test, grep section of the echo command, return true
|
||||
output = "";
|
||||
error = "";
|
||||
result = runSystem([&](auto& $) {
|
||||
return $("echo Hello World!") | $("grep --only-matching Hello");
|
||||
}, &output, &error);
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(output, "Hello\n");
|
||||
EXPECT_EQ(error, "");
|
||||
|
||||
// Run all commands until first false, return true
|
||||
output = "";
|
||||
error = "";
|
||||
result = runSystem([&](auto& $) {
|
||||
return $("echo Hello") && $("echo World!");
|
||||
}, &output, &error);
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(output, "Hello\nWorld!\n");
|
||||
EXPECT_EQ(error, "");
|
||||
|
||||
// Run all commands until first true, return true
|
||||
output = "";
|
||||
error = "";
|
||||
result = runSystem([&](auto& $) {
|
||||
return $("echo Hello") || $("echo World!");
|
||||
}, &output, &error);
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(output, "Hello\n");
|
||||
EXPECT_EQ(error, "");
|
||||
|
||||
// And plus pipe test, grep the middle word, return true
|
||||
output = "";
|
||||
error = "";
|
||||
result = runSystem([&](auto& $) {
|
||||
return ($("echo -n one ") && $("echo -n two ") && $("echo -n three")) | $("grep --only-matching two");
|
||||
}, &output, &error);
|
||||
EXPECT_EQ(result, true);
|
||||
EXPECT_EQ(output, "two\n");
|
||||
EXPECT_EQ(error, "");
|
||||
|
||||
// FIXME waitpid does not seem to get the right exit status here
|
||||
// Return false
|
||||
output = "";
|
||||
error = "";
|
||||
result = runSystem([&](auto& $) {
|
||||
return $("exit 1")();
|
||||
}, &output, &error);
|
||||
EXPECT_EQ(result, false);
|
||||
EXPECT_EQ(output, "");
|
||||
EXPECT_EQ(error, "");
|
||||
}
|
||||
Reference in New Issue
Block a user