summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2018-04-23 13:40:09 -0400
committerBenety Goh <benety@mongodb.com>2018-04-23 13:41:42 -0400
commitfc8096229e6ba7745431f77ec985eb65ee0541af (patch)
tree454f2cb064ddd4602d408a257aa37932235d2292
parentdba852d5d9cd0b3f067fd8d880e7e576db580653 (diff)
downloadmongo-fc8096229e6ba7745431f77ec985eb65ee0541af.tar.gz
SERVER-34364 add Status and StatusWith support to invariant()
-rw-r--r--src/mongo/util/assert_util.cpp21
-rw-r--r--src/mongo/util/assert_util.h49
-rw-r--r--src/mongo/util/assert_util_test.cpp42
-rw-r--r--src/mongo/util/invariant.h43
4 files changed, 130 insertions, 25 deletions
diff --git a/src/mongo/util/assert_util.cpp b/src/mongo/util/assert_util.cpp
index 7fda800f414..7ff79f092e0 100644
--- a/src/mongo/util/assert_util.cpp
+++ b/src/mongo/util/assert_util.cpp
@@ -106,7 +106,7 @@ NOINLINE_DECL void invariantFailed(const char* expr, const char* file, unsigned
}
NOINLINE_DECL void invariantFailedWithMsg(const char* expr,
- const char* msg,
+ const std::string& msg,
const char* file,
unsigned line) noexcept {
severe() << "Invariant failure " << expr << " " << msg << " " << file << ' ' << dec << line
@@ -116,13 +116,6 @@ NOINLINE_DECL void invariantFailedWithMsg(const char* expr,
std::abort();
}
-NOINLINE_DECL void invariantFailedWithMsg(const char* expr,
- const std::string& msg,
- const char* file,
- unsigned line) noexcept {
- invariantFailedWithMsg(expr, msg.c_str(), file, line);
-}
-
NOINLINE_DECL void invariantOKFailed(const char* expr,
const Status& status,
const char* file,
@@ -134,6 +127,18 @@ NOINLINE_DECL void invariantOKFailed(const char* expr,
std::abort();
}
+NOINLINE_DECL void invariantOKFailedWithMsg(const char* expr,
+ const Status& status,
+ const std::string& msg,
+ const char* file,
+ unsigned line) noexcept {
+ severe() << "Invariant failure: " << expr << " " << msg << " resulted in status "
+ << redact(status) << " at " << file << ' ' << dec << line;
+ breakpoint();
+ severe() << "\n\n***aborting after invariant() failure\n\n" << endl;
+ std::abort();
+}
+
NOINLINE_DECL void fassertFailedWithLocation(int msgid, const char* file, unsigned line) noexcept {
severe() << "Fatal Assertion " << msgid << " at " << file << " " << dec << line;
breakpoint();
diff --git a/src/mongo/util/assert_util.h b/src/mongo/util/assert_util.h
index 0859738392e..b3d91d71238 100644
--- a/src/mongo/util/assert_util.h
+++ b/src/mongo/util/assert_util.h
@@ -220,6 +220,11 @@ MONGO_COMPILER_NORETURN void invariantOKFailed(const char* expr,
const Status& status,
const char* file,
unsigned line) noexcept;
+MONGO_COMPILER_NORETURN void invariantOKFailedWithMsg(const char* expr,
+ const Status& status,
+ const std::string& msg,
+ const char* file,
+ unsigned line) noexcept;
#define fassertFailed MONGO_fassertFailed
#define MONGO_fassertFailed(...) ::mongo::fassertFailedWithLocation(__VA_ARGS__, __FILE__, __LINE__)
@@ -449,6 +454,50 @@ inline void massertStatusOKWithLocation(const Status& status, const char* file,
if (kDebugBuild) \
invariantOK(expression)
+inline void invariantWithLocation(const Status& status,
+ const char* expr,
+ const char* file,
+ unsigned line) {
+ if (MONGO_unlikely(!status.isOK())) {
+ ::mongo::invariantOKFailed(expr, status, file, line);
+ }
+}
+
+template <typename T>
+inline T invariantWithLocation(StatusWith<T> sw,
+ const char* expr,
+ const char* file,
+ unsigned line) {
+ if (MONGO_unlikely(!sw.isOK())) {
+ ::mongo::invariantOKFailed(expr, sw.getStatus(), file, line);
+ }
+ return std::move(sw.getValue());
+}
+
+template <typename ContextExpr>
+inline void invariantWithContextAndLocation(const Status& status,
+ const char* expr,
+ ContextExpr&& contextExpr,
+ const char* file,
+ unsigned line) {
+ if (MONGO_unlikely(!status.isOK())) {
+ ::mongo::invariantOKFailedWithMsg(
+ expr, status, std::forward<ContextExpr>(contextExpr)(), file, line);
+ }
+}
+
+template <typename T, typename ContextExpr>
+inline T invariantWithContextAndLocation(StatusWith<T> sw,
+ const char* expr,
+ ContextExpr&& contextExpr,
+ const char* file,
+ unsigned line) {
+ if (MONGO_unlikely(!sw.isOK())) {
+ ::mongo::invariantOKFailedWithMsg(expr, sw.getStatus(), contextExpr(), file, line);
+ }
+ return std::move(sw.getValue());
+}
+
// some special ids that we want to duplicate
// > 10000 asserts
diff --git a/src/mongo/util/assert_util_test.cpp b/src/mongo/util/assert_util_test.cpp
index b4c3c4ab212..1405319e26e 100644
--- a/src/mongo/util/assert_util_test.cpp
+++ b/src/mongo/util/assert_util_test.cpp
@@ -290,6 +290,15 @@ DEATH_TEST(InvariantTerminationTest, invariant, "Invariant failure false " __FIL
invariant(false);
}
+DEATH_TEST(InvariantTerminationTest, invariantOverload, "Terminating with invariant") {
+ invariant(Status(ErrorCodes::InternalError, "Terminating with invariant"));
+}
+
+DEATH_TEST(InvariantTerminationTest, invariantStatusWithOverload, "Terminating with invariant") {
+ invariant(StatusWith<std::string>(ErrorCodes::InternalError,
+ "Terminating with invariantStatusWithOverload"));
+}
+
DEATH_TEST(InvariantTerminationTest, invariantOK, "Terminating with invariantOK") {
invariantOK(Status(ErrorCodes::InternalError, "Terminating with invariantOK"));
}
@@ -309,5 +318,38 @@ DEATH_TEST(InvariantTerminationTest,
invariant(false, msg);
}
+
+DEATH_TEST(InvariantTerminationTest,
+ invariantOverloadWithStringLiteralMsg,
+ "Terminating with string literal invariant message") {
+ invariant(Status(ErrorCodes::InternalError, "Terminating with invariant"),
+ "Terminating with string literal invariant message");
+}
+
+DEATH_TEST(InvariantTerminationTest,
+ invariantOverloadWithStdStringMsg,
+ "Terminating with std::string invariant message: 12345") {
+ const std::string msg = str::stream() << "Terminating with std::string invariant message: "
+ << 12345;
+ invariant(Status(ErrorCodes::InternalError, "Terminating with invariant"), msg);
+}
+
+DEATH_TEST(InvariantTerminationTest,
+ invariantStatusWithOverloadWithStringLiteralMsg,
+ "Terminating with string literal invariant message") {
+ invariant(StatusWith<std::string>(ErrorCodes::InternalError, "Terminating with invariant"),
+ "Terminating with string literal invariant message");
+}
+
+DEATH_TEST(InvariantTerminationTest,
+ invariantStatusWithOverloadWithStdStringMsg,
+ "Terminating with std::string invariant message: 12345") {
+ const std::string msg = str::stream() << "Terminating with std::string invariant message: "
+ << 12345;
+ invariant(StatusWith<std::string>(ErrorCodes::InternalError, "Terminating with invariant"),
+ msg);
+}
+
+
} // namespace
} // namespace mongo
diff --git a/src/mongo/util/invariant.h b/src/mongo/util/invariant.h
index edd2f210ce2..587eeb24f17 100644
--- a/src/mongo/util/invariant.h
+++ b/src/mongo/util/invariant.h
@@ -55,17 +55,18 @@ MONGO_COMPILER_NORETURN void invariantFailed(const char* expr,
//
// Invariant failure !condition some/file.cpp 528
//
-#define MONGO_invariant_1(_Expression) \
- do { \
- if (MONGO_unlikely(!(_Expression))) { \
- ::mongo::invariantFailed(#_Expression, __FILE__, __LINE__); \
- } \
- } while (false)
-
-MONGO_COMPILER_NORETURN void invariantFailedWithMsg(const char* expr,
- const char* msg,
- const char* file,
- unsigned line) noexcept;
+#define MONGO_invariant_1(Expression) \
+ ::mongo::invariantWithLocation((Expression), #Expression, __FILE__, __LINE__)
+
+template <typename T>
+inline void invariantWithLocation(const T& testOK,
+ const char* expr,
+ const char* file,
+ unsigned line) {
+ if (MONGO_unlikely(!testOK)) {
+ ::mongo::invariantFailed(expr, file, line);
+ }
+}
MONGO_COMPILER_NORETURN void invariantFailedWithMsg(const char* expr,
const std::string& msg,
@@ -79,12 +80,20 @@ MONGO_COMPILER_NORETURN void invariantFailedWithMsg(const char* expr,
//
// Invariant failure !condition "hello!" some/file.cpp 528
//
-#define MONGO_invariant_2(_Expression, _Message) \
- do { \
- if (MONGO_unlikely(!(_Expression))) { \
- ::mongo::invariantFailedWithMsg(#_Expression, (_Message), __FILE__, __LINE__); \
- } \
- } while (false)
+#define MONGO_invariant_2(Expression, contextExpr) \
+ ::mongo::invariantWithContextAndLocation((Expression), \
+ #Expression, \
+ [&]() -> std::string { return (contextExpr); }, \
+ __FILE__, \
+ __LINE__)
+
+template <typename T, typename ContextExpr>
+inline void invariantWithContextAndLocation(
+ const T& testOK, const char* expr, ContextExpr&& contextExpr, const char* file, unsigned line) {
+ if (MONGO_unlikely(!testOK)) {
+ ::mongo::invariantFailedWithMsg(expr, contextExpr(), file, line);
+ }
+}
// This helper macro is necessary to make the __VAR_ARGS__ expansion work properly on MSVC.
#define MONGO_expand(x) x