| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 | // Formatting library for C++ - tests of custom Google Test assertions//// Copyright (c) 2012 - present, Victor Zverovich// All rights reserved.//// For the license information refer to format.h.#include "gtest-extra.h"#include <gtest/gtest-spi.h>#include <cstring>#include <memory>#include <stdexcept>#include "fmt/os.h"#include "util.h"// Tests that assertion macros evaluate their arguments exactly once.namespace {class single_evaluation_test : public ::testing::Test { protected:  single_evaluation_test() {    p_ = s_;    a_ = 0;    b_ = 0;  }  static const char* const s_;  static const char* p_;  static int a_;  static int b_;};}  // namespaceconst char* const single_evaluation_test::s_ = "01234";const char* single_evaluation_test::p_;int single_evaluation_test::a_;int single_evaluation_test::b_;void do_nothing() {}FMT_NORETURN void throw_exception() { throw std::runtime_error("test"); }FMT_NORETURN void throw_system_error() {  throw fmt::system_error(EDOM, "test");}// Tests that when EXPECT_THROW_MSG fails, it evaluates its message argument// exactly once.TEST_F(single_evaluation_test, failed_expect_throw_msg) {  EXPECT_NONFATAL_FAILURE(      EXPECT_THROW_MSG(throw_exception(), std::exception, p_++), "01234");  EXPECT_EQ(s_ + 1, p_);}// Tests that when EXPECT_SYSTEM_ERROR fails, it evaluates its message argument// exactly once.TEST_F(single_evaluation_test, failed_expect_system_error) {  EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, p_++),                          "01234");  EXPECT_EQ(s_ + 1, p_);}// Tests that assertion arguments are evaluated exactly once.TEST_F(single_evaluation_test, exception_tests) {  // successful EXPECT_THROW_MSG  EXPECT_THROW_MSG(      {  // NOLINT        a_++;        throw_exception();      },      std::exception, (b_++, "test"));  EXPECT_EQ(1, a_);  EXPECT_EQ(1, b_);  // failed EXPECT_THROW_MSG, throws different type  EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG(                              {  // NOLINT                                a_++;                                throw_exception();                              },                              std::logic_error, (b_++, "test")),                          "throws a different type");  EXPECT_EQ(2, a_);  EXPECT_EQ(2, b_);  // failed EXPECT_THROW_MSG, throws an exception with different message  EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG(                              {  // NOLINT                                a_++;                                throw_exception();                              },                              std::exception, (b_++, "other")),                          "throws an exception with a different message");  EXPECT_EQ(3, a_);  EXPECT_EQ(3, b_);  // failed EXPECT_THROW_MSG, throws nothing  EXPECT_NONFATAL_FAILURE(      EXPECT_THROW_MSG(a_++, std::exception, (b_++, "test")), "throws nothing");  EXPECT_EQ(4, a_);  EXPECT_EQ(4, b_);}TEST_F(single_evaluation_test, system_error_tests) {  // successful EXPECT_SYSTEM_ERROR  EXPECT_SYSTEM_ERROR(      {  // NOLINT        a_++;        throw_system_error();      },      EDOM, (b_++, "test"));  EXPECT_EQ(1, a_);  EXPECT_EQ(1, b_);  // failed EXPECT_SYSTEM_ERROR, throws different type  EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(                              {  // NOLINT                                a_++;                                throw_exception();                              },                              EDOM, (b_++, "test")),                          "throws a different type");  EXPECT_EQ(2, a_);  EXPECT_EQ(2, b_);  // failed EXPECT_SYSTEM_ERROR, throws an exception with different message  EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(                              {  // NOLINT                                a_++;                                throw_system_error();                              },                              EDOM, (b_++, "other")),                          "throws an exception with a different message");  EXPECT_EQ(3, a_);  EXPECT_EQ(3, b_);  // failed EXPECT_SYSTEM_ERROR, throws nothing  EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(a_++, EDOM, (b_++, "test")),                          "throws nothing");  EXPECT_EQ(4, a_);  EXPECT_EQ(4, b_);}#if FMT_USE_FCNTL// Tests that when EXPECT_WRITE fails, it evaluates its message argument// exactly once.TEST_F(single_evaluation_test, failed_expect_write) {  EXPECT_NONFATAL_FAILURE(EXPECT_WRITE(stdout, std::printf("test"), p_++),                          "01234");  EXPECT_EQ(s_ + 1, p_);}// Tests that assertion arguments are evaluated exactly once.TEST_F(single_evaluation_test, write_tests) {  // successful EXPECT_WRITE  EXPECT_WRITE(      stdout,      {  // NOLINT        a_++;        std::printf("test");      },      (b_++, "test"));  EXPECT_EQ(1, a_);  EXPECT_EQ(1, b_);  // failed EXPECT_WRITE  EXPECT_NONFATAL_FAILURE(EXPECT_WRITE(                              stdout,                              {  // NOLINT                                a_++;                                std::printf("test");                              },                              (b_++, "other")),                          "Actual: test");  EXPECT_EQ(2, a_);  EXPECT_EQ(2, b_);}// Tests EXPECT_WRITE.TEST(gtest_extra_test, expect_write) {  EXPECT_WRITE(stdout, do_nothing(), "");  EXPECT_WRITE(stdout, std::printf("test"), "test");  EXPECT_WRITE(stderr, std::fprintf(stderr, "test"), "test");  EXPECT_NONFATAL_FAILURE(EXPECT_WRITE(stdout, std::printf("that"), "this"),                          "Expected: this\n"                          "  Actual: that");}TEST(gtest_extra_test, expect_write_streaming) {  EXPECT_WRITE(stdout, std::printf("test"), "test") << "unexpected failure";  EXPECT_NONFATAL_FAILURE(EXPECT_WRITE(stdout, std::printf("test"), "other")                              << "expected failure",                          "expected failure");}#endif  // FMT_USE_FCNTL// Tests that the compiler will not complain about unreachable code in the// EXPECT_THROW_MSG macro.TEST(gtest_extra_test, expect_throw_no_unreachable_code_warning) {  int n = 0;  using std::runtime_error;  EXPECT_THROW_MSG(throw runtime_error(""), runtime_error, "");  EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG(n++, runtime_error, ""), "");  EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG(throw 1, runtime_error, ""), "");  EXPECT_NONFATAL_FAILURE(      EXPECT_THROW_MSG(throw runtime_error("a"), runtime_error, "b"), "");}// Tests that the compiler will not complain about unreachable code in the// EXPECT_SYSTEM_ERROR macro.TEST(gtest_extra_test, expect_system_error_no_unreachable_code_warning) {  int n = 0;  EXPECT_SYSTEM_ERROR(throw fmt::system_error(EDOM, "test"), EDOM, "test");  EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(n++, EDOM, ""), "");  EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(throw 1, EDOM, ""), "");  EXPECT_NONFATAL_FAILURE(      EXPECT_SYSTEM_ERROR(throw fmt::system_error(EDOM, "aaa"), EDOM, "bbb"),      "");}TEST(gtest_extra_test, expect_throw_behaves_like_single_statement) {  if (::testing::internal::AlwaysFalse())    EXPECT_THROW_MSG(do_nothing(), std::exception, "");  if (::testing::internal::AlwaysTrue())    EXPECT_THROW_MSG(throw_exception(), std::exception, "test");  else    do_nothing();}TEST(gtest_extra_test, expect_system_error_behaves_like_single_statement) {  if (::testing::internal::AlwaysFalse())    EXPECT_SYSTEM_ERROR(do_nothing(), EDOM, "");  if (::testing::internal::AlwaysTrue())    EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "test");  else    do_nothing();}TEST(gtest_extra_test, expect_write_behaves_like_single_statement) {  if (::testing::internal::AlwaysFalse())    EXPECT_WRITE(stdout, std::printf("x"), "x");  if (::testing::internal::AlwaysTrue())    EXPECT_WRITE(stdout, std::printf("x"), "x");  else    do_nothing();}// Tests EXPECT_THROW_MSG.TEST(gtest_extra_test, expect_throw_msg) {  EXPECT_THROW_MSG(throw_exception(), std::exception, "test");  EXPECT_NONFATAL_FAILURE(      EXPECT_THROW_MSG(throw_exception(), std::logic_error, "test"),      "Expected: throw_exception() throws an exception of "      "type std::logic_error.\n  Actual: it throws a different type.");  EXPECT_NONFATAL_FAILURE(      EXPECT_THROW_MSG(do_nothing(), std::exception, "test"),      "Expected: do_nothing() throws an exception of type std::exception.\n"      "  Actual: it throws nothing.");  EXPECT_NONFATAL_FAILURE(      EXPECT_THROW_MSG(throw_exception(), std::exception, "other"),      "throw_exception() throws an exception with a different message.\n"      "Expected: other\n"      "  Actual: test");}// Tests EXPECT_SYSTEM_ERROR.TEST(gtest_extra_test, expect_system_error) {  EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "test");  EXPECT_NONFATAL_FAILURE(      EXPECT_SYSTEM_ERROR(throw_exception(), EDOM, "test"),      "Expected: throw_exception() throws an exception of "      "type std::system_error.\n  Actual: it throws a different type.");  EXPECT_NONFATAL_FAILURE(      EXPECT_SYSTEM_ERROR(do_nothing(), EDOM, "test"),      "Expected: do_nothing() throws an exception of type std::system_error.\n"      "  Actual: it throws nothing.");  EXPECT_NONFATAL_FAILURE(      EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "other"),      fmt::format(          "throw_system_error() throws an exception with a different message.\n"          "Expected: {}\n"          "  Actual: {}",          system_error_message(EDOM, "other"),          system_error_message(EDOM, "test")));}TEST(gtest_extra_test, expect_throw_msg_streaming) {  EXPECT_THROW_MSG(throw_exception(), std::exception, "test")      << "unexpected failure";  EXPECT_NONFATAL_FAILURE(      EXPECT_THROW_MSG(throw_exception(), std::exception, "other")          << "expected failure",      "expected failure");}TEST(gtest_extra_test, expect_system_error_streaming) {  EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "test")      << "unexpected failure";  EXPECT_NONFATAL_FAILURE(      EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "other")          << "expected failure",      "expected failure");}#if FMT_USE_FCNTLusing fmt::buffered_file;using fmt::file;TEST(output_redirect_test, scoped_redirect) {  file read_end, write_end;  file::pipe(read_end, write_end);  {    buffered_file file(write_end.fdopen("w"));    std::fprintf(file.get(), "[[[");    {      output_redirect redir(file.get());      std::fprintf(file.get(), "censored");    }    std::fprintf(file.get(), "]]]");  }  EXPECT_READ(read_end, "[[[]]]");}// Test that output_redirect handles errors in flush correctly.TEST(output_redirect_test, flush_error_in_ctor) {  file read_end, write_end;  file::pipe(read_end, write_end);  int write_fd = write_end.descriptor();  file write_copy = write_end.dup(write_fd);  buffered_file f = write_end.fdopen("w");  // Put a character in a file buffer.  EXPECT_EQ('x', fputc('x', f.get()));  FMT_POSIX(close(write_fd));  std::unique_ptr<output_redirect> redir{nullptr};  EXPECT_SYSTEM_ERROR_NOASSERT(redir.reset(new output_redirect(f.get())), EBADF,                               "cannot flush stream");  redir.reset(nullptr);  write_copy.dup2(write_fd);  // "undo" close or dtor will fail}TEST(output_redirect_test, dup_error_in_ctor) {  buffered_file f = open_buffered_file();  int fd = (f.descriptor)();  file copy = file::dup(fd);  FMT_POSIX(close(fd));  std::unique_ptr<output_redirect> redir{nullptr};  EXPECT_SYSTEM_ERROR_NOASSERT(      redir.reset(new output_redirect(f.get())), EBADF,      fmt::format("cannot duplicate file descriptor {}", fd));  copy.dup2(fd);  // "undo" close or dtor will fail}TEST(output_redirect_test, restore_and_read) {  file read_end, write_end;  file::pipe(read_end, write_end);  buffered_file file(write_end.fdopen("w"));  std::fprintf(file.get(), "[[[");  output_redirect redir(file.get());  std::fprintf(file.get(), "censored");  EXPECT_EQ("censored", redir.restore_and_read());  EXPECT_EQ("", redir.restore_and_read());  std::fprintf(file.get(), "]]]");  file = buffered_file();  EXPECT_READ(read_end, "[[[]]]");}// Test that OutputRedirect handles errors in flush correctly.TEST(output_redirect_test, flush_error_in_restore_and_read) {  file read_end, write_end;  file::pipe(read_end, write_end);  int write_fd = write_end.descriptor();  file write_copy = write_end.dup(write_fd);  buffered_file f = write_end.fdopen("w");  output_redirect redir(f.get());  // Put a character in a file buffer.  EXPECT_EQ('x', fputc('x', f.get()));  FMT_POSIX(close(write_fd));  EXPECT_SYSTEM_ERROR_NOASSERT(redir.restore_and_read(), EBADF,                               "cannot flush stream");  write_copy.dup2(write_fd);  // "undo" close or dtor will fail}TEST(output_redirect_test, error_in_dtor) {  file read_end, write_end;  file::pipe(read_end, write_end);  int write_fd = write_end.descriptor();  file write_copy = write_end.dup(write_fd);  buffered_file f = write_end.fdopen("w");  std::unique_ptr<output_redirect> redir(new output_redirect(f.get()));  // Put a character in a file buffer.  EXPECT_EQ('x', fputc('x', f.get()));  EXPECT_WRITE(      stderr,      {        // The close function must be called inside EXPECT_WRITE,        // otherwise the system may recycle closed file descriptor when        // redirecting the output in EXPECT_STDERR and the second close        // will break output redirection.        FMT_POSIX(close(write_fd));        SUPPRESS_ASSERT(redir.reset(nullptr));      },      system_error_message(EBADF, "cannot flush stream"));  write_copy.dup2(write_fd);  // "undo" close or dtor of buffered_file will fail}#endif  // FMT_USE_FCNTL
 |