Mercurial > minori
comparison dep/fmt/test/gtest-extra-test.cc @ 343:1faa72660932
*: transfer back to cmake from autotools
autotools just made lots of things more complicated than
they should have and many things broke (i.e. translations)
| author | Paper <paper@paper.us.eu.org> |
|---|---|
| date | Thu, 20 Jun 2024 05:56:06 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 342:adb79bdde329 | 343:1faa72660932 |
|---|---|
| 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: | |
| 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 | |
| 42 void do_nothing() {} | |
| 43 | |
| 44 FMT_NORETURN void throw_exception() { throw std::runtime_error("test"); } | |
| 45 | |
| 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. | |
| 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. | |
| 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. | |
| 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 | |
| 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. | |
| 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. | |
| 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. | |
| 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 | |
| 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. | |
| 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. | |
| 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 | |
| 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 | |
| 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 | |
| 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. | |
| 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. | |
| 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 | |
| 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 | |
| 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 | |
| 318 TEST(output_redirect_test, scoped_redirect) { | |
| 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 output_redirect 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 output_redirect handles errors in flush correctly. | |
| 334 TEST(output_redirect_test, flush_error_in_ctor) { | |
| 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)); | |
| 343 std::unique_ptr<output_redirect> redir{nullptr}; | |
| 344 EXPECT_SYSTEM_ERROR_NOASSERT(redir.reset(new output_redirect(f.get())), EBADF, | |
| 345 "cannot flush stream"); | |
| 346 redir.reset(nullptr); | |
| 347 write_copy.dup2(write_fd); // "undo" close or dtor will fail | |
| 348 } | |
| 349 | |
| 350 TEST(output_redirect_test, dup_error_in_ctor) { | |
| 351 buffered_file f = open_buffered_file(); | |
| 352 int fd = (f.descriptor)(); | |
| 353 file copy = file::dup(fd); | |
| 354 FMT_POSIX(close(fd)); | |
| 355 std::unique_ptr<output_redirect> redir{nullptr}; | |
| 356 EXPECT_SYSTEM_ERROR_NOASSERT( | |
| 357 redir.reset(new output_redirect(f.get(), false)), EBADF, | |
| 358 fmt::format("cannot duplicate file descriptor {}", fd)); | |
| 359 copy.dup2(fd); // "undo" close or dtor will fail | |
| 360 } | |
| 361 | |
| 362 TEST(output_redirect_test, restore_and_read) { | |
| 363 file read_end, write_end; | |
| 364 file::pipe(read_end, write_end); | |
| 365 buffered_file file(write_end.fdopen("w")); | |
| 366 std::fprintf(file.get(), "[[["); | |
| 367 output_redirect redir(file.get()); | |
| 368 std::fprintf(file.get(), "censored"); | |
| 369 EXPECT_EQ("censored", redir.restore_and_read()); | |
| 370 EXPECT_EQ("", redir.restore_and_read()); | |
| 371 std::fprintf(file.get(), "]]]"); | |
| 372 file = buffered_file(); | |
| 373 EXPECT_READ(read_end, "[[[]]]"); | |
| 374 } | |
| 375 | |
| 376 // Test that OutputRedirect handles errors in flush correctly. | |
| 377 TEST(output_redirect_test, flush_error_in_restore_and_read) { | |
| 378 file read_end, write_end; | |
| 379 file::pipe(read_end, write_end); | |
| 380 int write_fd = write_end.descriptor(); | |
| 381 file write_copy = write_end.dup(write_fd); | |
| 382 buffered_file f = write_end.fdopen("w"); | |
| 383 output_redirect redir(f.get()); | |
| 384 // Put a character in a file buffer. | |
| 385 EXPECT_EQ('x', fputc('x', f.get())); | |
| 386 FMT_POSIX(close(write_fd)); | |
| 387 EXPECT_SYSTEM_ERROR_NOASSERT(redir.restore_and_read(), EBADF, | |
| 388 "cannot flush stream"); | |
| 389 write_copy.dup2(write_fd); // "undo" close or dtor will fail | |
| 390 } | |
| 391 | |
| 392 TEST(output_redirect_test, error_in_dtor) { | |
| 393 file read_end, write_end; | |
| 394 file::pipe(read_end, write_end); | |
| 395 int write_fd = write_end.descriptor(); | |
| 396 file write_copy = write_end.dup(write_fd); | |
| 397 buffered_file f = write_end.fdopen("w"); | |
| 398 std::unique_ptr<output_redirect> redir(new output_redirect(f.get())); | |
| 399 // Put a character in a file buffer. | |
| 400 EXPECT_EQ('x', fputc('x', f.get())); | |
| 401 EXPECT_WRITE( | |
| 402 stderr, | |
| 403 { | |
| 404 // The close function must be called inside EXPECT_WRITE, | |
| 405 // otherwise the system may recycle closed file descriptor when | |
| 406 // redirecting the output in EXPECT_STDERR and the second close | |
| 407 // will break output redirection. | |
| 408 FMT_POSIX(close(write_fd)); | |
| 409 SUPPRESS_ASSERT(redir.reset(nullptr)); | |
| 410 }, | |
| 411 system_error_message(EBADF, "cannot flush stream")); | |
| 412 write_copy.dup2(write_fd); // "undo" close or dtor of buffered_file will fail | |
| 413 } | |
| 414 | |
| 415 #endif // FMT_USE_FCNTL |
