12#include "gtest/gtest.h"
18#include "libmesh/utility.h"
32template <
class ExceptionType = std::exception,
class Action =
bool>
35 const std::optional<std::string> & contains = {},
36 const bool set_throw_on_error =
false)
38 static_assert(std::is_base_of_v<std::exception, ExceptionType>,
"Not an exception");
40 std::unique_ptr<Moose::ScopedThrowOnError> scoped_throw_on_error;
41 if (set_throw_on_error)
42 scoped_throw_on_error = std::make_unique<Moose::ScopedThrowOnError>();
47 FAIL() <<
"Expected " << MooseUtils::prettyCppType<ExceptionType>() <<
" not thrown";
49 catch (std::exception
const & e)
51 if constexpr (!std::is_same_v<std::exception, ExceptionType>)
52 if (!
dynamic_cast<const ExceptionType *
>(&e))
53 FAIL() <<
"Threw " << demangle(
typeid(e).name()) <<
" instead of "
54 << MooseUtils::prettyCppType<ExceptionType>() <<
" with message '" << e.what()
59 ASSERT_TRUE(std::string(e.what()).find(*contains) != std::string::npos)
60 <<
"Exception \"" << e.what() <<
"\" does not contain \"" << *contains <<
"\"";
68template <
typename ExceptionType,
bool exact,
bool assert,
bool set_throw_on_error,
typename Func>
72 static_assert(std::is_base_of_v<std::exception, ExceptionType>,
"Not an exception");
74 std::ostringstream error;
78 std::unique_ptr<Moose::ScopedThrowOnError> scoped_throw_on_error;
79 if constexpr (set_throw_on_error)
80 scoped_throw_on_error = std::make_unique<Moose::ScopedThrowOnError>();
84 error <<
"Expected exception of type " <<
libMesh::demangle(
typeid(ExceptionType).name())
85 <<
" but no exception was thrown.";
87 catch (
const ExceptionType & ex)
92 if (std::string(ex.what()) == message)
98 if (std::string(ex.what()).find(message) != std::string::npos)
102 error <<
"Expected" << (exact ?
"" :
" partial") <<
" exception message: \"" << message
103 <<
"\"\n Actual exception message: \"" << ex.what() <<
"\"";
105 catch (
const std::exception & ex)
107 error <<
"Expected exception of type " <<
libMesh::demangle(
typeid(ExceptionType).name())
108 <<
" but exception of type " <<
libMesh::demangle(
typeid(ex).name()) <<
" was thrown.";
111 ::testing::internal::AssertHelper(
112 ::testing::TestPartResult::kNonFatalFailure, file, line, error.str().c_str()) =
113 ::testing::Message();
128 const std::filesystem::path &
path()
const {
return _path; }
152 const std::filesystem::path &
path()
const {
return _path; }
166#define EXPECT_THROW_MSG(stmt, exc_type, expected_msg) \
167 ::Moose::UnitUtils::throwsWithMessage<exc_type, true, false, false>( \
168 [&]() { stmt; }, expected_msg, __FILE__, __LINE__)
171#define ASSERT_THROW_MSG(stmt, exc_type, expected_msg) \
172 ::Moose::UnitUtils::throwsWithMessage<exc_type, true, true, false>( \
173 [&]() { stmt; }, expected_msg, __FILE__, __LINE__)
176#define EXPECT_THROW_MSG_CONTAINS(stmt, exc_type, expected_substr) \
177 ::Moose::UnitUtils::throwsWithMessage<exc_type, false, false, false>( \
178 [&]() { stmt; }, expected_substr, __FILE__, __LINE__)
181#define ASSERT_THROW_MSG_CONTAINS(stmt, exc_type, expected_substr) \
182 ::Moose::UnitUtils::throwsWithMessage<exc_type, false, true, false>( \
183 [&]() { stmt; }, expected_substr, __FILE__, __LINE__)
186#define EXPECT_MOOSEERROR_MSG(stmt, expected_msg) \
187 ::Moose::UnitUtils::throwsWithMessage<MooseRuntimeError, true, false, true>( \
188 [&]() { stmt; }, expected_msg, __FILE__, __LINE__)
191#define ASSERT_MOOSEERROR_MSG(stmt, expected_msg) \
192 ::Moose::UnitUtils::throwsWithMessage<MooseRuntimeError, true, true, true>( \
193 [&]() { stmt; }, expected_msg, __FILE__, __LINE__)
196#define EXPECT_MOOSEERROR_MSG_CONTAINS(stmt, expected_substr) \
197 ::Moose::UnitUtils::throwsWithMessage<MooseRuntimeError, false, false, true>( \
198 [&]() { stmt; }, expected_substr, __FILE__, __LINE__)
201#define ASSERT_MOOSEERROR_MSG_CONTAINS(stmt, expected_substr) \
202 ::Moose::UnitUtils::throwsWithMessage<MooseRuntimeError, false, true, true>( \
203 [&]() { stmt; }, expected_substr, __FILE__, __LINE__)
Run a unit test from a unique temporary working directory.
const std::filesystem::path _original_path
Working directory to restore upon destruction.
static std::filesystem::path createPath()
ScopedTestDirectory & operator=(const ScopedTestDirectory &)=delete
const std::filesystem::path _path
Unique temporary working directory.
const std::filesystem::path & path() const
ScopedTestDirectory(const ScopedTestDirectory &)=delete
Create a temporary file and delete it upon destruction.
const std::filesystem::path _path
const std::filesystem::path & path() const
void assertThrows(const Action &action, const std::optional< std::string > &contains={}, const bool set_throw_on_error=false)
A helper for asserting that calling something throws an exception.
void throwsWithMessage(Func &&fn, const std::string_view message, const char *file, int line)
Helper for the [EXPECT,ASSERT]_[MOOSEERROR,THROW]_[MSG,MSG_CONTAINS] macros.
std::string demangle(const char *name)