xref: /aosp_15_r20/external/fmtlib/test/gtest-extra-test.cc (revision 5c90c05cd622c0a81b57953a4d343e0e489f2e08)
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:
single_evaluation_test()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 
do_nothing()42 void do_nothing() {}
43 
throw_exception()44 FMT_NORETURN void throw_exception() { throw std::runtime_error("test"); }
45 
throw_system_error()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.
TEST_F(single_evaluation_test,failed_expect_throw_msg)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.
TEST_F(single_evaluation_test,failed_expect_system_error)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.
TEST_F(single_evaluation_test,exception_tests)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 
TEST_F(single_evaluation_test,system_error_tests)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.
TEST_F(single_evaluation_test,failed_expect_write)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.
TEST_F(single_evaluation_test,write_tests)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.
TEST(gtest_extra_test,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 
TEST(gtest_extra_test,expect_write_streaming)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.
TEST(gtest_extra_test,expect_throw_no_unreachable_code_warning)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.
TEST(gtest_extra_test,expect_system_error_no_unreachable_code_warning)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 
TEST(gtest_extra_test,expect_throw_behaves_like_single_statement)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 
TEST(gtest_extra_test,expect_system_error_behaves_like_single_statement)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 
TEST(gtest_extra_test,expect_write_behaves_like_single_statement)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.
TEST(gtest_extra_test,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.
TEST(gtest_extra_test,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 
TEST(gtest_extra_test,expect_throw_msg_streaming)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 
TEST(gtest_extra_test,expect_system_error_streaming)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 
TEST(output_redirect_test,scoped_redirect)318 TEST(output_redirect_test, scoped_redirect) {
319   auto pipe = fmt::pipe();
320   {
321     buffered_file file(pipe.write_end.fdopen("w"));
322     std::fprintf(file.get(), "[[[");
323     {
324       output_redirect redir(file.get());
325       std::fprintf(file.get(), "censored");
326     }
327     std::fprintf(file.get(), "]]]");
328   }
329   EXPECT_READ(pipe.read_end, "[[[]]]");
330 }
331 
332 // Test that output_redirect handles errors in flush correctly.
TEST(output_redirect_test,flush_error_in_ctor)333 TEST(output_redirect_test, flush_error_in_ctor) {
334   auto pipe = fmt::pipe();
335   int write_fd = pipe.write_end.descriptor();
336   file write_copy = pipe.write_end.dup(write_fd);
337   buffered_file f = pipe.write_end.fdopen("w");
338   // Put a character in a file buffer.
339   EXPECT_EQ('x', fputc('x', f.get()));
340   FMT_POSIX(close(write_fd));
341   std::unique_ptr<output_redirect> redir{nullptr};
342   EXPECT_SYSTEM_ERROR_NOASSERT(redir.reset(new output_redirect(f.get())), EBADF,
343                                "cannot flush stream");
344   redir.reset(nullptr);
345   write_copy.dup2(write_fd);  // "undo" close or dtor will fail
346 }
347 
TEST(output_redirect_test,dup_error_in_ctor)348 TEST(output_redirect_test, dup_error_in_ctor) {
349   buffered_file f = open_buffered_file();
350   int fd = (f.descriptor)();
351   file copy = file::dup(fd);
352   FMT_POSIX(close(fd));
353   std::unique_ptr<output_redirect> redir{nullptr};
354   EXPECT_SYSTEM_ERROR_NOASSERT(
355       redir.reset(new output_redirect(f.get(), false)), EBADF,
356       fmt::format("cannot duplicate file descriptor {}", fd));
357   copy.dup2(fd);  // "undo" close or dtor will fail
358 }
359 
TEST(output_redirect_test,restore_and_read)360 TEST(output_redirect_test, restore_and_read) {
361   auto pipe = fmt::pipe();
362   buffered_file file(pipe.write_end.fdopen("w"));
363   std::fprintf(file.get(), "[[[");
364   output_redirect redir(file.get());
365   std::fprintf(file.get(), "censored");
366   EXPECT_EQ("censored", redir.restore_and_read());
367   EXPECT_EQ("", redir.restore_and_read());
368   std::fprintf(file.get(), "]]]");
369   file = buffered_file();
370   EXPECT_READ(pipe.read_end, "[[[]]]");
371 }
372 
373 // Test that OutputRedirect handles errors in flush correctly.
TEST(output_redirect_test,flush_error_in_restore_and_read)374 TEST(output_redirect_test, flush_error_in_restore_and_read) {
375   auto pipe = fmt::pipe();
376   int write_fd = pipe.write_end.descriptor();
377   file write_copy = pipe.write_end.dup(write_fd);
378   buffered_file f = pipe.write_end.fdopen("w");
379   output_redirect redir(f.get());
380   // Put a character in a file buffer.
381   EXPECT_EQ('x', fputc('x', f.get()));
382   FMT_POSIX(close(write_fd));
383   EXPECT_SYSTEM_ERROR_NOASSERT(redir.restore_and_read(), EBADF,
384                                "cannot flush stream");
385   write_copy.dup2(write_fd);  // "undo" close or dtor will fail
386 }
387 
TEST(output_redirect_test,error_in_dtor)388 TEST(output_redirect_test, error_in_dtor) {
389   auto pipe = fmt::pipe();
390   int write_fd = pipe.write_end.descriptor();
391   file write_copy = pipe.write_end.dup(write_fd);
392   buffered_file f = pipe.write_end.fdopen("w");
393   std::unique_ptr<output_redirect> redir(new output_redirect(f.get()));
394   // Put a character in a file buffer.
395   EXPECT_EQ('x', fputc('x', f.get()));
396   EXPECT_WRITE(
397       stderr,
398       {
399         // The close function must be called inside EXPECT_WRITE,
400         // otherwise the system may recycle closed file descriptor when
401         // redirecting the output in EXPECT_STDERR and the second close
402         // will break output redirection.
403         FMT_POSIX(close(write_fd));
404         SUPPRESS_ASSERT(redir.reset(nullptr));
405       },
406       system_error_message(EBADF, "cannot flush stream"));
407   write_copy.dup2(write_fd);  // "undo" close or dtor of buffered_file will fail
408 }
409 
410 #endif  // FMT_USE_FCNTL
411