• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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