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