4#define DOCTEST_CONFIG_IMPLEMENT
14#include <doctest/doctest.h>
18#include <spdlog/spdlog.h>
31#define DOCTEST_LOCK_MUTEX(name) \
32 std::lock_guard<std::mutex> DOCTEST_ANONYMOUS(DOCTEST_ANON_LOCK_)(name);
43 if (opt.minimal && p.numTestCasesFailed == 0) {
49 <<
"==============================================================================="
50 << Color::None <<
"\n";
54 int(std::ceil(log10(
static_cast<double>(std::max(p.numTestCasesPassingFilters,
55 static_cast<unsigned>(p.numAsserts))) +
58 int(std::ceil(log10(
static_cast<double>(std::max(
59 p.numTestCasesPassingFilters - p.numTestCasesFailed,
60 static_cast<unsigned>(p.numAsserts - p.numAssertsFailed))) +
63 std::ceil(log10(
static_cast<double>(std::max(
64 p.numTestCasesFailed,
static_cast<unsigned>(p.numAssertsFailed))) +
66 const bool anythingFailed = p.numTestCasesFailed > 0 || p.numAssertsFailed > 0;
67 ss <<
"test cases: " << std::setw(totwidth) << p.numTestCasesPassingFilters <<
" | "
68 << ((p.numTestCasesPassingFilters == 0 || anythingFailed) ? Color::None : Color::Green)
69 << std::setw(passwidth) << p.numTestCasesPassingFilters - p.numTestCasesFailed
70 <<
" passed" << Color::None <<
" | "
71 << (p.numTestCasesFailed > 0 ? Color::Red : Color::None) << std::setw(failwidth)
72 << p.numTestCasesFailed <<
" failed" << Color::None <<
" |";
73 if (!opt.no_skipped_summary) {
74 const unsigned int numSkipped = p.numTestCases - p.numTestCasesPassingFilters;
75 ss <<
" " << (numSkipped == 0 ? Color::None : Color::Yellow) << numSkipped <<
" skipped"
79 ss <<
"assertions: " << std::setw(totwidth) << p.numAsserts <<
" | "
80 << ((p.numAsserts == 0 || anythingFailed) ? Color::None : Color::Green)
81 << std::setw(passwidth) << (p.numAsserts - p.numAssertsFailed) <<
" passed"
82 << Color::None <<
" | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None)
83 << std::setw(failwidth) << p.numAssertsFailed <<
" failed" << Color::None <<
" |\n";
84 ss <<
"Status: " << (p.numTestCasesFailed > 0 ? Color::Red : Color::Green)
85 << ((p.numTestCasesFailed > 0) ?
"FAILURE!" :
"SUCCESS!") << Color::None << std::endl;
87 if (p.numTestCasesFailed > 0) {
88 for (std::string line; std::getline(ss, line);) {
92 for (std::string line; std::getline(ss, line);) {
99 if (tc->m_no_output) {
104 (st.failure_flags != 0 &&
105 st.failure_flags !=
static_cast<int>(TestCaseFailureReason::AssertFailure))) {
110 std::stringstream ss;
111 ss << std::setprecision(6) << std::fixed << st.seconds <<
" s: " << tc->m_name;
112 SPDLOG_INFO(ss.str());
115 if ((st.failure_flags & TestCaseFailureReason::Timeout) != 0) {
116 std::stringstream ss;
117 ss << Color::Red <<
"Test case exceeded time limit of " << std::setprecision(6)
118 << std::fixed << tc->m_timeout <<
"!" << Color::None;
119 SPDLOG_ERROR(ss.str());
122 if ((st.failure_flags & TestCaseFailureReason::ShouldHaveFailedButDidnt) != 0) {
123 std::stringstream ss;
124 ss << Color::Red <<
"Should have failed but didn't! Marking it as failed!"
126 SPDLOG_ERROR(ss.str());
127 }
else if ((st.failure_flags & TestCaseFailureReason::ShouldHaveFailedAndDid) != 0) {
128 std::stringstream ss;
129 ss << Color::Yellow <<
"Failed as expected so marking it as not failed" << Color::None;
130 SPDLOG_WARN(ss.str());
131 }
else if ((st.failure_flags & TestCaseFailureReason::CouldHaveFailedAndDid) != 0) {
132 std::stringstream ss;
133 ss << Color::Yellow <<
"Allowed to fail so marking it as not failed" << Color::None;
134 SPDLOG_WARN(ss.str());
135 }
else if ((st.failure_flags & TestCaseFailureReason::DidntFailExactlyNumTimes) != 0) {
136 std::stringstream ss;
137 ss << Color::Red <<
"Didn't fail exactly " << tc->m_expected_failures
138 <<
" times so marking it as failed!" << Color::None;
139 SPDLOG_ERROR(ss.str());
140 }
else if ((st.failure_flags & TestCaseFailureReason::FailedExactlyNumTimes) != 0) {
141 std::stringstream ss;
142 ss << Color::Yellow <<
"Failed exactly " << tc->m_expected_failures
143 <<
" times as expected so marking it as not failed!" << Color::None;
144 SPDLOG_WARN(ss.str());
147 if ((st.failure_flags & TestCaseFailureReason::TooManyFailedAsserts) != 0) {
148 std::stringstream ss;
149 ss << Color::Red <<
"Aborting - too many failed asserts!" << Color::None;
150 SPDLOG_ERROR(ss.str());
155 if (tc->m_no_output) {
163 std::stringstream ss;
164 ss <<
"[" << skipPathFromFilename(tc->m_file.c_str()) << (opt.gnu_file_line ?
":" :
"(")
165 << (opt.no_line_numbers ? 0 : tc->m_line) << (opt.gnu_file_line ?
"" :
")") <<
"] ";
166 std::string loc = ss.str();
168 ss << Color::Red << (e.is_crash ?
"test case CRASHED: " :
"test case THREW exception: ")
169 << Color::None << e.error_string;
170 for (std::string line; std::getline(ss, line);) {
171 SPDLOG_ERROR(loc + line);
176 if ((!rb.m_failed && !opt.success) || tc->m_no_output) {
184 std::stringstream ss;
185 ss <<
"[" << skipPathFromFilename(rb.m_file) << (opt.gnu_file_line ?
":" :
"(")
186 << (opt.no_line_numbers ? 0 : rb.m_line) << (opt.gnu_file_line ?
"" :
")") <<
"] ";
187 std::string loc = ss.str();
189 fulltext_log_assert_to_stream(ss, rb);
191 for (std::string line; std::getline(ss, line);) {
192 SPDLOG_ERROR(loc + line);
195 for (std::string line; std::getline(ss, line);) {
196 SPDLOG_INFO(loc + line);
204 if (tc->m_no_output) {
212 std::stringstream ss;
213 ss <<
"[" << skipPathFromFilename(mb.m_file) << (opt.gnu_file_line ?
":" :
"(")
214 << (opt.no_line_numbers ? 0 : mb.m_line) << (opt.gnu_file_line ?
"" :
")") <<
"] ";
215 std::string loc = ss.str();
217 ss << getSuccessOrFailColor(
false, mb.m_severity)
218 << getSuccessOrFailString((mb.m_severity & assertType::is_warn) != 0, mb.m_severity,
220 <<
": " << Color::None << mb.m_string;
221 for (std::string line; std::getline(ss, line);) {
222 SPDLOG_INFO(loc + line);
237#elif defined(__APPLE__)
239#elif defined(__linux__)
250 doctest::Context ctx;
251 ctx.setOption(
"abort-after", 5);
252 ctx.setOption(
"no-run", 0);
253 ctx.setOption(
"duration",
true);
254 ctx.setOption(
"no-path-filenames",
true);
255 ctx.applyCommandLine(argc, argv);
256 ctx.setOption(
"no-colors",
true);
257 ctx.setOption(
"no-breaks",
true);
258 ctx.setOption(
"reporters",
"logging");
259 ctx.setOption(
"no-intro",
true);
264 SPDLOG_INFO(
"Operating system: {}",
OS_NAME);
268 int exitcode = ctx.run();
271 SPDLOG_INFO(
"The log was stored to {}", logdir.string());
274 if (download_missing) {
275 httplib::Client client(
"https://www.github.com");
276 auto res = client.Head(
"/");
279 "Test failed. Please check your internet connection. An internet "
280 "connection is required to download databases of atomic states and matrix "
281 "elements if they are not available locally. The log was stored to {}",
285 "Tests failed. Consider creating an issue on "
286 "https://github.com/pairinteraction/pairinteraction/issues, attaching the "
287 "log. The log was stored to {}",
292 "Tests failed. Consider creating an issue on "
293 "https://github.com/pairinteraction/pairinteraction/issues, attaching the "
294 "log. If the tests failed because of unavailable states or "
295 "matrix elements, consider downloading missing databases by calling "
296 "the test function with 'download_missing = true'. The log was stored to {}",
static Database & get_global_instance()
REGISTER_REPORTER("logging", 1, doctest::LoggingReporter)
std::filesystem::path get_cache_directory()
constexpr int VERSION_MINOR
constexpr int VERSION_PATCH
constexpr int VERSION_MAJOR
int run_unit_tests(int argc=0, char **argv={}, bool download_missing=false, bool use_cache=true, std::filesystem::path database_dir="")
#define DOCTEST_LOCK_MUTEX(name)
constexpr std::string_view OS_NAME
LoggingReporter(const ContextOptions &co)
void log_message(const MessageData &mb) override
void test_case_end(const CurrentTestCaseStats &st) override
void log_assert(const AssertData &rb) override
void test_case_exception(const TestCaseException &e) override
void test_run_end(const TestRunStats &p) override