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