From 3295fa5f8bf48c3119f87cc9e2cd44c2a8fbbb12 Mon Sep 17 00:00:00 2001 From: Enrico Seiler Date: Tue, 27 Feb 2024 16:01:09 +0100 Subject: [PATCH] [TEST] Add EXPECT_THROW_MSG --- test/include/sharg/test/expect_throw_msg.hpp | 54 +++++++++++++++++++ test/unit/parser/enumeration_names_test.cpp | 30 +++-------- test/unit/parser/format_parse_test.cpp | 21 ++------ test/unit/parser/parser_design_error_test.cpp | 46 +++++++--------- 4 files changed, 87 insertions(+), 64 deletions(-) create mode 100644 test/include/sharg/test/expect_throw_msg.hpp diff --git a/test/include/sharg/test/expect_throw_msg.hpp b/test/include/sharg/test/expect_throw_msg.hpp new file mode 100644 index 00000000..e20002a7 --- /dev/null +++ b/test/include/sharg/test/expect_throw_msg.hpp @@ -0,0 +1,54 @@ +// SPDX-FileCopyrightText: 2006-2024, Knut Reinert & Freie Universität Berlin +// SPDX-FileCopyrightText: 2016-2024, Knut Reinert & MPI für molekulare Genetik +// SPDX-License-Identifier: BSD-3-Clause + +/*!\file + * \brief Provides EXPECT_THROW_MSG. + * \author Enrico Seiler + */ + +#pragma once + +#include + +#ifdef EXPECT_THROW_MSG +# warning "EXPECT_THROW_MSG is already defined." +#else +# define EXPECT_THROW_MSG(statement, expected_exception, expected_message) \ + try \ + { \ + statement; \ + std::string const message = "Expected: " #statement " throws an exception of type " #expected_exception \ + ".\n Actual: it throws nothing."; \ + GTEST_NONFATAL_FAILURE_(message.data()); \ + } \ + catch (expected_exception const & exception) \ + { \ + if (auto result = ::testing::internal::EqHelper::Compare("Expected", \ + "Actual", \ + std::string_view{expected_message}, \ + std::string_view{exception.what()}); \ + !result) \ + { \ + std::string message = #statement " throws the correct exception, but the description is incorrect.\n"; \ + message += result.failure_message(); \ + GTEST_NONFATAL_FAILURE_(message.data()); \ + } \ + } \ + catch (std::exception const & exception) \ + { \ + std::string message = "Expected: " #statement " throws an exception of type " #expected_exception ".\n "; \ + message += "Actual: it throws "; \ + message += ::testing::internal::GetTypeName(typeid(exception)); \ + message += " with description \""; \ + message += exception.what(); \ + message += "\"."; \ + GTEST_NONFATAL_FAILURE_(message.data()); \ + } \ + catch (...) \ + { \ + std::string message = "Expected: " #statement " throws an exception of type " #expected_exception ".\n "; \ + message += "Actual: it throws an unknown exception."; \ + GTEST_NONFATAL_FAILURE_(message.data()); \ + } +#endif diff --git a/test/unit/parser/enumeration_names_test.cpp b/test/unit/parser/enumeration_names_test.cpp index a3b1fcd9..e6300c36 100644 --- a/test/unit/parser/enumeration_names_test.cpp +++ b/test/unit/parser/enumeration_names_test.cpp @@ -7,6 +7,7 @@ #include #include +#include #include namespace foo @@ -112,34 +113,19 @@ TEST_F(enumeration_names_test, enum_error_message) foo::bar value{}; Other::bar value2{}; - auto parser = get_parser(); - - auto check_error = [&parser](std::string_view const expected) - { - try - { - parser.parse(); - FAIL(); - } - catch (sharg::user_input_error const & exception) - { - EXPECT_EQ(expected, exception.what()); - } - catch (...) - { - FAIL(); - } - }; - // foo::bar does not contain duplicate values - parser = get_parser("-e", "nine"); + auto parser = get_parser("-e", "nine"); parser.add_option(value, sharg::config{.short_id = 'e'}); - check_error("You have chosen an invalid input value: nine. Please use one of: [one, two, three]"); + EXPECT_THROW_MSG(parser.parse(), + sharg::user_input_error, + "You have chosen an invalid input value: nine. Please use one of: [one, two, three]"); // Other::bar does contain duplicate values parser = get_parser("-e", "nine"); parser.add_option(value2, sharg::config{.short_id = 'e'}); - check_error("You have chosen an invalid input value: nine. Please use one of: [1, one, 2, two]"); + EXPECT_THROW_MSG(parser.parse(), + sharg::user_input_error, + "You have chosen an invalid input value: nine. Please use one of: [1, one, 2, two]"); } // https://github.com/seqan/seqan3/pull/2381 diff --git a/test/unit/parser/format_parse_test.cpp b/test/unit/parser/format_parse_test.cpp index c89e5d9e..fbf39670 100644 --- a/test/unit/parser/format_parse_test.cpp +++ b/test/unit/parser/format_parse_test.cpp @@ -7,6 +7,7 @@ #include #include +#include #include class format_parse_test : public sharg::test::test_fixture @@ -770,22 +771,10 @@ TEST_F(format_parse_test, error_message_parsing) auto parser = get_parser("--value", "-30"); parser.add_option(option_value, sharg::config{.long_id = "value"}); - - try - { - parser.parse(); - FAIL(); - } - catch (sharg::user_input_error const & exception) - { - std::string_view const expected_message{"Value parse failed for --value: Argument -30 could not be parsed as " - "type unsigned 64 bit integer."}; - EXPECT_EQ(expected_message, exception.what()); - } - catch (...) - { - FAIL(); - } + EXPECT_THROW_MSG(parser.parse(), + sharg::user_input_error, + "Value parse failed for --value: Argument -30 could " + "not be parsed as type unsigned 64 bit integer."); } // https://github.com/seqan/seqan3/pull/2381 diff --git a/test/unit/parser/parser_design_error_test.cpp b/test/unit/parser/parser_design_error_test.cpp index 1c488fe7..d93e330e 100644 --- a/test/unit/parser/parser_design_error_test.cpp +++ b/test/unit/parser/parser_design_error_test.cpp @@ -5,6 +5,7 @@ #include #include +#include #include class design_error_test : public sharg::test::test_fixture @@ -295,30 +296,23 @@ TEST_F(design_error_test, not_allowed_after_parse) parser.add_option(value, sharg::config{.short_id = 'i'}); EXPECT_NO_THROW(parser.parse()); - auto check_error = [](auto call_fn, std::string const function_name) - { - try - { - call_fn(); - FAIL(); - } - catch (sharg::design_error const & exception) - { - EXPECT_EQ(function_name + " may only be used before calling parse().", exception.what()); - } - catch (...) - { - FAIL(); - } - }; - - // clang-format off - check_error([&parser, &value]() { parser.add_option(value, sharg::config{.short_id = 'i'}); }, "add_option"); - check_error([&parser, &flag]() { parser.add_flag(flag, sharg::config{.short_id = 'i'}); }, "add_flag"); - check_error([&parser, &value]() { parser.add_positional_option(value, sharg::config{}); }, "add_positional_option"); - check_error([&parser]() { parser.add_section(""); }, "add_section"); - check_error([&parser]() { parser.add_subsection(""); }, "add_subsection"); - check_error([&parser]() { parser.add_line(""); }, "add_line"); - check_error([&parser]() { parser.add_list_item("", ""); }, "add_list_item"); - // clang-format on + EXPECT_THROW_MSG(parser.add_option(value, sharg::config{.short_id = 'i'}), + sharg::design_error, + "add_option may only be used before calling parse()."); + EXPECT_THROW_MSG(parser.add_flag(flag, sharg::config{.short_id = 'i'}), + sharg::design_error, + "add_flag may only be used before calling parse()."); + EXPECT_THROW_MSG(parser.add_positional_option(value, sharg::config{}), + sharg::design_error, + "add_positional_option may only be used before calling parse()."); + EXPECT_THROW_MSG(parser.add_section(""), + sharg::design_error, + "add_section may only be used before calling parse()."); + EXPECT_THROW_MSG(parser.add_subsection(""), + sharg::design_error, + "add_subsection may only be used before calling parse()."); + EXPECT_THROW_MSG(parser.add_line(""), sharg::design_error, "add_line may only be used before calling parse()."); + EXPECT_THROW_MSG(parser.add_list_item("", ""), + sharg::design_error, + "add_list_item may only be used before calling parse()."); }