xref: /aosp_15_r20/external/fmtlib/test/gtest-extra.h (revision 5c90c05cd622c0a81b57953a4d343e0e489f2e08)
1*5c90c05cSAndroid Build Coastguard Worker // Formatting library for C++ - custom Google Test assertions
2*5c90c05cSAndroid Build Coastguard Worker //
3*5c90c05cSAndroid Build Coastguard Worker // Copyright (c) 2012 - present, Victor Zverovich
4*5c90c05cSAndroid Build Coastguard Worker // All rights reserved.
5*5c90c05cSAndroid Build Coastguard Worker //
6*5c90c05cSAndroid Build Coastguard Worker // For the license information refer to format.h.
7*5c90c05cSAndroid Build Coastguard Worker 
8*5c90c05cSAndroid Build Coastguard Worker #ifndef FMT_GTEST_EXTRA_H_
9*5c90c05cSAndroid Build Coastguard Worker #define FMT_GTEST_EXTRA_H_
10*5c90c05cSAndroid Build Coastguard Worker 
11*5c90c05cSAndroid Build Coastguard Worker #include <stdlib.h>  // _invalid_parameter_handler
12*5c90c05cSAndroid Build Coastguard Worker 
13*5c90c05cSAndroid Build Coastguard Worker #include <string>
14*5c90c05cSAndroid Build Coastguard Worker 
15*5c90c05cSAndroid Build Coastguard Worker #include "fmt/os.h"
16*5c90c05cSAndroid Build Coastguard Worker #include "gmock/gmock.h"
17*5c90c05cSAndroid Build Coastguard Worker 
18*5c90c05cSAndroid Build Coastguard Worker #define FMT_TEST_THROW_(statement, expected_exception, expected_message, fail) \
19*5c90c05cSAndroid Build Coastguard Worker   GTEST_AMBIGUOUS_ELSE_BLOCKER_                                                \
20*5c90c05cSAndroid Build Coastguard Worker   if (::testing::AssertionResult gtest_ar = ::testing::AssertionSuccess()) {   \
21*5c90c05cSAndroid Build Coastguard Worker     std::string gtest_expected_message = expected_message;                     \
22*5c90c05cSAndroid Build Coastguard Worker     bool gtest_caught_expected = false;                                        \
23*5c90c05cSAndroid Build Coastguard Worker     try {                                                                      \
24*5c90c05cSAndroid Build Coastguard Worker       GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement);               \
25*5c90c05cSAndroid Build Coastguard Worker     } catch (expected_exception const& e) {                                    \
26*5c90c05cSAndroid Build Coastguard Worker       if (gtest_expected_message != e.what()) {                                \
27*5c90c05cSAndroid Build Coastguard Worker         gtest_ar << #statement                                                 \
28*5c90c05cSAndroid Build Coastguard Worker             " throws an exception with a different message.\n"                 \
29*5c90c05cSAndroid Build Coastguard Worker                  << "Expected: " << gtest_expected_message << "\n"             \
30*5c90c05cSAndroid Build Coastguard Worker                  << "  Actual: " << e.what();                                  \
31*5c90c05cSAndroid Build Coastguard Worker         goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__);            \
32*5c90c05cSAndroid Build Coastguard Worker       }                                                                        \
33*5c90c05cSAndroid Build Coastguard Worker       gtest_caught_expected = true;                                            \
34*5c90c05cSAndroid Build Coastguard Worker     } catch (...) {                                                            \
35*5c90c05cSAndroid Build Coastguard Worker       gtest_ar << "Expected: " #statement                                      \
36*5c90c05cSAndroid Build Coastguard Worker                   " throws an exception of type " #expected_exception          \
37*5c90c05cSAndroid Build Coastguard Worker                   ".\n  Actual: it throws a different type.";                  \
38*5c90c05cSAndroid Build Coastguard Worker       goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__);              \
39*5c90c05cSAndroid Build Coastguard Worker     }                                                                          \
40*5c90c05cSAndroid Build Coastguard Worker     if (!gtest_caught_expected) {                                              \
41*5c90c05cSAndroid Build Coastguard Worker       gtest_ar << "Expected: " #statement                                      \
42*5c90c05cSAndroid Build Coastguard Worker                   " throws an exception of type " #expected_exception          \
43*5c90c05cSAndroid Build Coastguard Worker                   ".\n  Actual: it throws nothing.";                           \
44*5c90c05cSAndroid Build Coastguard Worker       goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__);              \
45*5c90c05cSAndroid Build Coastguard Worker     }                                                                          \
46*5c90c05cSAndroid Build Coastguard Worker   } else                                                                       \
47*5c90c05cSAndroid Build Coastguard Worker     GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__)                      \
48*5c90c05cSAndroid Build Coastguard Worker         : fail(gtest_ar.failure_message())
49*5c90c05cSAndroid Build Coastguard Worker 
50*5c90c05cSAndroid Build Coastguard Worker // Tests that the statement throws the expected exception and the exception's
51*5c90c05cSAndroid Build Coastguard Worker // what() method returns expected message.
52*5c90c05cSAndroid Build Coastguard Worker #define EXPECT_THROW_MSG(statement, expected_exception, expected_message) \
53*5c90c05cSAndroid Build Coastguard Worker   FMT_TEST_THROW_(statement, expected_exception, expected_message,        \
54*5c90c05cSAndroid Build Coastguard Worker                   GTEST_NONFATAL_FAILURE_)
55*5c90c05cSAndroid Build Coastguard Worker 
system_error_message(int error_code,const std::string & message)56*5c90c05cSAndroid Build Coastguard Worker inline std::string system_error_message(int error_code,
57*5c90c05cSAndroid Build Coastguard Worker                                         const std::string& message) {
58*5c90c05cSAndroid Build Coastguard Worker   auto ec = std::error_code(error_code, std::generic_category());
59*5c90c05cSAndroid Build Coastguard Worker   return std::system_error(ec, message).what();
60*5c90c05cSAndroid Build Coastguard Worker }
61*5c90c05cSAndroid Build Coastguard Worker 
62*5c90c05cSAndroid Build Coastguard Worker #define EXPECT_SYSTEM_ERROR(statement, error_code, message) \
63*5c90c05cSAndroid Build Coastguard Worker   EXPECT_THROW_MSG(statement, std::system_error,            \
64*5c90c05cSAndroid Build Coastguard Worker                    system_error_message(error_code, message))
65*5c90c05cSAndroid Build Coastguard Worker 
66*5c90c05cSAndroid Build Coastguard Worker #if FMT_USE_FCNTL
67*5c90c05cSAndroid Build Coastguard Worker 
68*5c90c05cSAndroid Build Coastguard Worker // Captures file output by redirecting it to a pipe.
69*5c90c05cSAndroid Build Coastguard Worker // The output it can handle is limited by the pipe capacity.
70*5c90c05cSAndroid Build Coastguard Worker class output_redirect {
71*5c90c05cSAndroid Build Coastguard Worker  private:
72*5c90c05cSAndroid Build Coastguard Worker   FILE* file_;
73*5c90c05cSAndroid Build Coastguard Worker   fmt::file original_;  // Original file passed to redirector.
74*5c90c05cSAndroid Build Coastguard Worker   fmt::file read_end_;  // Read end of the pipe where the output is redirected.
75*5c90c05cSAndroid Build Coastguard Worker 
76*5c90c05cSAndroid Build Coastguard Worker   void flush();
77*5c90c05cSAndroid Build Coastguard Worker   void restore();
78*5c90c05cSAndroid Build Coastguard Worker 
79*5c90c05cSAndroid Build Coastguard Worker  public:
80*5c90c05cSAndroid Build Coastguard Worker   explicit output_redirect(FILE* file, bool flush = true);
81*5c90c05cSAndroid Build Coastguard Worker   ~output_redirect() noexcept;
82*5c90c05cSAndroid Build Coastguard Worker 
83*5c90c05cSAndroid Build Coastguard Worker   output_redirect(const output_redirect&) = delete;
84*5c90c05cSAndroid Build Coastguard Worker   void operator=(const output_redirect&) = delete;
85*5c90c05cSAndroid Build Coastguard Worker 
86*5c90c05cSAndroid Build Coastguard Worker   // Restores the original file, reads output from the pipe into a string
87*5c90c05cSAndroid Build Coastguard Worker   // and returns it.
88*5c90c05cSAndroid Build Coastguard Worker   std::string restore_and_read();
89*5c90c05cSAndroid Build Coastguard Worker };
90*5c90c05cSAndroid Build Coastguard Worker 
91*5c90c05cSAndroid Build Coastguard Worker #  define FMT_TEST_WRITE_(statement, expected_output, file, fail)              \
92*5c90c05cSAndroid Build Coastguard Worker     GTEST_AMBIGUOUS_ELSE_BLOCKER_                                              \
93*5c90c05cSAndroid Build Coastguard Worker     if (::testing::AssertionResult gtest_ar = ::testing::AssertionSuccess()) { \
94*5c90c05cSAndroid Build Coastguard Worker       std::string gtest_expected_output = expected_output;                     \
95*5c90c05cSAndroid Build Coastguard Worker       output_redirect gtest_redir(file);                                       \
96*5c90c05cSAndroid Build Coastguard Worker       GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement);               \
97*5c90c05cSAndroid Build Coastguard Worker       std::string gtest_output = gtest_redir.restore_and_read();               \
98*5c90c05cSAndroid Build Coastguard Worker       if (gtest_output != gtest_expected_output) {                             \
99*5c90c05cSAndroid Build Coastguard Worker         gtest_ar << #statement " produces different output.\n"                 \
100*5c90c05cSAndroid Build Coastguard Worker                  << "Expected: " << gtest_expected_output << "\n"              \
101*5c90c05cSAndroid Build Coastguard Worker                  << "  Actual: " << gtest_output;                              \
102*5c90c05cSAndroid Build Coastguard Worker         goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__);            \
103*5c90c05cSAndroid Build Coastguard Worker       }                                                                        \
104*5c90c05cSAndroid Build Coastguard Worker     } else                                                                     \
105*5c90c05cSAndroid Build Coastguard Worker       GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__)                    \
106*5c90c05cSAndroid Build Coastguard Worker           : fail(gtest_ar.failure_message())
107*5c90c05cSAndroid Build Coastguard Worker 
108*5c90c05cSAndroid Build Coastguard Worker // Tests that the statement writes the expected output to file.
109*5c90c05cSAndroid Build Coastguard Worker #  define EXPECT_WRITE(file, statement, expected_output) \
110*5c90c05cSAndroid Build Coastguard Worker     FMT_TEST_WRITE_(statement, expected_output, file, GTEST_NONFATAL_FAILURE_)
111*5c90c05cSAndroid Build Coastguard Worker 
112*5c90c05cSAndroid Build Coastguard Worker #  ifdef _MSC_VER
113*5c90c05cSAndroid Build Coastguard Worker 
114*5c90c05cSAndroid Build Coastguard Worker // Suppresses Windows assertions on invalid file descriptors, making
115*5c90c05cSAndroid Build Coastguard Worker // POSIX functions return proper error codes instead of crashing on Windows.
116*5c90c05cSAndroid Build Coastguard Worker class suppress_assert {
117*5c90c05cSAndroid Build Coastguard Worker  private:
118*5c90c05cSAndroid Build Coastguard Worker   _invalid_parameter_handler original_handler_;
119*5c90c05cSAndroid Build Coastguard Worker   int original_report_mode_;
120*5c90c05cSAndroid Build Coastguard Worker 
handle_invalid_parameter(const wchar_t *,const wchar_t *,const wchar_t *,unsigned,uintptr_t)121*5c90c05cSAndroid Build Coastguard Worker   static void handle_invalid_parameter(const wchar_t*, const wchar_t*,
122*5c90c05cSAndroid Build Coastguard Worker                                        const wchar_t*, unsigned, uintptr_t) {}
123*5c90c05cSAndroid Build Coastguard Worker 
124*5c90c05cSAndroid Build Coastguard Worker  public:
suppress_assert()125*5c90c05cSAndroid Build Coastguard Worker   suppress_assert()
126*5c90c05cSAndroid Build Coastguard Worker       : original_handler_(
127*5c90c05cSAndroid Build Coastguard Worker             _set_invalid_parameter_handler(handle_invalid_parameter)),
128*5c90c05cSAndroid Build Coastguard Worker         original_report_mode_(_CrtSetReportMode(_CRT_ASSERT, 0)) {}
~suppress_assert()129*5c90c05cSAndroid Build Coastguard Worker   ~suppress_assert() {
130*5c90c05cSAndroid Build Coastguard Worker     _set_invalid_parameter_handler(original_handler_);
131*5c90c05cSAndroid Build Coastguard Worker     _CrtSetReportMode(_CRT_ASSERT, original_report_mode_);
132*5c90c05cSAndroid Build Coastguard Worker     (void)original_report_mode_;
133*5c90c05cSAndroid Build Coastguard Worker   }
134*5c90c05cSAndroid Build Coastguard Worker };
135*5c90c05cSAndroid Build Coastguard Worker 
136*5c90c05cSAndroid Build Coastguard Worker #    define SUPPRESS_ASSERT(statement) \
137*5c90c05cSAndroid Build Coastguard Worker       {                                \
138*5c90c05cSAndroid Build Coastguard Worker         suppress_assert sa;            \
139*5c90c05cSAndroid Build Coastguard Worker         statement;                     \
140*5c90c05cSAndroid Build Coastguard Worker       }
141*5c90c05cSAndroid Build Coastguard Worker #  else
142*5c90c05cSAndroid Build Coastguard Worker #    define SUPPRESS_ASSERT(statement) statement
143*5c90c05cSAndroid Build Coastguard Worker #  endif  // _MSC_VER
144*5c90c05cSAndroid Build Coastguard Worker 
145*5c90c05cSAndroid Build Coastguard Worker #  define EXPECT_SYSTEM_ERROR_NOASSERT(statement, error_code, message) \
146*5c90c05cSAndroid Build Coastguard Worker     EXPECT_SYSTEM_ERROR(SUPPRESS_ASSERT(statement), error_code, message)
147*5c90c05cSAndroid Build Coastguard Worker 
148*5c90c05cSAndroid Build Coastguard Worker // Attempts to read count characters from a file.
149*5c90c05cSAndroid Build Coastguard Worker std::string read(fmt::file& f, size_t count);
150*5c90c05cSAndroid Build Coastguard Worker 
151*5c90c05cSAndroid Build Coastguard Worker #  define EXPECT_READ(file, expected_content) \
152*5c90c05cSAndroid Build Coastguard Worker     EXPECT_EQ(expected_content,               \
153*5c90c05cSAndroid Build Coastguard Worker               read(file, fmt::string_view(expected_content).size()))
154*5c90c05cSAndroid Build Coastguard Worker 
155*5c90c05cSAndroid Build Coastguard Worker #else
156*5c90c05cSAndroid Build Coastguard Worker #  define EXPECT_WRITE(file, statement, expected_output) \
157*5c90c05cSAndroid Build Coastguard Worker     do {                                                 \
158*5c90c05cSAndroid Build Coastguard Worker       (void)(file);                                      \
159*5c90c05cSAndroid Build Coastguard Worker       (void)(statement);                                 \
160*5c90c05cSAndroid Build Coastguard Worker       (void)(expected_output);                           \
161*5c90c05cSAndroid Build Coastguard Worker       SUCCEED();                                         \
162*5c90c05cSAndroid Build Coastguard Worker     } while (false)
163*5c90c05cSAndroid Build Coastguard Worker #endif  // FMT_USE_FCNTL
164*5c90c05cSAndroid Build Coastguard Worker 
165*5c90c05cSAndroid Build Coastguard Worker #endif  // FMT_GTEST_EXTRA_H_
166