https://mooseframework.inl.gov
Loading...
Searching...
No Matches
MooseUnitUtils.h
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#pragma once
11
12#include "gtest/gtest.h"
13
14#include <filesystem>
15#include <string>
16
17#include "libmesh/utility.h"
18
19#include "MooseUtils.h"
20#include "Moose.h"
21
23{
31template <class ExceptionType = std::exception, class Action = bool>
32void
33assertThrows(const Action & action,
34 const std::optional<std::string> & contains = {},
35 const bool set_throw_on_error = false)
36{
37 static_assert(std::is_base_of_v<std::exception, ExceptionType>, "Not an exception");
38
39 std::unique_ptr<Moose::ScopedThrowOnError> scoped_throw_on_error;
40 if (set_throw_on_error)
41 scoped_throw_on_error = std::make_unique<Moose::ScopedThrowOnError>();
42
43 try
44 {
45 action();
46 FAIL() << "Expected " << MooseUtils::prettyCppType<ExceptionType>() << " not thrown";
47 }
48 catch (std::exception const & e)
49 {
50 if constexpr (!std::is_same_v<std::exception, ExceptionType>)
51 if (!dynamic_cast<const ExceptionType *>(&e))
52 FAIL() << "Threw " << demangle(typeid(e).name()) << " instead of "
53 << MooseUtils::prettyCppType<ExceptionType>() << " with message '" << e.what()
54 << "'";
55
56 if (contains)
57 {
58 ASSERT_TRUE(std::string(e.what()).find(*contains) != std::string::npos)
59 << "Exception \"" << e.what() << "\" does not contain \"" << *contains << "\"";
60 }
61 }
62}
63
67template <typename ExceptionType, bool exact, bool assert, bool set_throw_on_error, typename Func>
68void
69throwsWithMessage(Func && fn, const std::string_view message, const char * file, int line)
70{
71 static_assert(std::is_base_of_v<std::exception, ExceptionType>, "Not an exception");
72
73 std::ostringstream error;
74
75 try
76 {
77 std::unique_ptr<Moose::ScopedThrowOnError> scoped_throw_on_error;
78 if constexpr (set_throw_on_error)
79 scoped_throw_on_error = std::make_unique<Moose::ScopedThrowOnError>();
80
81 fn();
82
83 error << "Expected exception of type " << libMesh::demangle(typeid(ExceptionType).name())
84 << " but no exception was thrown.";
85 }
86 catch (const ExceptionType & ex)
87 {
88 // Exact match
89 if constexpr (exact)
90 {
91 if (std::string(ex.what()) == message)
92 return;
93 }
94 // Partial match
95 else
96 {
97 if (std::string(ex.what()).find(message) != std::string::npos)
98 return;
99 }
100
101 error << "Expected" << (exact ? "" : " partial") << " exception message: \"" << message
102 << "\"\n Actual exception message: \"" << ex.what() << "\"";
103 }
104 catch (const std::exception & ex)
105 {
106 error << "Expected exception of type " << libMesh::demangle(typeid(ExceptionType).name())
107 << " but exception of type " << libMesh::demangle(typeid(ex).name()) << " was thrown.";
108 }
109
110 ::testing::internal::AssertHelper(
111 ::testing::TestPartResult::kNonFatalFailure, file, line, error.str().c_str()) =
112 ::testing::Message();
113}
114
119{
120public:
121 TempFile();
122 ~TempFile();
123
127 const std::filesystem::path & path() const { return _path; }
128
129private:
130 static std::filesystem::path generatePath();
131
132 const std::filesystem::path _path;
133};
134
135} // namespace Moose::UnitUtils
136
138#define EXPECT_THROW_MSG(stmt, exc_type, expected_msg) \
139 ::Moose::UnitUtils::throwsWithMessage<exc_type, true, false, false>( \
140 [&]() { stmt; }, expected_msg, __FILE__, __LINE__)
141
143#define ASSERT_THROW_MSG(stmt, exc_type, expected_msg) \
144 ::Moose::UnitUtils::throwsWithMessage<exc_type, true, true, false>( \
145 [&]() { stmt; }, expected_msg, __FILE__, __LINE__)
146
148#define EXPECT_THROW_MSG_CONTAINS(stmt, exc_type, expected_substr) \
149 ::Moose::UnitUtils::throwsWithMessage<exc_type, false, false, false>( \
150 [&]() { stmt; }, expected_substr, __FILE__, __LINE__)
151
153#define ASSERT_THROW_MSG_CONTAINS(stmt, exc_type, expected_substr) \
154 ::Moose::UnitUtils::throwsWithMessage<exc_type, false, true, false>( \
155 [&]() { stmt; }, expected_substr, __FILE__, __LINE__)
156
158#define EXPECT_MOOSEERROR_MSG(stmt, expected_msg) \
159 ::Moose::UnitUtils::throwsWithMessage<MooseRuntimeError, true, false, true>( \
160 [&]() { stmt; }, expected_msg, __FILE__, __LINE__)
161
163#define ASSERT_MOOSEERROR_MSG(stmt, expected_msg) \
164 ::Moose::UnitUtils::throwsWithMessage<MooseRuntimeError, true, true, true>( \
165 [&]() { stmt; }, expected_msg, __FILE__, __LINE__)
166
168#define EXPECT_MOOSEERROR_MSG_CONTAINS(stmt, expected_substr) \
169 ::Moose::UnitUtils::throwsWithMessage<MooseRuntimeError, false, false, true>( \
170 [&]() { stmt; }, expected_substr, __FILE__, __LINE__)
171
173#define ASSERT_MOOSEERROR_MSG_CONTAINS(stmt, expected_substr) \
174 ::Moose::UnitUtils::throwsWithMessage<MooseRuntimeError, false, true, true>( \
175 [&]() { stmt; }, expected_substr, __FILE__, __LINE__)
Base class for actions.
Definition Action.h:38
Create a temporary file and delete it upon destruction.
const std::filesystem::path _path
const std::filesystem::path & path() const
static std::filesystem::path generatePath()
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)