Index: base/logging_unittest.cc |
diff --git a/base/logging_unittest.cc b/base/logging_unittest.cc |
index f41cce2f43b390fa9603a14f3f689fe87d0dcb33..6a18a109ff71efe6f530491786696e56d984d4fe 100644 |
--- a/base/logging_unittest.cc |
+++ b/base/logging_unittest.cc |
@@ -3,6 +3,7 @@ |
// found in the LICENSE file. |
#include "base/compiler_specific.h" |
+#include "base/debug/dump_without_crashing.h" |
#include "base/logging.h" |
#include "base/macros.h" |
@@ -16,11 +17,11 @@ namespace { |
using ::testing::Return; |
// Needs to be global since log assert handlers can't maintain state. |
-int log_sink_call_count = 0; |
+int g_log_sink_call_count = 0; |
#if !defined(OFFICIAL_BUILD) || defined(DCHECK_ALWAYS_ON) || !defined(NDEBUG) |
void LogSink(const std::string& str) { |
- ++log_sink_call_count; |
+ ++g_log_sink_call_count; |
} |
#endif |
@@ -33,7 +34,7 @@ class LogStateSaver { |
~LogStateSaver() { |
SetMinLogLevel(old_min_log_level_); |
SetLogAssertHandler(NULL); |
- log_sink_call_count = 0; |
+ g_log_sink_call_count = 0; |
} |
private: |
@@ -86,10 +87,12 @@ TEST_F(LoggingTest, BasicLogging) { |
} |
TEST_F(LoggingTest, LogIsOn) { |
-#if defined(NDEBUG) |
- const bool kDfatalIsFatal = false; |
+#if defined(DCHECK_IS_DUMP_WITHOUT_CRASH) |
+ const bool kDfatalIsActive = true; |
+#elif defined(NDEBUG) |
+ const bool kDfatalIsActive = false; |
#else // defined(NDEBUG) |
- const bool kDfatalIsFatal = true; |
+ const bool kDfatalIsActive = true; |
#endif // defined(NDEBUG) |
SetMinLogLevel(LOG_INFO); |
@@ -119,7 +122,9 @@ TEST_F(LoggingTest, LogIsOn) { |
EXPECT_FALSE(LOG_IS_ON(WARNING)); |
EXPECT_FALSE(LOG_IS_ON(ERROR)); |
EXPECT_TRUE(LOG_IS_ON(FATAL)); |
- EXPECT_TRUE(kDfatalIsFatal == LOG_IS_ON(DFATAL)); |
+ EXPECT_EQ(kDfatalIsActive, LOG_IS_ON(DFATAL)); |
+ |
+ EXPECT_EQ(DCHECK_IS_ON() != 0, LOG_IS_ON(DCHECK)); |
} |
TEST_F(LoggingTest, LoggingIsLazyBySeverity) { |
@@ -191,7 +196,7 @@ TEST_F(LoggingTest, CheckStreamsAreLazy) { |
#endif |
TEST_F(LoggingTest, DebugLoggingReleaseBehavior) { |
-#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) |
+#if DCHECK_IS_ON() |
int debug_only_variable = 1; |
#endif |
// These should avoid emitting references to |debug_only_variable| |
@@ -217,6 +222,7 @@ TEST_F(LoggingTest, DcheckStreamsAreLazy) { |
#endif |
} |
+#if !defined(DCHECK_IS_DUMP_WITHOUT_CRASH) |
void DcheckEmptyFunction1() { |
// Provide a body so that Release builds do not cause the compiler to |
// optimize DcheckEmptyFunction1 and DcheckEmptyFunction2 as a single |
@@ -242,33 +248,33 @@ TEST_F(LoggingTest, Dcheck) { |
EXPECT_TRUE(DLOG_IS_ON(DCHECK)); |
#endif |
- EXPECT_EQ(0, log_sink_call_count); |
+ EXPECT_EQ(0, g_log_sink_call_count); |
DCHECK(false); |
- EXPECT_EQ(DCHECK_IS_ON() ? 1 : 0, log_sink_call_count); |
+ EXPECT_EQ(DCHECK_IS_ON() ? 1 : 0, g_log_sink_call_count); |
DPCHECK(false); |
- EXPECT_EQ(DCHECK_IS_ON() ? 2 : 0, log_sink_call_count); |
+ EXPECT_EQ(DCHECK_IS_ON() ? 2 : 0, g_log_sink_call_count); |
DCHECK_EQ(0, 1); |
- EXPECT_EQ(DCHECK_IS_ON() ? 3 : 0, log_sink_call_count); |
+ EXPECT_EQ(DCHECK_IS_ON() ? 3 : 0, g_log_sink_call_count); |
// Test DCHECK on std::nullptr_t |
- log_sink_call_count = 0; |
+ g_log_sink_call_count = 0; |
const void* p_null = nullptr; |
const void* p_not_null = &p_null; |
DCHECK_EQ(p_null, nullptr); |
DCHECK_EQ(nullptr, p_null); |
DCHECK_NE(p_not_null, nullptr); |
DCHECK_NE(nullptr, p_not_null); |
- EXPECT_EQ(0, log_sink_call_count); |
+ EXPECT_EQ(0, g_log_sink_call_count); |
// Test DCHECK on a scoped enum. |
enum class Animal { DOG, CAT }; |
DCHECK_EQ(Animal::DOG, Animal::DOG); |
- EXPECT_EQ(0, log_sink_call_count); |
+ EXPECT_EQ(0, g_log_sink_call_count); |
DCHECK_EQ(Animal::DOG, Animal::CAT); |
- EXPECT_EQ(DCHECK_IS_ON() ? 1 : 0, log_sink_call_count); |
+ EXPECT_EQ(DCHECK_IS_ON() ? 1 : 0, g_log_sink_call_count); |
// Test DCHECK on functions and function pointers. |
- log_sink_call_count = 0; |
+ g_log_sink_call_count = 0; |
struct MemberFunctions { |
void MemberFunction1() { |
// See the comment in DcheckEmptyFunction1(). |
@@ -282,16 +288,17 @@ TEST_F(LoggingTest, Dcheck) { |
void (*fp2)() = DcheckEmptyFunction2; |
void (*fp3)() = DcheckEmptyFunction1; |
DCHECK_EQ(fp1, fp3); |
- EXPECT_EQ(0, log_sink_call_count); |
+ EXPECT_EQ(0, g_log_sink_call_count); |
DCHECK_EQ(mp1, &MemberFunctions::MemberFunction1); |
- EXPECT_EQ(0, log_sink_call_count); |
+ EXPECT_EQ(0, g_log_sink_call_count); |
DCHECK_EQ(mp2, &MemberFunctions::MemberFunction2); |
- EXPECT_EQ(0, log_sink_call_count); |
+ EXPECT_EQ(0, g_log_sink_call_count); |
DCHECK_EQ(fp1, fp2); |
- EXPECT_EQ(DCHECK_IS_ON() ? 1 : 0, log_sink_call_count); |
+ EXPECT_EQ(DCHECK_IS_ON() ? 1 : 0, g_log_sink_call_count); |
DCHECK_EQ(mp2, &MemberFunctions::MemberFunction1); |
- EXPECT_EQ(DCHECK_IS_ON() ? 2 : 0, log_sink_call_count); |
+ EXPECT_EQ(DCHECK_IS_ON() ? 2 : 0, g_log_sink_call_count); |
} |
+#endif // !defined(DCHECK_IS_DUMP_WITHOUT_CRASH) |
TEST_F(LoggingTest, DcheckReleaseBehavior) { |
int some_variable = 1; |
@@ -326,6 +333,37 @@ TEST_F(LoggingTest, CheckEqStatements) { |
CHECK_EQ(false, true); // Unreached. |
} |
+namespace { |
+ |
+int g_fake_dump_without_crashing_count = 0; |
+void FakeDumpWithoutCrashing() { |
+ g_fake_dump_without_crashing_count++; |
+} |
+ |
+} // namespace |
+ |
+TEST_F(LoggingTest, LogMessageDump) { |
+ // Replace the dump-without-crashing function, to test. |
+ base::debug::SetDumpWithoutCrashingFunction(&FakeDumpWithoutCrashing); |
+ |
+ // LOG_DUMP is an internal severity level for use by dump-on-DCHECK, so |
+ // we must call LogMessage() directly, rather than using LOG(DUMP). |
+ LogMessage(__FILE__, __LINE__, LOG_DUMP, new std::string); |
+ EXPECT_EQ(1, g_fake_dump_without_crashing_count); |
+ LogMessage(__FILE__, __LINE__, LOG_DUMP, new std::string); |
+ EXPECT_EQ(1, g_fake_dump_without_crashing_count); |
+ |
+#if defined(DCHECK_IS_DUMP_WITHOUT_CRASH) |
+ EXPECT_EQ(LOG_DUMP, LOG_DFATAL); |
+ EXPECT_EQ(LOG_DUMP, LOG_DCHECK); |
+#else // defined(DCHECK_IS_DUMP_WITHOUT_CRASH) |
+ EXPECT_NE(LOG_DUMP, LOG_DFATAL); |
+ EXPECT_NE(LOG_DUMP, LOG_DCHECK); |
+#endif // defined(DCHECK_IS_DUMP_WITHOUT_CRASH) |
+ |
+ base::debug::SetDumpWithoutCrashingFunction(nullptr); |
+} |
+ |
// Test that defining an operator<< for a type in a namespace doesn't prevent |
// other code in that namespace from calling the operator<<(ostream, wstring) |
// defined by logging.h. This can fail if operator<<(ostream, wstring) can't be |