diff --git a/source/common/common/assert.h b/source/common/common/assert.h index 9d4f4c5275215..3654a160df2ce 100644 --- a/source/common/common/assert.h +++ b/source/common/common/assert.h @@ -29,11 +29,19 @@ namespace Envoy { } while (false) #ifndef NDEBUG -#define ASSERT(X) RELEASE_ASSERT(X, "") +#define _ASSERT_ORIGINAL(X) RELEASE_ASSERT(X, "") +#define _ASSERT_VERBOSE(X, Y) RELEASE_ASSERT(X, Y) +#define _ASSERT_SELECTOR(_1, _2, ASSERT_MACRO, ...) ASSERT_MACRO + +// If ASSERT is called with one argument, the ASSERT_SELECTOR will return +// _ASSERT_ORIGINAL and this will call _ASSERT_ORIGINAL(__VA_ARGS__). +// If ASSERT is called with two arguments, ASSERT_SELECTOR will return +// _ASSERT_VERBOSE, and this will call _ASSERT_VERBOSE,(__VA_ARGS__) +#define ASSERT(...) _ASSERT_SELECTOR(__VA_ARGS__, _ASSERT_VERBOSE, _ASSERT_ORIGINAL)(__VA_ARGS__) #else // This non-implementation ensures that its argument is a valid expression that can be statically // casted to a bool, but the expression is never evaluated and will be compiled away. -#define ASSERT(X) \ +#define ASSERT(X, ...) \ do { \ constexpr bool __assert_dummy_variable = false && static_cast(X); \ (void)__assert_dummy_variable; \ diff --git a/source/common/network/connection_impl.cc b/source/common/network/connection_impl.cc index b08c483ca8a7b..935075e1c16ab 100644 --- a/source/common/network/connection_impl.cc +++ b/source/common/network/connection_impl.cc @@ -504,7 +504,9 @@ void ConnectionImpl::onWriteReady() { } void ConnectionImpl::setConnectionStats(const ConnectionStats& stats) { - ASSERT(!connection_stats_); + ASSERT(!connection_stats_, + "Two network filters are attempting to set connection stats. This indicates an issue " + "with the configured filter chain."); connection_stats_.reset(new ConnectionStats(stats)); } diff --git a/test/common/common/assert_test.cc b/test/common/common/assert_test.cc index 49f3c8d7d748b..9143b1a6391e7 100644 --- a/test/common/common/assert_test.cc +++ b/test/common/common/assert_test.cc @@ -4,7 +4,7 @@ namespace Envoy { -TEST(Assert, VariousLogs) { +TEST(ReleaseAssert, VariousLogs) { Logger::StderrSinkDelegate stderr_sink(Logger::Registry::getSink()); // For coverage build. EXPECT_DEATH({ RELEASE_ASSERT(0, ""); }, ".*assert failure: 0.*"); EXPECT_DEATH({ RELEASE_ASSERT(0, "With some logs"); }, @@ -13,4 +13,16 @@ TEST(Assert, VariousLogs) { ".*assert failure: 0 == EAGAIN. Details: using fmt.*"); } +TEST(Assert, VariousLogs) { +#ifndef NDEBUG + EXPECT_DEATH({ ASSERT(0); }, ".*assert failure: 0.*"); + EXPECT_DEATH({ ASSERT(0, ""); }, ".*assert failure: 0.*"); + EXPECT_DEATH({ ASSERT(0, "With some logs"); }, ".*assert failure: 0. Details: With some logs.*"); +#else + ASSERT(0); + ASSERT(0, ""); + ASSERT(0, "With some logs"); +#endif +} + } // namespace Envoy