Mercurial > minori
comparison dep/fmt/test/gtest-extra.h @ 343:1faa72660932
*: transfer back to cmake from autotools
autotools just made lots of things more complicated than
they should have and many things broke (i.e. translations)
| author | Paper <paper@paper.us.eu.org> |
|---|---|
| date | Thu, 20 Jun 2024 05:56:06 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 342:adb79bdde329 | 343:1faa72660932 |
|---|---|
| 1 // Formatting library for C++ - custom Google Test assertions | |
| 2 // | |
| 3 // Copyright (c) 2012 - present, Victor Zverovich | |
| 4 // All rights reserved. | |
| 5 // | |
| 6 // For the license information refer to format.h. | |
| 7 | |
| 8 #ifndef FMT_GTEST_EXTRA_H_ | |
| 9 #define FMT_GTEST_EXTRA_H_ | |
| 10 | |
| 11 #include <stdlib.h> // _invalid_parameter_handler | |
| 12 | |
| 13 #include <string> | |
| 14 | |
| 15 #include "fmt/os.h" | |
| 16 #include "gmock/gmock.h" | |
| 17 | |
| 18 #define FMT_TEST_THROW_(statement, expected_exception, expected_message, fail) \ | |
| 19 GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ | |
| 20 if (::testing::AssertionResult gtest_ar = ::testing::AssertionSuccess()) { \ | |
| 21 std::string gtest_expected_message = expected_message; \ | |
| 22 bool gtest_caught_expected = false; \ | |
| 23 try { \ | |
| 24 GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ | |
| 25 } catch (expected_exception const& e) { \ | |
| 26 if (gtest_expected_message != e.what()) { \ | |
| 27 gtest_ar << #statement \ | |
| 28 " throws an exception with a different message.\n" \ | |
| 29 << "Expected: " << gtest_expected_message << "\n" \ | |
| 30 << " Actual: " << e.what(); \ | |
| 31 goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ | |
| 32 } \ | |
| 33 gtest_caught_expected = true; \ | |
| 34 } catch (...) { \ | |
| 35 gtest_ar << "Expected: " #statement \ | |
| 36 " throws an exception of type " #expected_exception \ | |
| 37 ".\n Actual: it throws a different type."; \ | |
| 38 goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ | |
| 39 } \ | |
| 40 if (!gtest_caught_expected) { \ | |
| 41 gtest_ar << "Expected: " #statement \ | |
| 42 " throws an exception of type " #expected_exception \ | |
| 43 ".\n Actual: it throws nothing."; \ | |
| 44 goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ | |
| 45 } \ | |
| 46 } else \ | |
| 47 GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__) \ | |
| 48 : fail(gtest_ar.failure_message()) | |
| 49 | |
| 50 // Tests that the statement throws the expected exception and the exception's | |
| 51 // what() method returns expected message. | |
| 52 #define EXPECT_THROW_MSG(statement, expected_exception, expected_message) \ | |
| 53 FMT_TEST_THROW_(statement, expected_exception, expected_message, \ | |
| 54 GTEST_NONFATAL_FAILURE_) | |
| 55 | |
| 56 inline std::string system_error_message(int error_code, | |
| 57 const std::string& message) { | |
| 58 auto ec = std::error_code(error_code, std::generic_category()); | |
| 59 return std::system_error(ec, message).what(); | |
| 60 } | |
| 61 | |
| 62 #define EXPECT_SYSTEM_ERROR(statement, error_code, message) \ | |
| 63 EXPECT_THROW_MSG(statement, std::system_error, \ | |
| 64 system_error_message(error_code, message)) | |
| 65 | |
| 66 #if FMT_USE_FCNTL | |
| 67 | |
| 68 // Captures file output by redirecting it to a pipe. | |
| 69 // The output it can handle is limited by the pipe capacity. | |
| 70 class output_redirect { | |
| 71 private: | |
| 72 FILE* file_; | |
| 73 fmt::file original_; // Original file passed to redirector. | |
| 74 fmt::file read_end_; // Read end of the pipe where the output is redirected. | |
| 75 | |
| 76 void flush(); | |
| 77 void restore(); | |
| 78 | |
| 79 public: | |
| 80 explicit output_redirect(FILE* file, bool flush = true); | |
| 81 ~output_redirect() noexcept; | |
| 82 | |
| 83 output_redirect(const output_redirect&) = delete; | |
| 84 void operator=(const output_redirect&) = delete; | |
| 85 | |
| 86 // Restores the original file, reads output from the pipe into a string | |
| 87 // and returns it. | |
| 88 std::string restore_and_read(); | |
| 89 }; | |
| 90 | |
| 91 # define FMT_TEST_WRITE_(statement, expected_output, file, fail) \ | |
| 92 GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ | |
| 93 if (::testing::AssertionResult gtest_ar = ::testing::AssertionSuccess()) { \ | |
| 94 std::string gtest_expected_output = expected_output; \ | |
| 95 output_redirect gtest_redir(file); \ | |
| 96 GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ | |
| 97 std::string gtest_output = gtest_redir.restore_and_read(); \ | |
| 98 if (gtest_output != gtest_expected_output) { \ | |
| 99 gtest_ar << #statement " produces different output.\n" \ | |
| 100 << "Expected: " << gtest_expected_output << "\n" \ | |
| 101 << " Actual: " << gtest_output; \ | |
| 102 goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ | |
| 103 } \ | |
| 104 } else \ | |
| 105 GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__) \ | |
| 106 : fail(gtest_ar.failure_message()) | |
| 107 | |
| 108 // Tests that the statement writes the expected output to file. | |
| 109 # define EXPECT_WRITE(file, statement, expected_output) \ | |
| 110 FMT_TEST_WRITE_(statement, expected_output, file, GTEST_NONFATAL_FAILURE_) | |
| 111 | |
| 112 # ifdef _MSC_VER | |
| 113 | |
| 114 // Suppresses Windows assertions on invalid file descriptors, making | |
| 115 // POSIX functions return proper error codes instead of crashing on Windows. | |
| 116 class suppress_assert { | |
| 117 private: | |
| 118 _invalid_parameter_handler original_handler_; | |
| 119 int original_report_mode_; | |
| 120 | |
| 121 static void handle_invalid_parameter(const wchar_t*, const wchar_t*, | |
| 122 const wchar_t*, unsigned, uintptr_t) {} | |
| 123 | |
| 124 public: | |
| 125 suppress_assert() | |
| 126 : original_handler_( | |
| 127 _set_invalid_parameter_handler(handle_invalid_parameter)), | |
| 128 original_report_mode_(_CrtSetReportMode(_CRT_ASSERT, 0)) {} | |
| 129 ~suppress_assert() { | |
| 130 _set_invalid_parameter_handler(original_handler_); | |
| 131 _CrtSetReportMode(_CRT_ASSERT, original_report_mode_); | |
| 132 (void)original_report_mode_; | |
| 133 } | |
| 134 }; | |
| 135 | |
| 136 # define SUPPRESS_ASSERT(statement) \ | |
| 137 { \ | |
| 138 suppress_assert sa; \ | |
| 139 statement; \ | |
| 140 } | |
| 141 # else | |
| 142 # define SUPPRESS_ASSERT(statement) statement | |
| 143 # endif // _MSC_VER | |
| 144 | |
| 145 # define EXPECT_SYSTEM_ERROR_NOASSERT(statement, error_code, message) \ | |
| 146 EXPECT_SYSTEM_ERROR(SUPPRESS_ASSERT(statement), error_code, message) | |
| 147 | |
| 148 // Attempts to read count characters from a file. | |
| 149 std::string read(fmt::file& f, size_t count); | |
| 150 | |
| 151 # define EXPECT_READ(file, expected_content) \ | |
| 152 EXPECT_EQ(expected_content, \ | |
| 153 read(file, fmt::string_view(expected_content).size())) | |
| 154 | |
| 155 #else | |
| 156 # define EXPECT_WRITE(file, statement, expected_output) \ | |
| 157 do { \ | |
| 158 (void)(file); \ | |
| 159 (void)(statement); \ | |
| 160 (void)(expected_output); \ | |
| 161 SUCCEED(); \ | |
| 162 } while (false) | |
| 163 #endif // FMT_USE_FCNTL | |
| 164 | |
| 165 #endif // FMT_GTEST_EXTRA_H_ |
