Skip to content

Commit

Permalink
[TEST] Add EXPECT_THROW_MSG
Browse files Browse the repository at this point in the history
  • Loading branch information
eseiler committed Feb 27, 2024
1 parent 64399ce commit f056c7e
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 64 deletions.
54 changes: 54 additions & 0 deletions test/include/sharg/test/expect_throw_msg.hpp
Original file line number Diff line number Diff line change
@@ -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 <enrico.seiler AT fu-berlin.de>
*/

#pragma once

#include <gtest/gtest.h>

#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_message, \
"exception.what()", \
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
30 changes: 8 additions & 22 deletions test/unit/parser/enumeration_names_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <ranges>

#include <sharg/parser.hpp>
#include <sharg/test/expect_throw_msg.hpp>
#include <sharg/test/test_fixture.hpp>

namespace foo
Expand Down Expand Up @@ -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
Expand Down
21 changes: 5 additions & 16 deletions test/unit/parser/format_parse_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <ranges>

#include <sharg/parser.hpp>
#include <sharg/test/expect_throw_msg.hpp>
#include <sharg/test/test_fixture.hpp>

class format_parse_test : public sharg::test::test_fixture
Expand Down Expand Up @@ -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
Expand Down
46 changes: 20 additions & 26 deletions test/unit/parser/parser_design_error_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <gtest/gtest.h>

#include <sharg/parser.hpp>
#include <sharg/test/expect_throw_msg.hpp>
#include <sharg/test/test_fixture.hpp>

class design_error_test : public sharg::test::test_fixture
Expand Down Expand Up @@ -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().");
}

0 comments on commit f056c7e

Please sign in to comment.