From 95c0ec9afc89d8651e41c46c9087faae71328be7 Mon Sep 17 00:00:00 2001 From: Brian Gianforcaro Date: Fri, 26 Nov 2021 16:27:35 -0800 Subject: Tests: Fix TestLibCoreArgsParser with add_positional_argument API change Since we no longer populate a Vector the lifetime of the strings in all of these tests is now messed up, as the Vector 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. --- Tests/LibCore/TestLibCoreArgsParser.cpp | 136 +++++++++++++++++++------------- 1 file changed, 82 insertions(+), 54 deletions(-) (limited to 'Tests/LibCore/TestLibCoreArgsParser.cpp') 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 #include -static char** build_argv(Vector 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 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 arguments, Function parser_initialization = {}) +static ParserResult run_parser(Vector arguments, Function 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 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 positionals; // Bool options (given) and positional arguments (given) // Expected: all arguments fill as given bool bool_opt1 = false; bool bool_opt2 = false; - Vector 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); -- cgit v1.2.3