aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/testing/gtest_extensions/assertions.h
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/testing/gtest_extensions/assertions.h
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/testing/gtest_extensions/assertions.h')
-rw-r--r--library/cpp/testing/gtest_extensions/assertions.h111
1 files changed, 111 insertions, 0 deletions
diff --git a/library/cpp/testing/gtest_extensions/assertions.h b/library/cpp/testing/gtest_extensions/assertions.h
new file mode 100644
index 0000000000..e8ea07b5df
--- /dev/null
+++ b/library/cpp/testing/gtest_extensions/assertions.h
@@ -0,0 +1,111 @@
+#pragma once
+
+#include <util/generic/string.h>
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+/**
+ * Check that the given statement throws an exception of the given type,
+ * and that the thrown exception message contains the given substring.
+ */
+#define EXPECT_THROW_MESSAGE_HAS_SUBSTR(statement, expectedException, substring) \
+ _Y_GTEST_EXPECT_THROW_MESSAGE_HAS_SUBSTR_IMPL_(statement, expectedException, substring, GTEST_NONFATAL_FAILURE_)
+
+/**
+ * Check that the given statement throws an exception of the given type,
+ * and that the thrown exception message contains the given substring.
+ */
+#define ASSERT_THROW_MESSAGE_HAS_SUBSTR(statement, expectedException, substring) \
+ _Y_GTEST_EXPECT_THROW_MESSAGE_HAS_SUBSTR_IMPL_(statement, expectedException, substring, GTEST_FATAL_FAILURE_)
+
+
+// Improve default macros. New implementation shows better exception messages.
+// See https://github.com/google/googletest/issues/2878
+
+#undef EXPECT_THROW
+#define EXPECT_THROW(statement, expectedException) \
+ _Y_GTEST_EXPECT_THROW_IMPL_(statement, expectedException, GTEST_NONFATAL_FAILURE_)
+
+#undef ASSERT_THROW
+#define ASSERT_THROW(statement, expectedException) \
+ _Y_GTEST_EXPECT_THROW_IMPL_(statement, expectedException, GTEST_FATAL_FAILURE_)
+
+#undef EXPECT_NO_THROW
+#define EXPECT_NO_THROW(statement) \
+ _Y_GTEST_EXPECT_NO_THROW_IMPL_(statement, GTEST_NONFATAL_FAILURE_)
+
+#undef ASSERT_NO_THROW
+#define ASSERT_NO_THROW(statement) \
+ _Y_GTEST_EXPECT_NO_THROW_IMPL_(statement, GTEST_FATAL_FAILURE_)
+
+
+// Implementation details
+
+namespace NGTest::NInternal {
+ TString FormatErrorWrongException(const char* statement, const char* type);
+ TString FormatErrorWrongException(const char* statement, const char* type, TString contains);
+ TString FormatErrorUnexpectedException(const char* statement);
+ bool ExceptionMessageContains(const std::exception& err, TString contains);
+}
+
+#define _Y_GTEST_EXPECT_THROW_IMPL_(statement, expectedException, fail) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (::TString gtestMsg = ""; ::testing::internal::AlwaysTrue()) { \
+ bool gtestCaughtExpected = false; \
+ try { \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ } catch (expectedException const&) { \
+ gtestCaughtExpected = true; \
+ } catch (...) { \
+ gtestMsg = ::NGTest::NInternal::FormatErrorWrongException( \
+ #statement, #expectedException); \
+ goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
+ } if (!gtestCaughtExpected) { \
+ gtestMsg = ::NGTest::NInternal::FormatErrorWrongException( \
+ #statement, #expectedException); \
+ goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
+ } \
+ } else \
+ GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
+ fail(gtestMsg.c_str())
+
+#define _Y_GTEST_EXPECT_THROW_MESSAGE_HAS_SUBSTR_IMPL_(statement, expectedException, substring, fail) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (::TString gtestMsg = ""; ::testing::internal::AlwaysTrue()) { \
+ bool gtestCaughtExpected = false; \
+ ::TString gtestSubstring{substring}; \
+ try { \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ } catch (expectedException const& gtestError) { \
+ if (!::NGTest::NInternal::ExceptionMessageContains(gtestError, gtestSubstring)) { \
+ gtestMsg = ::NGTest::NInternal::FormatErrorWrongException( \
+ #statement, #expectedException, gtestSubstring); \
+ goto GTEST_CONCAT_TOKEN_(gtest_label_testthrowsubstr_, __LINE__); \
+ } \
+ gtestCaughtExpected = true; \
+ } catch (...) { \
+ gtestMsg = ::NGTest::NInternal::FormatErrorWrongException( \
+ #statement, #expectedException, gtestSubstring); \
+ goto GTEST_CONCAT_TOKEN_(gtest_label_testthrowsubstr_, __LINE__); \
+ } if (!gtestCaughtExpected) { \
+ gtestMsg = ::NGTest::NInternal::FormatErrorWrongException( \
+ #statement, #expectedException, gtestSubstring); \
+ goto GTEST_CONCAT_TOKEN_(gtest_label_testthrowsubstr_, __LINE__); \
+ } \
+ } else \
+ GTEST_CONCAT_TOKEN_(gtest_label_testthrowsubstr_, __LINE__): \
+ fail(gtestMsg.c_str())
+
+#define _Y_GTEST_EXPECT_NO_THROW_IMPL_(statement, fail) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (::TString gtestMsg = ""; ::testing::internal::AlwaysTrue()) { \
+ try { \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ } catch (...) { \
+ gtestMsg = ::NGTest::NInternal::FormatErrorUnexpectedException(#statement); \
+ goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
+ } \
+ } else \
+ GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \
+ fail(gtestMsg.c_str())