diff options
author | Brian Gianforcaro <bgianf@serenityos.org> | 2021-11-26 16:27:35 -0800 |
---|---|---|
committer | Brian Gianforcaro <b.gianfo@gmail.com> | 2021-11-26 18:57:26 -0800 |
commit | 95c0ec9afc89d8651e41c46c9087faae71328be7 (patch) | |
tree | e9f25c18230568d0d1c068ae2ed648ef5dee5a6c /Tests/LibCore/TestLibCoreArgsParser.cpp | |
parent | f807796380e89a03aeed1c46b82d6012e5f9dad7 (diff) | |
download | serenity-95c0ec9afc89d8651e41c46c9087faae71328be7.zip |
Tests: Fix TestLibCoreArgsParser with add_positional_argument API change
Since we no longer populate a Vector<String> the lifetime of the strings
in all of these tests is now messed up, as the Vector<StringView> now
points to free'd memory.
We attempt to fix this for the unit tests, by saving the results in a
RAII type that should live as long as the test wants to validate some
output of the ArgParser.
Diffstat (limited to 'Tests/LibCore/TestLibCoreArgsParser.cpp')
-rw-r--r-- | Tests/LibCore/TestLibCoreArgsParser.cpp | 136 |
1 files changed, 82 insertions, 54 deletions
diff --git a/Tests/LibCore/TestLibCoreArgsParser.cpp b/Tests/LibCore/TestLibCoreArgsParser.cpp index b19f0fab81..9883e3bd82 100644 --- a/Tests/LibCore/TestLibCoreArgsParser.cpp +++ b/Tests/LibCore/TestLibCoreArgsParser.cpp @@ -10,44 +10,71 @@ #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; +class ParserResult { +public: + ParserResult(Vector<String> const& arguments) + { + argv = new char*[arguments.size() + 1]; + argc = 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[argc++] = char_argument; + } + argv[argc] = nullptr; } - 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; -} + ParserResult(ParserResult&& other) + { + result = other.result; + argv = other.argv; + argc = other.argc; + + other.argv = nullptr; + other.argc = 0; + } + + ParserResult& operator=(ParserResult&& other) + { + if (this != &other) { + result = other.result; + argv = other.argv; + argc = other.argc; + + other.argv = nullptr; + other.argc = 0; + } + return *this; + } + + ~ParserResult() + { + for (size_t i = 0; i < argc; ++i) + delete[] argv[i]; + delete[] argv; + } + + bool result { false }; + char** argv { nullptr }; + size_t argc { 0 }; +}; -static bool run_parser(Vector<String> arguments, Function<void(Core::ArgsParser&)> parser_initialization = {}) +static ParserResult 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; + auto parse_result = ParserResult { arguments }; + parse_result.result = parser.parse(parse_result.argc, parse_result.argv, Core::ArgsParser::FailureBehavior::Ignore); + return parse_result; } TEST_CASE(no_arguments) { auto parser_result = run_parser({ "app" }); - EXPECT_EQ(parser_result, true); + EXPECT_EQ(parser_result.result, true); } TEST_CASE(bool_option) @@ -57,7 +84,7 @@ TEST_CASE(bool_option) auto parser_result = run_parser({ "app", "-f" }, [&](auto& parser) { parser.add_option(force, "force", nullptr, 'f'); }); - EXPECT_EQ(parser_result, true); + EXPECT_EQ(parser_result.result, true); EXPECT_EQ(force, true); // Short option, not given @@ -65,7 +92,7 @@ TEST_CASE(bool_option) parser_result = run_parser({ "app" }, [&](auto& parser) { parser.add_option(force, "force", nullptr, 'f'); }); - EXPECT_EQ(parser_result, true); + EXPECT_EQ(parser_result.result, true); EXPECT_EQ(force, false); // Long option @@ -73,7 +100,7 @@ TEST_CASE(bool_option) parser_result = run_parser({ "app", "--force" }, [&](auto& parser) { parser.add_option(force, "force", "force", '\0'); }); - EXPECT_EQ(parser_result, true); + EXPECT_EQ(parser_result.result, true); EXPECT_EQ(force, true); // Long option, not given @@ -81,7 +108,7 @@ TEST_CASE(bool_option) parser_result = run_parser({ "app" }, [&](auto& parser) { parser.add_option(force, "force", "force", '\0'); }); - EXPECT_EQ(parser_result, true); + EXPECT_EQ(parser_result.result, true); EXPECT_EQ(force, false); // Allow both short and long option, provide short @@ -89,7 +116,7 @@ TEST_CASE(bool_option) parser_result = run_parser({ "app", "-f" }, [&](auto& parser) { parser.add_option(force, "force", "force", 'f'); }); - EXPECT_EQ(parser_result, true); + EXPECT_EQ(parser_result.result, true); EXPECT_EQ(force, true); // Allow both short and long option, provide long @@ -97,7 +124,7 @@ TEST_CASE(bool_option) parser_result = run_parser({ "app", "--force" }, [&](auto& parser) { parser.add_option(force, "force", "force", 'f'); }); - EXPECT_EQ(parser_result, true); + EXPECT_EQ(parser_result.result, true); EXPECT_EQ(force, true); // Allow both short and long option, provide both @@ -105,7 +132,7 @@ TEST_CASE(bool_option) parser_result = run_parser({ "app", "--force", "-f" }, [&](auto& parser) { parser.add_option(force, "force", "force", 'f'); }); - EXPECT_EQ(parser_result, true); + EXPECT_EQ(parser_result.result, true); EXPECT_EQ(force, true); } @@ -116,7 +143,7 @@ TEST_CASE(positional_string_argument) 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(parser_result.result, true); EXPECT_EQ(name, "buggie"); // Single required string argument, not given @@ -124,7 +151,7 @@ TEST_CASE(positional_string_argument) 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(parser_result.result, false); EXPECT_EQ(name, ""); // Single optional string argument @@ -132,7 +159,7 @@ TEST_CASE(positional_string_argument) 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(parser_result.result, true); EXPECT_EQ(name, "buggie"); // Single optional string argument, not given @@ -140,18 +167,19 @@ TEST_CASE(positional_string_argument) 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(parser_result.result, true); EXPECT_EQ(name, ""); } TEST_CASE(positional_vector_string_argument) { - // Zero or more positional arguments, zero given Vector<StringView> values; + + // Zero or more positional arguments, zero given 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(parser_result.result, true); EXPECT_EQ(values.size(), 0u); // Zero or more positional arguments, one given @@ -159,7 +187,7 @@ TEST_CASE(positional_vector_string_argument) 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(parser_result.result, true); EXPECT_EQ(values.size(), 1u); if (values.size() == 1u) EXPECT_EQ(values[0], "one"); @@ -169,7 +197,7 @@ TEST_CASE(positional_vector_string_argument) 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(parser_result.result, true); EXPECT_EQ(values.size(), 2u); if (values.size() == 2u) { EXPECT_EQ(values[0], "one"); @@ -181,7 +209,7 @@ TEST_CASE(positional_vector_string_argument) 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(parser_result.result, false); EXPECT_EQ(values.size(), 0u); // One or more positional arguments, one given @@ -189,7 +217,7 @@ TEST_CASE(positional_vector_string_argument) 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(parser_result.result, true); EXPECT_EQ(values.size(), 1u); if (values.size() == 1u) EXPECT_EQ(values[0], "one"); @@ -199,7 +227,7 @@ TEST_CASE(positional_vector_string_argument) 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(parser_result.result, true); EXPECT_EQ(values.size(), 2u); if (values.size() == 2u) { EXPECT_EQ(values[0], "one"); @@ -209,17 +237,17 @@ TEST_CASE(positional_vector_string_argument) TEST_CASE(combination_of_bool_options_with_positional_vector_string) { + Vector<StringView> positionals; // Bool options (given) and positional arguments (given) // Expected: all arguments fill as given bool bool_opt1 = false; bool bool_opt2 = false; - Vector<StringView> positionals; auto parser_result = run_parser({ "app", "-b", "-c", "one", "two" }, [&](auto& parser) { parser.add_option(bool_opt1, "bool_opt1", nullptr, 'b'); parser.add_option(bool_opt2, "bool_opt2", nullptr, 'c'); parser.add_positional_argument(positionals, "pos", "pos", Core::ArgsParser::Required::No); }); - EXPECT_EQ(parser_result, true); + EXPECT_EQ(parser_result.result, true); EXPECT_EQ(bool_opt1, true); EXPECT_EQ(bool_opt2, true); EXPECT_EQ(positionals.size(), 2u); @@ -238,7 +266,7 @@ TEST_CASE(combination_of_bool_options_with_positional_vector_string) parser.add_option(bool_opt2, "bool_opt2", nullptr, 'c'); parser.add_positional_argument(positionals, "pos", "pos", Core::ArgsParser::Required::No); }); - EXPECT_EQ(parser_result, true); + EXPECT_EQ(parser_result.result, true); EXPECT_EQ(bool_opt1, false); EXPECT_EQ(bool_opt2, false); EXPECT_EQ(positionals.size(), 2u); @@ -257,7 +285,7 @@ TEST_CASE(combination_of_bool_options_with_positional_vector_string) parser.add_option(bool_opt2, "bool_opt2", nullptr, 'c'); parser.add_positional_argument(positionals, "pos", "pos", Core::ArgsParser::Required::No); }); - EXPECT_EQ(parser_result, true); + EXPECT_EQ(parser_result.result, true); EXPECT_EQ(bool_opt1, true); EXPECT_EQ(bool_opt2, true); EXPECT_EQ(positionals.size(), 0u); @@ -272,7 +300,7 @@ TEST_CASE(combination_of_bool_options_with_positional_vector_string) parser.add_option(bool_opt2, "bool_opt2", nullptr, 'c'); parser.add_positional_argument(positionals, "pos", "pos", Core::ArgsParser::Required::No); }); - EXPECT_EQ(parser_result, true); + EXPECT_EQ(parser_result.result, true); EXPECT_EQ(bool_opt1, false); EXPECT_EQ(bool_opt2, false); EXPECT_EQ(positionals.size(), 2u); @@ -291,7 +319,7 @@ TEST_CASE(combination_of_bool_options_with_positional_vector_string) parser.add_option(bool_opt2, "bool_opt2", nullptr, 'c'); parser.add_positional_argument(positionals, "pos", "pos", Core::ArgsParser::Required::No); }); - EXPECT_EQ(parser_result, true); + EXPECT_EQ(parser_result.result, true); EXPECT_EQ(bool_opt1, true); EXPECT_EQ(bool_opt2, false); EXPECT_EQ(positionals.size(), 1u); @@ -309,7 +337,7 @@ TEST_CASE(combination_of_bool_options_with_positional_vector_string) parser.add_option(bool_opt2, "bool_opt2", nullptr, 'c'); parser.add_positional_argument(positionals, "pos", "pos", Core::ArgsParser::Required::No); }); - EXPECT_EQ(parser_result, false); + EXPECT_EQ(parser_result.result, false); }; TEST_CASE(stop_on_first_non_option) @@ -325,7 +353,7 @@ TEST_CASE(stop_on_first_non_option) parser.add_option(bool_opt2, "bool_opt2", nullptr, 'c'); parser.add_positional_argument(positionals, "pos", "pos", Core::ArgsParser::Required::Yes); }); - EXPECT_EQ(parser_result, true); + EXPECT_EQ(parser_result.result, true); EXPECT_EQ(bool_opt1, true); EXPECT_EQ(bool_opt2, true); EXPECT_EQ(positionals.size(), 1u); @@ -343,7 +371,7 @@ TEST_CASE(stop_on_first_non_option) parser.add_option(bool_opt2, "bool_opt2", nullptr, 'c'); parser.add_positional_argument(positionals, "pos", "pos", Core::ArgsParser::Required::Yes); }); - EXPECT_EQ(parser_result, true); + EXPECT_EQ(parser_result.result, true); EXPECT_EQ(bool_opt1, true); EXPECT_EQ(bool_opt2, true); EXPECT_EQ(positionals.size(), 1u); @@ -361,7 +389,7 @@ TEST_CASE(stop_on_first_non_option) parser.add_option(bool_opt2, "bool_opt2", nullptr, 'c'); parser.add_positional_argument(positionals, "pos", "pos", Core::ArgsParser::Required::Yes); }); - EXPECT_EQ(parser_result, true); + EXPECT_EQ(parser_result.result, true); EXPECT_EQ(bool_opt1, true); EXPECT_EQ(bool_opt2, true); EXPECT_EQ(positionals.size(), 1u); @@ -379,7 +407,7 @@ TEST_CASE(stop_on_first_non_option) parser.add_option(bool_opt2, "bool_opt2", nullptr, 'c'); parser.add_positional_argument(positionals, "pos", "pos", Core::ArgsParser::Required::Yes); }); - EXPECT_EQ(parser_result, true); + EXPECT_EQ(parser_result.result, true); EXPECT_EQ(bool_opt1, true); EXPECT_EQ(bool_opt2, false); EXPECT_EQ(positionals.size(), 2u); |