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