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_ |