diff options
-rw-r--r-- | Tests/LibCore/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Tests/LibCore/TestLibCoreArgsParser.cpp | 209 |
2 files changed, 210 insertions, 0 deletions
diff --git a/Tests/LibCore/CMakeLists.txt b/Tests/LibCore/CMakeLists.txt index 1a949bfd2f..934d2982a2 100644 --- a/Tests/LibCore/CMakeLists.txt +++ b/Tests/LibCore/CMakeLists.txt @@ -1,5 +1,6 @@ set( TEST_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/TestLibCoreArgsParser.cpp ${CMAKE_CURRENT_SOURCE_DIR}/TestLibCoreFileWatcher.cpp ) diff --git a/Tests/LibCore/TestLibCoreArgsParser.cpp b/Tests/LibCore/TestLibCoreArgsParser.cpp new file mode 100644 index 0000000000..8292e20369 --- /dev/null +++ b/Tests/LibCore/TestLibCoreArgsParser.cpp @@ -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"); + } +} +} |