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