Forráskód Böngészése

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.
Jelle Raaijmakers 4 éve
szülő
commit
0b0bce78f6
2 módosított fájl, 210 hozzáadás és 0 törlés
  1. 1 0
      Tests/LibCore/CMakeLists.txt
  2. 209 0
      Tests/LibCore/TestLibCoreArgsParser.cpp

+ 1 - 0
Tests/LibCore/CMakeLists.txt

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

+ 209 - 0
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");
+    }
+}
+}