summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmirsaman Memaripour <amirsaman.memaripour@mongodb.com>2020-06-18 19:07:17 +0000
committerAmirsaman Memaripour <amirsaman.memaripour@mongodb.com>2020-06-25 18:27:55 +0000
commite0a5a83e6f24553441707a53c7a5305fd4723419 (patch)
tree89c7adff55bdd0306b064d9ed8de5213ea8b1968
parentf4273b8a9d14ed989477748cd46d51eaccf65140 (diff)
downloadmongo-e0a5a83e6f24553441707a53c7a5305fd4723419.tar.gz
SERVER-48922 Create internal assertion macro
(cherry picked from commit 8f4f4741ad6711896caa78fbd0486e2da00e25e4)
-rw-r--r--src/mongo/platform/source_location.h1
-rw-r--r--src/mongo/util/assert_util.cpp7
-rw-r--r--src/mongo/util/assert_util.h36
-rw-r--r--src/mongo/util/assert_util_test.cpp39
-rw-r--r--src/mongo/util/interruptible.h4
5 files changed, 85 insertions, 2 deletions
diff --git a/src/mongo/platform/source_location.h b/src/mongo/platform/source_location.h
index 3d9830ec97b..1909ab1c436 100644
--- a/src/mongo/platform/source_location.h
+++ b/src/mongo/platform/source_location.h
@@ -30,6 +30,7 @@
#pragma once
#include <cstdint>
+#include <ostream>
#include <string>
#if !defined(_MSC_VER) && !defined(__clang__) // not windows or clang
diff --git a/src/mongo/util/assert_util.cpp b/src/mongo/util/assert_util.cpp
index cc52a6f1d13..d1e9281f490 100644
--- a/src/mongo/util/assert_util.cpp
+++ b/src/mongo/util/assert_util.cpp
@@ -269,6 +269,13 @@ MONGO_COMPILER_NOINLINE void msgassertedWithLocation(const Status& status,
error_details::throwExceptionForStatus(status);
}
+void internalAssertWithLocation(SourceLocationHolder loc, const Status& status) {
+ if (status.isOK())
+ return;
+ LOGV2_DEBUG(4892201, 3, "Internal assertion", "error"_attr = status, "location"_attr = loc);
+ error_details::throwExceptionForStatus(status);
+}
+
std::string causedBy(StringData e) {
constexpr auto prefix = " :: caused by :: "_sd;
std::string out;
diff --git a/src/mongo/util/assert_util.h b/src/mongo/util/assert_util.h
index 44ac167c33f..f1e54d2a7ce 100644
--- a/src/mongo/util/assert_util.h
+++ b/src/mongo/util/assert_util.h
@@ -36,6 +36,7 @@
#include "mongo/base/status.h" // NOTE: This is safe as utils depend on base
#include "mongo/base/status_with.h"
#include "mongo/platform/compiler.h"
+#include "mongo/platform/source_location.h"
#include "mongo/util/concurrency/thread_name.h"
#include "mongo/util/debug_util.h"
@@ -436,6 +437,41 @@ inline void massertStatusOKWithLocation(const Status& status, const char* file,
}
/**
+ * `internalAssert` is provided as an alternative for `uassert` variants (e.g., `uassertStatusOK`)
+ * to support cases where we expect a failure, the failure is recoverable, or accounting for the
+ * failure, updating assertion counters, isn't desired. `internalAssert` logs at D3 instead of D1,
+ * which helps with reducing the noise of assertions in production. The goal is to keep one
+ * interface (i.e., `internalAssert(...)`) for all possible assertion variants, and use function
+ * overloading to expand type support as needed.
+ */
+#define internalAssert(...) \
+ ::mongo::internalAssertWithLocation(MONGO_SOURCE_LOCATION(), __VA_ARGS__)
+
+void internalAssertWithLocation(SourceLocationHolder loc, const Status& status);
+
+inline void internalAssertWithLocation(SourceLocationHolder loc, Status&& status) {
+ internalAssertWithLocation(std::move(loc), status);
+}
+
+inline void internalAssertWithLocation(SourceLocationHolder loc,
+ int msgid,
+ const std::string& msg,
+ bool expr) {
+ if (MONGO_unlikely(!expr))
+ internalAssertWithLocation(std::move(loc), Status(ErrorCodes::Error(msgid), msg));
+}
+
+template <typename T>
+inline void internalAssertWithLocation(SourceLocationHolder loc, const StatusWith<T>& sw) {
+ internalAssertWithLocation(std::move(loc), sw.getStatus());
+}
+
+template <typename T>
+inline void internalAssertWithLocation(SourceLocationHolder loc, StatusWith<T>&& sw) {
+ internalAssertWithLocation(std::move(loc), sw);
+}
+
+/**
* verify is deprecated. It is like invariant() in debug builds and massert() in release builds.
*/
#define verify(expression) MONGO_verify(expression)
diff --git a/src/mongo/util/assert_util_test.cpp b/src/mongo/util/assert_util_test.cpp
index 07367a80a7a..4275d8a907e 100644
--- a/src/mongo/util/assert_util_test.cpp
+++ b/src/mongo/util/assert_util_test.cpp
@@ -212,6 +212,45 @@ TEST(AssertUtils, UassertTypedExtraInfoWorks) {
}
}
+TEST(AssertUtils, UassertIncrementsUserAssertionCounter) {
+ auto userAssertions = assertionCount.user.load();
+ auto asserted = false;
+ try {
+ Status status = {ErrorCodes::BadValue, "Test"};
+ uassertStatusOK(status);
+ } catch (const DBException&) {
+ asserted = true;
+ }
+ ASSERT(asserted);
+ ASSERT_EQ(userAssertions + 1, assertionCount.user.load());
+}
+
+TEST(AssertUtils, InternalAssertWithStatus) {
+ auto userAssertions = assertionCount.user.load();
+ try {
+ Status status = {ErrorCodes::BadValue, "Test"};
+ internalAssert(status);
+ } catch (const DBException& ex) {
+ ASSERT_EQ(ex.code(), ErrorCodes::BadValue);
+ ASSERT_EQ(ex.reason(), "Test");
+ }
+ ASSERT_EQ(userAssertions, assertionCount.user.load());
+}
+
+TEST(AssertUtils, InternalAssertWithExpression) {
+ auto userAssertions = assertionCount.user.load();
+ try {
+ internalAssert(48922, "Test", false);
+ } catch (const DBException& ex) {
+ ASSERT_EQ(ex.code(), 48922);
+ ASSERT_EQ(ex.reason(), "Test");
+ }
+
+ internalAssert(48922, "Another test", true);
+
+ ASSERT_EQ(userAssertions, assertionCount.user.load());
+}
+
TEST(AssertUtils, MassertTypedExtraInfoWorks) {
try {
msgasserted(ErrorExtraInfoExample(123), "");
diff --git a/src/mongo/util/interruptible.h b/src/mongo/util/interruptible.h
index 364a3927f0d..5b14c29bcc1 100644
--- a/src/mongo/util/interruptible.h
+++ b/src/mongo/util/interruptible.h
@@ -317,7 +317,7 @@ public:
* Raises a AssertionException if this operation is in a killed state.
*/
void checkForInterrupt() {
- uassertStatusOK(checkForInterruptNoAssert());
+ internalAssert(checkForInterruptNoAssert());
}
/**
@@ -395,7 +395,7 @@ public:
if (!swResult.isOK()) {
_onWake(latchName, WakeReason::kInterrupt, speed);
- uassertStatusOK(std::move(swResult));
+ internalAssert(std::move(swResult));
}
if (pred()) {