Mercurial > minori
comparison dep/fmt/test/gtest-extra-test.cc @ 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++ - tests of 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 #include "gtest-extra.h" | |
9 | |
10 #include <gtest/gtest-spi.h> | |
11 | |
12 #include <cstring> | |
13 #include <memory> | |
14 #include <stdexcept> | |
15 | |
16 #include "fmt/os.h" | |
17 #include "util.h" | |
18 | |
19 // Tests that assertion macros evaluate their arguments exactly once. | |
20 namespace { | |
21 class single_evaluation_test : public ::testing::Test { | |
22 protected: | |
23 single_evaluation_test() { | |
24 p_ = s_; | |
25 a_ = 0; | |
26 b_ = 0; | |
27 } | |
28 | |
29 static const char* const s_; | |
30 static const char* p_; | |
31 | |
32 static int a_; | |
33 static int b_; | |
34 }; | |
35 } // namespace | |
36 | |
37 const char* const single_evaluation_test::s_ = "01234"; | |
38 const char* single_evaluation_test::p_; | |
39 int single_evaluation_test::a_; | |
40 int single_evaluation_test::b_; | |
41 | |
42 void do_nothing() {} | |
43 | |
44 FMT_NORETURN void throw_exception() { throw std::runtime_error("test"); } | |
45 | |
46 FMT_NORETURN void throw_system_error() { | |
47 throw fmt::system_error(EDOM, "test"); | |
48 } | |
49 | |
50 // Tests that when EXPECT_THROW_MSG fails, it evaluates its message argument | |
51 // exactly once. | |
52 TEST_F(single_evaluation_test, failed_expect_throw_msg) { | |
53 EXPECT_NONFATAL_FAILURE( | |
54 EXPECT_THROW_MSG(throw_exception(), std::exception, p_++), "01234"); | |
55 EXPECT_EQ(s_ + 1, p_); | |
56 } | |
57 | |
58 // Tests that when EXPECT_SYSTEM_ERROR fails, it evaluates its message argument | |
59 // exactly once. | |
60 TEST_F(single_evaluation_test, failed_expect_system_error) { | |
61 EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, p_++), | |
62 "01234"); | |
63 EXPECT_EQ(s_ + 1, p_); | |
64 } | |
65 | |
66 // Tests that assertion arguments are evaluated exactly once. | |
67 TEST_F(single_evaluation_test, exception_tests) { | |
68 // successful EXPECT_THROW_MSG | |
69 EXPECT_THROW_MSG( | |
70 { // NOLINT | |
71 a_++; | |
72 throw_exception(); | |
73 }, | |
74 std::exception, (b_++, "test")); | |
75 EXPECT_EQ(1, a_); | |
76 EXPECT_EQ(1, b_); | |
77 | |
78 // failed EXPECT_THROW_MSG, throws different type | |
79 EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG( | |
80 { // NOLINT | |
81 a_++; | |
82 throw_exception(); | |
83 }, | |
84 std::logic_error, (b_++, "test")), | |
85 "throws a different type"); | |
86 EXPECT_EQ(2, a_); | |
87 EXPECT_EQ(2, b_); | |
88 | |
89 // failed EXPECT_THROW_MSG, throws an exception with different message | |
90 EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG( | |
91 { // NOLINT | |
92 a_++; | |
93 throw_exception(); | |
94 }, | |
95 std::exception, (b_++, "other")), | |
96 "throws an exception with a different message"); | |
97 EXPECT_EQ(3, a_); | |
98 EXPECT_EQ(3, b_); | |
99 | |
100 // failed EXPECT_THROW_MSG, throws nothing | |
101 EXPECT_NONFATAL_FAILURE( | |
102 EXPECT_THROW_MSG(a_++, std::exception, (b_++, "test")), "throws nothing"); | |
103 EXPECT_EQ(4, a_); | |
104 EXPECT_EQ(4, b_); | |
105 } | |
106 | |
107 TEST_F(single_evaluation_test, system_error_tests) { | |
108 // successful EXPECT_SYSTEM_ERROR | |
109 EXPECT_SYSTEM_ERROR( | |
110 { // NOLINT | |
111 a_++; | |
112 throw_system_error(); | |
113 }, | |
114 EDOM, (b_++, "test")); | |
115 EXPECT_EQ(1, a_); | |
116 EXPECT_EQ(1, b_); | |
117 | |
118 // failed EXPECT_SYSTEM_ERROR, throws different type | |
119 EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR( | |
120 { // NOLINT | |
121 a_++; | |
122 throw_exception(); | |
123 }, | |
124 EDOM, (b_++, "test")), | |
125 "throws a different type"); | |
126 EXPECT_EQ(2, a_); | |
127 EXPECT_EQ(2, b_); | |
128 | |
129 // failed EXPECT_SYSTEM_ERROR, throws an exception with different message | |
130 EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR( | |
131 { // NOLINT | |
132 a_++; | |
133 throw_system_error(); | |
134 }, | |
135 EDOM, (b_++, "other")), | |
136 "throws an exception with a different message"); | |
137 EXPECT_EQ(3, a_); | |
138 EXPECT_EQ(3, b_); | |
139 | |
140 // failed EXPECT_SYSTEM_ERROR, throws nothing | |
141 EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(a_++, EDOM, (b_++, "test")), | |
142 "throws nothing"); | |
143 EXPECT_EQ(4, a_); | |
144 EXPECT_EQ(4, b_); | |
145 } | |
146 | |
147 #if FMT_USE_FCNTL | |
148 // Tests that when EXPECT_WRITE fails, it evaluates its message argument | |
149 // exactly once. | |
150 TEST_F(single_evaluation_test, failed_expect_write) { | |
151 EXPECT_NONFATAL_FAILURE(EXPECT_WRITE(stdout, std::printf("test"), p_++), | |
152 "01234"); | |
153 EXPECT_EQ(s_ + 1, p_); | |
154 } | |
155 | |
156 // Tests that assertion arguments are evaluated exactly once. | |
157 TEST_F(single_evaluation_test, write_tests) { | |
158 // successful EXPECT_WRITE | |
159 EXPECT_WRITE( | |
160 stdout, | |
161 { // NOLINT | |
162 a_++; | |
163 std::printf("test"); | |
164 }, | |
165 (b_++, "test")); | |
166 EXPECT_EQ(1, a_); | |
167 EXPECT_EQ(1, b_); | |
168 | |
169 // failed EXPECT_WRITE | |
170 EXPECT_NONFATAL_FAILURE(EXPECT_WRITE( | |
171 stdout, | |
172 { // NOLINT | |
173 a_++; | |
174 std::printf("test"); | |
175 }, | |
176 (b_++, "other")), | |
177 "Actual: test"); | |
178 EXPECT_EQ(2, a_); | |
179 EXPECT_EQ(2, b_); | |
180 } | |
181 | |
182 // Tests EXPECT_WRITE. | |
183 TEST(gtest_extra_test, expect_write) { | |
184 EXPECT_WRITE(stdout, do_nothing(), ""); | |
185 EXPECT_WRITE(stdout, std::printf("test"), "test"); | |
186 EXPECT_WRITE(stderr, std::fprintf(stderr, "test"), "test"); | |
187 EXPECT_NONFATAL_FAILURE(EXPECT_WRITE(stdout, std::printf("that"), "this"), | |
188 "Expected: this\n" | |
189 " Actual: that"); | |
190 } | |
191 | |
192 TEST(gtest_extra_test, expect_write_streaming) { | |
193 EXPECT_WRITE(stdout, std::printf("test"), "test") << "unexpected failure"; | |
194 EXPECT_NONFATAL_FAILURE(EXPECT_WRITE(stdout, std::printf("test"), "other") | |
195 << "expected failure", | |
196 "expected failure"); | |
197 } | |
198 #endif // FMT_USE_FCNTL | |
199 | |
200 // Tests that the compiler will not complain about unreachable code in the | |
201 // EXPECT_THROW_MSG macro. | |
202 TEST(gtest_extra_test, expect_throw_no_unreachable_code_warning) { | |
203 int n = 0; | |
204 (void)n; | |
205 using std::runtime_error; | |
206 EXPECT_THROW_MSG(throw runtime_error(""), runtime_error, ""); | |
207 EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG(n++, runtime_error, ""), ""); | |
208 EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG(throw 1, runtime_error, ""), ""); | |
209 EXPECT_NONFATAL_FAILURE( | |
210 EXPECT_THROW_MSG(throw runtime_error("a"), runtime_error, "b"), ""); | |
211 } | |
212 | |
213 // Tests that the compiler will not complain about unreachable code in the | |
214 // EXPECT_SYSTEM_ERROR macro. | |
215 TEST(gtest_extra_test, expect_system_error_no_unreachable_code_warning) { | |
216 int n = 0; | |
217 (void)n; | |
218 EXPECT_SYSTEM_ERROR(throw fmt::system_error(EDOM, "test"), EDOM, "test"); | |
219 EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(n++, EDOM, ""), ""); | |
220 EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(throw 1, EDOM, ""), ""); | |
221 EXPECT_NONFATAL_FAILURE( | |
222 EXPECT_SYSTEM_ERROR(throw fmt::system_error(EDOM, "aaa"), EDOM, "bbb"), | |
223 ""); | |
224 } | |
225 | |
226 TEST(gtest_extra_test, expect_throw_behaves_like_single_statement) { | |
227 if (::testing::internal::AlwaysFalse()) | |
228 EXPECT_THROW_MSG(do_nothing(), std::exception, ""); | |
229 | |
230 if (::testing::internal::AlwaysTrue()) | |
231 EXPECT_THROW_MSG(throw_exception(), std::exception, "test"); | |
232 else | |
233 do_nothing(); | |
234 } | |
235 | |
236 TEST(gtest_extra_test, expect_system_error_behaves_like_single_statement) { | |
237 if (::testing::internal::AlwaysFalse()) | |
238 EXPECT_SYSTEM_ERROR(do_nothing(), EDOM, ""); | |
239 | |
240 if (::testing::internal::AlwaysTrue()) | |
241 EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "test"); | |
242 else | |
243 do_nothing(); | |
244 } | |
245 | |
246 TEST(gtest_extra_test, expect_write_behaves_like_single_statement) { | |
247 if (::testing::internal::AlwaysFalse()) | |
248 EXPECT_WRITE(stdout, std::printf("x"), "x"); | |
249 | |
250 if (::testing::internal::AlwaysTrue()) | |
251 EXPECT_WRITE(stdout, std::printf("x"), "x"); | |
252 else | |
253 do_nothing(); | |
254 } | |
255 | |
256 // Tests EXPECT_THROW_MSG. | |
257 TEST(gtest_extra_test, expect_throw_msg) { | |
258 EXPECT_THROW_MSG(throw_exception(), std::exception, "test"); | |
259 EXPECT_NONFATAL_FAILURE( | |
260 EXPECT_THROW_MSG(throw_exception(), std::logic_error, "test"), | |
261 "Expected: throw_exception() throws an exception of " | |
262 "type std::logic_error.\n Actual: it throws a different type."); | |
263 EXPECT_NONFATAL_FAILURE( | |
264 EXPECT_THROW_MSG(do_nothing(), std::exception, "test"), | |
265 "Expected: do_nothing() throws an exception of type std::exception.\n" | |
266 " Actual: it throws nothing."); | |
267 EXPECT_NONFATAL_FAILURE( | |
268 EXPECT_THROW_MSG(throw_exception(), std::exception, "other"), | |
269 "throw_exception() throws an exception with a different message.\n" | |
270 "Expected: other\n" | |
271 " Actual: test"); | |
272 } | |
273 | |
274 // Tests EXPECT_SYSTEM_ERROR. | |
275 TEST(gtest_extra_test, expect_system_error) { | |
276 EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "test"); | |
277 EXPECT_NONFATAL_FAILURE( | |
278 EXPECT_SYSTEM_ERROR(throw_exception(), EDOM, "test"), | |
279 "Expected: throw_exception() throws an exception of " | |
280 "type std::system_error.\n Actual: it throws a different type."); | |
281 EXPECT_NONFATAL_FAILURE( | |
282 EXPECT_SYSTEM_ERROR(do_nothing(), EDOM, "test"), | |
283 "Expected: do_nothing() throws an exception of type std::system_error.\n" | |
284 " Actual: it throws nothing."); | |
285 EXPECT_NONFATAL_FAILURE( | |
286 EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "other"), | |
287 fmt::format( | |
288 "throw_system_error() throws an exception with a different message.\n" | |
289 "Expected: {}\n" | |
290 " Actual: {}", | |
291 system_error_message(EDOM, "other"), | |
292 system_error_message(EDOM, "test"))); | |
293 } | |
294 | |
295 TEST(gtest_extra_test, expect_throw_msg_streaming) { | |
296 EXPECT_THROW_MSG(throw_exception(), std::exception, "test") | |
297 << "unexpected failure"; | |
298 EXPECT_NONFATAL_FAILURE( | |
299 EXPECT_THROW_MSG(throw_exception(), std::exception, "other") | |
300 << "expected failure", | |
301 "expected failure"); | |
302 } | |
303 | |
304 TEST(gtest_extra_test, expect_system_error_streaming) { | |
305 EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "test") | |
306 << "unexpected failure"; | |
307 EXPECT_NONFATAL_FAILURE( | |
308 EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "other") | |
309 << "expected failure", | |
310 "expected failure"); | |
311 } | |
312 | |
313 #if FMT_USE_FCNTL | |
314 | |
315 using fmt::buffered_file; | |
316 using fmt::file; | |
317 | |
318 TEST(output_redirect_test, scoped_redirect) { | |
319 file read_end, write_end; | |
320 file::pipe(read_end, write_end); | |
321 { | |
322 buffered_file file(write_end.fdopen("w")); | |
323 std::fprintf(file.get(), "[[["); | |
324 { | |
325 output_redirect redir(file.get()); | |
326 std::fprintf(file.get(), "censored"); | |
327 } | |
328 std::fprintf(file.get(), "]]]"); | |
329 } | |
330 EXPECT_READ(read_end, "[[[]]]"); | |
331 } | |
332 | |
333 // Test that output_redirect handles errors in flush correctly. | |
334 TEST(output_redirect_test, flush_error_in_ctor) { | |
335 file read_end, write_end; | |
336 file::pipe(read_end, write_end); | |
337 int write_fd = write_end.descriptor(); | |
338 file write_copy = write_end.dup(write_fd); | |
339 buffered_file f = write_end.fdopen("w"); | |
340 // Put a character in a file buffer. | |
341 EXPECT_EQ('x', fputc('x', f.get())); | |
342 FMT_POSIX(close(write_fd)); | |
343 std::unique_ptr<output_redirect> redir{nullptr}; | |
344 EXPECT_SYSTEM_ERROR_NOASSERT(redir.reset(new output_redirect(f.get())), EBADF, | |
345 "cannot flush stream"); | |
346 redir.reset(nullptr); | |
347 write_copy.dup2(write_fd); // "undo" close or dtor will fail | |
348 } | |
349 | |
350 TEST(output_redirect_test, dup_error_in_ctor) { | |
351 buffered_file f = open_buffered_file(); | |
352 int fd = (f.descriptor)(); | |
353 file copy = file::dup(fd); | |
354 FMT_POSIX(close(fd)); | |
355 std::unique_ptr<output_redirect> redir{nullptr}; | |
356 EXPECT_SYSTEM_ERROR_NOASSERT( | |
357 redir.reset(new output_redirect(f.get(), false)), EBADF, | |
358 fmt::format("cannot duplicate file descriptor {}", fd)); | |
359 copy.dup2(fd); // "undo" close or dtor will fail | |
360 } | |
361 | |
362 TEST(output_redirect_test, restore_and_read) { | |
363 file read_end, write_end; | |
364 file::pipe(read_end, write_end); | |
365 buffered_file file(write_end.fdopen("w")); | |
366 std::fprintf(file.get(), "[[["); | |
367 output_redirect redir(file.get()); | |
368 std::fprintf(file.get(), "censored"); | |
369 EXPECT_EQ("censored", redir.restore_and_read()); | |
370 EXPECT_EQ("", redir.restore_and_read()); | |
371 std::fprintf(file.get(), "]]]"); | |
372 file = buffered_file(); | |
373 EXPECT_READ(read_end, "[[[]]]"); | |
374 } | |
375 | |
376 // Test that OutputRedirect handles errors in flush correctly. | |
377 TEST(output_redirect_test, flush_error_in_restore_and_read) { | |
378 file read_end, write_end; | |
379 file::pipe(read_end, write_end); | |
380 int write_fd = write_end.descriptor(); | |
381 file write_copy = write_end.dup(write_fd); | |
382 buffered_file f = write_end.fdopen("w"); | |
383 output_redirect redir(f.get()); | |
384 // Put a character in a file buffer. | |
385 EXPECT_EQ('x', fputc('x', f.get())); | |
386 FMT_POSIX(close(write_fd)); | |
387 EXPECT_SYSTEM_ERROR_NOASSERT(redir.restore_and_read(), EBADF, | |
388 "cannot flush stream"); | |
389 write_copy.dup2(write_fd); // "undo" close or dtor will fail | |
390 } | |
391 | |
392 TEST(output_redirect_test, error_in_dtor) { | |
393 file read_end, write_end; | |
394 file::pipe(read_end, write_end); | |
395 int write_fd = write_end.descriptor(); | |
396 file write_copy = write_end.dup(write_fd); | |
397 buffered_file f = write_end.fdopen("w"); | |
398 std::unique_ptr<output_redirect> redir(new output_redirect(f.get())); | |
399 // Put a character in a file buffer. | |
400 EXPECT_EQ('x', fputc('x', f.get())); | |
401 EXPECT_WRITE( | |
402 stderr, | |
403 { | |
404 // The close function must be called inside EXPECT_WRITE, | |
405 // otherwise the system may recycle closed file descriptor when | |
406 // redirecting the output in EXPECT_STDERR and the second close | |
407 // will break output redirection. | |
408 FMT_POSIX(close(write_fd)); | |
409 SUPPRESS_ASSERT(redir.reset(nullptr)); | |
410 }, | |
411 system_error_message(EBADF, "cannot flush stream")); | |
412 write_copy.dup2(write_fd); // "undo" close or dtor of buffered_file will fail | |
413 } | |
414 | |
415 #endif // FMT_USE_FCNTL |