1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/logging.h" 6 7 #include <gmock/gmock.h> 8 #include <gtest/gtest.h> 9 10 #include "base/compiler_specific.h" 11 #include "base/macros.h" 12 13 namespace logging { 14 15 namespace { 16 17 using ::testing::Return; 18 19 // Needs to be global since log assert handlers can't maintain state. 20 int log_sink_call_count = 0; 21 22 #if !defined(OFFICIAL_BUILD) || defined(DCHECK_ALWAYS_ON) || !defined(NDEBUG) 23 void LogSink(const std::string& str) { 24 ++log_sink_call_count; 25 } 26 #endif 27 28 // Class to make sure any manipulations we do to the min log level are 29 // contained (i.e., do not affect other unit tests). 30 class LogStateSaver { 31 public: 32 LogStateSaver() : old_min_log_level_(GetMinLogLevel()) {} 33 34 ~LogStateSaver() { 35 SetMinLogLevel(old_min_log_level_); 36 SetLogAssertHandler(NULL); 37 log_sink_call_count = 0; 38 } 39 40 private: 41 int old_min_log_level_; 42 43 DISALLOW_COPY_AND_ASSIGN(LogStateSaver); 44 }; 45 46 class LoggingTest : public testing::Test { 47 private: 48 LogStateSaver log_state_saver_; 49 }; 50 51 class MockLogSource { 52 public: 53 MOCK_METHOD0(Log, const char*()); 54 }; 55 56 TEST_F(LoggingTest, BasicLogging) { 57 MockLogSource mock_log_source; 58 EXPECT_CALL(mock_log_source, Log()). 59 WillRepeatedly(Return("log message")); 60 61 SetMinLogLevel(LOG_INFO); 62 63 EXPECT_TRUE(LOG_IS_ON(INFO)); 64 // As of g++-4.5, the first argument to EXPECT_EQ cannot be a 65 // constant expression. 66 const bool kIsDebugMode = (DEBUG_MODE != 0); 67 EXPECT_TRUE(kIsDebugMode == DLOG_IS_ON(INFO)); 68 EXPECT_TRUE(VLOG_IS_ON(0)); 69 70 LOG(INFO) << mock_log_source.Log(); 71 LOG_IF(INFO, true) << mock_log_source.Log(); 72 VLOG(0) << mock_log_source.Log(); 73 VLOG_IF(0, true) << mock_log_source.Log(); 74 75 DLOG(INFO) << mock_log_source.Log(); 76 DLOG_IF(INFO, true) << mock_log_source.Log(); 77 DVLOG(0) << mock_log_source.Log(); 78 DVLOG_IF(0, true) << mock_log_source.Log(); 79 } 80 81 TEST_F(LoggingTest, LogIsOn) { 82 #if defined(NDEBUG) 83 const bool kDfatalIsFatal = false; 84 #else // defined(NDEBUG) 85 const bool kDfatalIsFatal = true; 86 #endif // defined(NDEBUG) 87 88 SetMinLogLevel(LOG_INFO); 89 EXPECT_TRUE(LOG_IS_ON(INFO)); 90 EXPECT_TRUE(LOG_IS_ON(WARNING)); 91 EXPECT_TRUE(LOG_IS_ON(ERROR)); 92 EXPECT_TRUE(LOG_IS_ON(FATAL)); 93 EXPECT_TRUE(LOG_IS_ON(DFATAL)); 94 95 SetMinLogLevel(LOG_WARNING); 96 EXPECT_FALSE(LOG_IS_ON(INFO)); 97 EXPECT_TRUE(LOG_IS_ON(WARNING)); 98 EXPECT_TRUE(LOG_IS_ON(ERROR)); 99 EXPECT_TRUE(LOG_IS_ON(FATAL)); 100 EXPECT_TRUE(LOG_IS_ON(DFATAL)); 101 102 SetMinLogLevel(LOG_ERROR); 103 EXPECT_FALSE(LOG_IS_ON(INFO)); 104 EXPECT_FALSE(LOG_IS_ON(WARNING)); 105 EXPECT_TRUE(LOG_IS_ON(ERROR)); 106 EXPECT_TRUE(LOG_IS_ON(FATAL)); 107 EXPECT_TRUE(LOG_IS_ON(DFATAL)); 108 109 // LOG_IS_ON(FATAL) should always be true. 110 SetMinLogLevel(LOG_FATAL + 1); 111 EXPECT_FALSE(LOG_IS_ON(INFO)); 112 EXPECT_FALSE(LOG_IS_ON(WARNING)); 113 EXPECT_FALSE(LOG_IS_ON(ERROR)); 114 EXPECT_TRUE(LOG_IS_ON(FATAL)); 115 EXPECT_TRUE(kDfatalIsFatal == LOG_IS_ON(DFATAL)); 116 } 117 118 TEST_F(LoggingTest, LoggingIsLazyBySeverity) { 119 MockLogSource mock_log_source; 120 EXPECT_CALL(mock_log_source, Log()).Times(0); 121 122 SetMinLogLevel(LOG_WARNING); 123 124 EXPECT_FALSE(LOG_IS_ON(INFO)); 125 EXPECT_FALSE(DLOG_IS_ON(INFO)); 126 EXPECT_FALSE(VLOG_IS_ON(1)); 127 128 LOG(INFO) << mock_log_source.Log(); 129 LOG_IF(INFO, false) << mock_log_source.Log(); 130 VLOG(1) << mock_log_source.Log(); 131 VLOG_IF(1, true) << mock_log_source.Log(); 132 133 DLOG(INFO) << mock_log_source.Log(); 134 DLOG_IF(INFO, true) << mock_log_source.Log(); 135 DVLOG(1) << mock_log_source.Log(); 136 DVLOG_IF(1, true) << mock_log_source.Log(); 137 } 138 139 TEST_F(LoggingTest, LoggingIsLazyByDestination) { 140 MockLogSource mock_log_source; 141 MockLogSource mock_log_source_error; 142 EXPECT_CALL(mock_log_source, Log()).Times(0); 143 144 // Severity >= ERROR is always printed to stderr. 145 EXPECT_CALL(mock_log_source_error, Log()).Times(1). 146 WillRepeatedly(Return("log message")); 147 148 LoggingSettings settings; 149 settings.logging_dest = LOG_NONE; 150 InitLogging(settings); 151 152 LOG(INFO) << mock_log_source.Log(); 153 LOG(WARNING) << mock_log_source.Log(); 154 LOG(ERROR) << mock_log_source_error.Log(); 155 } 156 157 // Official builds have CHECKs directly call BreakDebugger. 158 #if !defined(OFFICIAL_BUILD) 159 160 TEST_F(LoggingTest, CheckStreamsAreLazy) { 161 MockLogSource mock_log_source, uncalled_mock_log_source; 162 EXPECT_CALL(mock_log_source, Log()). 163 WillRepeatedly(Return("check message")); 164 EXPECT_CALL(uncalled_mock_log_source, Log()).Times(0); 165 166 SetLogAssertHandler(&LogSink); 167 168 CHECK(mock_log_source.Log()) << uncalled_mock_log_source.Log(); 169 CHECK_EQ(mock_log_source.Log(), mock_log_source.Log()) 170 << uncalled_mock_log_source.Log(); 171 CHECK_NE(mock_log_source.Log(), mock_log_source.Log()) 172 << mock_log_source.Log(); 173 } 174 175 #endif 176 177 TEST_F(LoggingTest, DebugLoggingReleaseBehavior) { 178 #if !defined(NDEBUG) 179 int debug_only_variable = 1; 180 #endif 181 // These should avoid emitting references to |debug_only_variable| 182 // in release mode. 183 DLOG_IF(INFO, debug_only_variable) << "test"; 184 DLOG_ASSERT(debug_only_variable) << "test"; 185 DVLOG_IF(1, debug_only_variable) << "test"; 186 } 187 188 TEST_F(LoggingTest, DcheckStreamsAreLazy) { 189 MockLogSource mock_log_source; 190 EXPECT_CALL(mock_log_source, Log()).Times(0); 191 #if DCHECK_IS_ON() 192 DCHECK(true) << mock_log_source.Log(); 193 DCHECK_EQ(0, 0) << mock_log_source.Log(); 194 #else 195 DCHECK(mock_log_source.Log()) << mock_log_source.Log(); 196 DCHECK_EQ(0, 0) << mock_log_source.Log(); 197 DCHECK_EQ(mock_log_source.Log(), static_cast<const char*>(NULL)) 198 << mock_log_source.Log(); 199 #endif 200 } 201 202 TEST_F(LoggingTest, Dcheck) { 203 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) 204 // Release build. 205 EXPECT_FALSE(DCHECK_IS_ON()); 206 EXPECT_FALSE(DLOG_IS_ON(DCHECK)); 207 #elif defined(NDEBUG) && defined(DCHECK_ALWAYS_ON) 208 // Release build with real DCHECKS. 209 SetLogAssertHandler(&LogSink); 210 EXPECT_TRUE(DCHECK_IS_ON()); 211 EXPECT_FALSE(DLOG_IS_ON(DCHECK)); 212 #else 213 // Debug build. 214 SetLogAssertHandler(&LogSink); 215 EXPECT_TRUE(DCHECK_IS_ON()); 216 EXPECT_TRUE(DLOG_IS_ON(DCHECK)); 217 #endif 218 219 EXPECT_EQ(0, log_sink_call_count); 220 DCHECK(false); 221 EXPECT_EQ(DCHECK_IS_ON() ? 1 : 0, log_sink_call_count); 222 DCHECK_EQ(0, 1); 223 EXPECT_EQ(DCHECK_IS_ON() ? 2 : 0, log_sink_call_count); 224 } 225 226 TEST_F(LoggingTest, DcheckReleaseBehavior) { 227 int some_variable = 1; 228 // These should still reference |some_variable| so we don't get 229 // unused variable warnings. 230 DCHECK(some_variable) << "test"; 231 DCHECK_EQ(some_variable, 1) << "test"; 232 } 233 234 TEST_F(LoggingTest, DCheckEqStatements) { 235 bool reached = false; 236 if (false) 237 DCHECK_EQ(false, true); // Unreached. 238 else 239 DCHECK_EQ(true, reached = true); // Reached, passed. 240 ASSERT_EQ(DCHECK_IS_ON() ? true : false, reached); 241 242 if (false) 243 DCHECK_EQ(false, true); // Unreached. 244 } 245 246 TEST_F(LoggingTest, CheckEqStatements) { 247 bool reached = false; 248 if (false) 249 CHECK_EQ(false, true); // Unreached. 250 else 251 CHECK_EQ(true, reached = true); // Reached, passed. 252 ASSERT_TRUE(reached); 253 254 if (false) 255 CHECK_EQ(false, true); // Unreached. 256 } 257 258 } // namespace 259 260 } // namespace logging 261