LibCore/ArgsParser: Add test suite

This adds a very basic test suite for ArgsParser that we can use to set
a baseline of functionality that we want to make sure keeps working.
This commit is contained in:
Jelle Raaijmakers 2021-06-07 20:01:12 +02:00 committed by Andreas Kling
parent d6a3f1fcd7
commit 0b0bce78f6
Notes: sideshowbarker 2024-07-18 12:39:09 +09:00
2 changed files with 210 additions and 0 deletions

View file

@ -1,5 +1,6 @@
set(
TEST_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/TestLibCoreArgsParser.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TestLibCoreFileWatcher.cpp
)

View file

@ -0,0 +1,209 @@
/*
* Copyright (c) 2021, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/Function.h>
#include <AK/Vector.h>
#include <LibCore/ArgsParser.h>
#include <LibTest/TestCase.h>
#include <string.h>
static char** build_argv(Vector<String> arguments)
{
auto argv = new char*[arguments.size() + 1];
size_t idx = 0;
for (auto& argument : arguments) {
auto char_argument = new char[argument.length() + 1];
memcpy(char_argument, argument.characters(), argument.length());
char_argument[argument.length()] = '\0';
argv[idx++] = char_argument;
}
argv[idx++] = nullptr;
return argv;
}
static void delete_argv(char** argv, size_t number_of_arguments)
{
for (size_t idx = 0; idx < number_of_arguments; ++idx)
delete[] argv[idx];
delete[] argv;
}
static bool run_parser(Vector<String> arguments, Function<void(Core::ArgsParser&)> parser_initialization = {})
{
Core::ArgsParser parser;
if (parser_initialization)
parser_initialization(parser);
auto argv = build_argv(arguments);
auto result = parser.parse(arguments.size(), argv, Core::ArgsParser::FailureBehavior::Ignore);
delete_argv(argv, arguments.size());
return result;
}
TEST_CASE(no_arguments)
{
auto parser_result = run_parser({ "app" });
EXPECT_EQ(parser_result, true);
}
TEST_CASE(bool_option)
{
// Short option
bool force = false;
auto parser_result = run_parser({ "app", "-f" }, [&](auto& parser) {
parser.add_option(force, "force", nullptr, 'f');
});
EXPECT_EQ(parser_result, true);
EXPECT_EQ(force, true);
// Short option, not given
force = false;
parser_result = run_parser({ "app" }, [&](auto& parser) {
parser.add_option(force, "force", nullptr, 'f');
});
EXPECT_EQ(parser_result, true);
EXPECT_EQ(force, false);
// Long option
force = false;
parser_result = run_parser({ "app", "--force" }, [&](auto& parser) {
parser.add_option(force, "force", "force", '\0');
});
EXPECT_EQ(parser_result, true);
EXPECT_EQ(force, true);
// Long option, not given
force = false;
parser_result = run_parser({ "app" }, [&](auto& parser) {
parser.add_option(force, "force", "force", '\0');
});
EXPECT_EQ(parser_result, true);
EXPECT_EQ(force, false);
// Allow both short and long option, provide short
force = false;
parser_result = run_parser({ "app", "-f" }, [&](auto& parser) {
parser.add_option(force, "force", "force", 'f');
});
EXPECT_EQ(parser_result, true);
EXPECT_EQ(force, true);
// Allow both short and long option, provide long
force = false;
parser_result = run_parser({ "app", "--force" }, [&](auto& parser) {
parser.add_option(force, "force", "force", 'f');
});
EXPECT_EQ(parser_result, true);
EXPECT_EQ(force, true);
// Allow both short and long option, provide both
force = false;
parser_result = run_parser({ "app", "--force", "-f" }, [&](auto& parser) {
parser.add_option(force, "force", "force", 'f');
});
EXPECT_EQ(parser_result, true);
EXPECT_EQ(force, true);
}
TEST_CASE(positional_string_argument)
{
// Single required string argument
String name = "";
auto parser_result = run_parser({ "app", "buggie" }, [&](auto& parser) {
parser.add_positional_argument(name, "name", "name", Core::ArgsParser::Required::Yes);
});
EXPECT_EQ(parser_result, true);
EXPECT_EQ(name, "buggie");
// Single required string argument, not given
name = "";
parser_result = run_parser({ "app" }, [&](auto& parser) {
parser.add_positional_argument(name, "name", "name", Core::ArgsParser::Required::Yes);
});
EXPECT_EQ(parser_result, false);
EXPECT_EQ(name, "");
// Single optional string argument
name = "";
parser_result = run_parser({ "app", "buggie" }, [&](auto& parser) {
parser.add_positional_argument(name, "name", "name", Core::ArgsParser::Required::No);
});
EXPECT_EQ(parser_result, true);
EXPECT_EQ(name, "buggie");
// Single optional string argument, not given
name = "";
parser_result = run_parser({ "app" }, [&](auto& parser) {
parser.add_positional_argument(name, "name", "name", Core::ArgsParser::Required::No);
});
EXPECT_EQ(parser_result, true);
EXPECT_EQ(name, "");
}
TEST_CASE(positional_vector_string_argument)
{
// Zero or more positional arguments, zero given
Vector<String> values = {};
auto parser_result = run_parser({ "app" }, [&](auto& parser) {
parser.add_positional_argument(values, "values", "values", Core::ArgsParser::Required::No);
});
EXPECT_EQ(parser_result, true);
EXPECT_EQ(values.size(), 0u);
// Zero or more positional arguments, one given
values = {};
parser_result = run_parser({ "app", "one" }, [&](auto& parser) {
parser.add_positional_argument(values, "values", "values", Core::ArgsParser::Required::No);
});
EXPECT_EQ(parser_result, true);
EXPECT_EQ(values.size(), 1u);
if (values.size() == 1u)
EXPECT_EQ(values[0], "one");
// Zero or more positional arguments, two given
values = {};
parser_result = run_parser({ "app", "one", "two" }, [&](auto& parser) {
parser.add_positional_argument(values, "values", "values", Core::ArgsParser::Required::No);
});
EXPECT_EQ(parser_result, true);
EXPECT_EQ(values.size(), 2u);
if (values.size() == 2u) {
EXPECT_EQ(values[0], "one");
EXPECT_EQ(values[1], "two");
}
// One or more positional arguments, zero given
values = {};
parser_result = run_parser({ "app" }, [&](auto& parser) {
parser.add_positional_argument(values, "values", "values", Core::ArgsParser::Required::Yes);
});
EXPECT_EQ(parser_result, false);
EXPECT_EQ(values.size(), 0u);
// One or more positional arguments, one given
values = {};
parser_result = run_parser({ "app", "one" }, [&](auto& parser) {
parser.add_positional_argument(values, "values", "values", Core::ArgsParser::Required::Yes);
});
EXPECT_EQ(parser_result, true);
EXPECT_EQ(values.size(), 1u);
if (values.size() == 1u)
EXPECT_EQ(values[0], "one");
// One or more positional arguments, two given
values = {};
parser_result = run_parser({ "app", "one", "two" }, [&](auto& parser) {
parser.add_positional_argument(values, "values", "values", Core::ArgsParser::Required::Yes);
});
EXPECT_EQ(parser_result, true);
EXPECT_EQ(values.size(), 2u);
if (values.size() == 2u) {
EXPECT_EQ(values[0], "one");
EXPECT_EQ(values[1], "two");
}
}
}