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/compiler_specific.h" 6#include "base/logging.h" 7#include "base/macros.h" 8 9#include "testing/gmock/include/gmock/gmock.h" 10#include "testing/gtest/include/gtest/gtest.h" 11 12namespace logging { 13 14namespace { 15 16using ::testing::Return; 17 18// Needs to be global since log assert handlers can't maintain state. 19int log_sink_call_count = 0; 20 21#if !defined(OFFICIAL_BUILD) || defined(DCHECK_ALWAYS_ON) || !defined(NDEBUG) 22void LogSink(const std::string& str) { 23 ++log_sink_call_count; 24} 25#endif 26 27// Class to make sure any manipulations we do to the min log level are 28// contained (i.e., do not affect other unit tests). 29class LogStateSaver { 30 public: 31 LogStateSaver() : old_min_log_level_(GetMinLogLevel()) {} 32 33 ~LogStateSaver() { 34 SetMinLogLevel(old_min_log_level_); 35 SetLogAssertHandler(NULL); 36 log_sink_call_count = 0; 37 } 38 39 private: 40 int old_min_log_level_; 41 42 DISALLOW_COPY_AND_ASSIGN(LogStateSaver); 43}; 44 45class LoggingTest : public testing::Test { 46 private: 47 LogStateSaver log_state_saver_; 48}; 49 50class MockLogSource { 51 public: 52 MOCK_METHOD0(Log, const char*()); 53}; 54 55TEST_F(LoggingTest, BasicLogging) { 56 MockLogSource mock_log_source; 57 EXPECT_CALL(mock_log_source, Log()).Times(DEBUG_MODE ? 16 : 8). 58 WillRepeatedly(Return("log message")); 59 60 SetMinLogLevel(LOG_INFO); 61 62 EXPECT_TRUE(LOG_IS_ON(INFO)); 63 // As of g++-4.5, the first argument to EXPECT_EQ cannot be a 64 // constant expression. 65 const bool kIsDebugMode = (DEBUG_MODE != 0); 66 EXPECT_TRUE(kIsDebugMode == DLOG_IS_ON(INFO)); 67 EXPECT_TRUE(VLOG_IS_ON(0)); 68 69 LOG(INFO) << mock_log_source.Log(); 70 LOG_IF(INFO, true) << mock_log_source.Log(); 71 PLOG(INFO) << mock_log_source.Log(); 72 PLOG_IF(INFO, true) << mock_log_source.Log(); 73 VLOG(0) << mock_log_source.Log(); 74 VLOG_IF(0, true) << mock_log_source.Log(); 75 VPLOG(0) << mock_log_source.Log(); 76 VPLOG_IF(0, true) << mock_log_source.Log(); 77 78 DLOG(INFO) << mock_log_source.Log(); 79 DLOG_IF(INFO, true) << mock_log_source.Log(); 80 DPLOG(INFO) << mock_log_source.Log(); 81 DPLOG_IF(INFO, true) << mock_log_source.Log(); 82 DVLOG(0) << mock_log_source.Log(); 83 DVLOG_IF(0, true) << mock_log_source.Log(); 84 DVPLOG(0) << mock_log_source.Log(); 85 DVPLOG_IF(0, true) << mock_log_source.Log(); 86} 87 88TEST_F(LoggingTest, LogIsOn) { 89#if defined(NDEBUG) 90 const bool kDfatalIsFatal = false; 91#else // defined(NDEBUG) 92 const bool kDfatalIsFatal = true; 93#endif // defined(NDEBUG) 94 95 SetMinLogLevel(LOG_INFO); 96 EXPECT_TRUE(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_WARNING); 103 EXPECT_FALSE(LOG_IS_ON(INFO)); 104 EXPECT_TRUE(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 SetMinLogLevel(LOG_ERROR); 110 EXPECT_FALSE(LOG_IS_ON(INFO)); 111 EXPECT_FALSE(LOG_IS_ON(WARNING)); 112 EXPECT_TRUE(LOG_IS_ON(ERROR)); 113 EXPECT_TRUE(LOG_IS_ON(FATAL)); 114 EXPECT_TRUE(LOG_IS_ON(DFATAL)); 115 116 // LOG_IS_ON(FATAL) should always be true. 117 SetMinLogLevel(LOG_FATAL + 1); 118 EXPECT_FALSE(LOG_IS_ON(INFO)); 119 EXPECT_FALSE(LOG_IS_ON(WARNING)); 120 EXPECT_FALSE(LOG_IS_ON(ERROR)); 121 EXPECT_TRUE(LOG_IS_ON(FATAL)); 122 EXPECT_TRUE(kDfatalIsFatal == LOG_IS_ON(DFATAL)); 123} 124 125TEST_F(LoggingTest, LoggingIsLazyBySeverity) { 126 MockLogSource mock_log_source; 127 EXPECT_CALL(mock_log_source, Log()).Times(0); 128 129 SetMinLogLevel(LOG_WARNING); 130 131 EXPECT_FALSE(LOG_IS_ON(INFO)); 132 EXPECT_FALSE(DLOG_IS_ON(INFO)); 133 EXPECT_FALSE(VLOG_IS_ON(1)); 134 135 LOG(INFO) << mock_log_source.Log(); 136 LOG_IF(INFO, false) << mock_log_source.Log(); 137 PLOG(INFO) << mock_log_source.Log(); 138 PLOG_IF(INFO, false) << mock_log_source.Log(); 139 VLOG(1) << mock_log_source.Log(); 140 VLOG_IF(1, true) << mock_log_source.Log(); 141 VPLOG(1) << mock_log_source.Log(); 142 VPLOG_IF(1, true) << mock_log_source.Log(); 143 144 DLOG(INFO) << mock_log_source.Log(); 145 DLOG_IF(INFO, true) << mock_log_source.Log(); 146 DPLOG(INFO) << mock_log_source.Log(); 147 DPLOG_IF(INFO, true) << mock_log_source.Log(); 148 DVLOG(1) << mock_log_source.Log(); 149 DVLOG_IF(1, true) << mock_log_source.Log(); 150 DVPLOG(1) << mock_log_source.Log(); 151 DVPLOG_IF(1, true) << mock_log_source.Log(); 152} 153 154TEST_F(LoggingTest, LoggingIsLazyByDestination) { 155 MockLogSource mock_log_source; 156 MockLogSource mock_log_source_error; 157 EXPECT_CALL(mock_log_source, Log()).Times(0); 158 159 // Severity >= ERROR is always printed to stderr. 160 EXPECT_CALL(mock_log_source_error, Log()).Times(1). 161 WillRepeatedly(Return("log message")); 162 163 LoggingSettings settings; 164 settings.logging_dest = LOG_NONE; 165 InitLogging(settings); 166 167 LOG(INFO) << mock_log_source.Log(); 168 LOG(WARNING) << mock_log_source.Log(); 169 LOG(ERROR) << mock_log_source_error.Log(); 170} 171 172// Official builds have CHECKs directly call BreakDebugger. 173#if !defined(OFFICIAL_BUILD) 174 175TEST_F(LoggingTest, CheckStreamsAreLazy) { 176 MockLogSource mock_log_source, uncalled_mock_log_source; 177 EXPECT_CALL(mock_log_source, Log()).Times(8). 178 WillRepeatedly(Return("check message")); 179 EXPECT_CALL(uncalled_mock_log_source, Log()).Times(0); 180 181 SetLogAssertHandler(&LogSink); 182 183 CHECK(mock_log_source.Log()) << uncalled_mock_log_source.Log(); 184 PCHECK(!mock_log_source.Log()) << mock_log_source.Log(); 185 CHECK_EQ(mock_log_source.Log(), mock_log_source.Log()) 186 << uncalled_mock_log_source.Log(); 187 CHECK_NE(mock_log_source.Log(), mock_log_source.Log()) 188 << mock_log_source.Log(); 189} 190 191#endif 192 193TEST_F(LoggingTest, DebugLoggingReleaseBehavior) { 194#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) 195 int debug_only_variable = 1; 196#endif 197 // These should avoid emitting references to |debug_only_variable| 198 // in release mode. 199 DLOG_IF(INFO, debug_only_variable) << "test"; 200 DLOG_ASSERT(debug_only_variable) << "test"; 201 DPLOG_IF(INFO, debug_only_variable) << "test"; 202 DVLOG_IF(1, debug_only_variable) << "test"; 203} 204 205TEST_F(LoggingTest, DcheckStreamsAreLazy) { 206 MockLogSource mock_log_source; 207 EXPECT_CALL(mock_log_source, Log()).Times(0); 208#if DCHECK_IS_ON() 209 DCHECK(true) << mock_log_source.Log(); 210 DCHECK_EQ(0, 0) << mock_log_source.Log(); 211#else 212 DCHECK(mock_log_source.Log()) << mock_log_source.Log(); 213 DPCHECK(mock_log_source.Log()) << mock_log_source.Log(); 214 DCHECK_EQ(0, 0) << mock_log_source.Log(); 215 DCHECK_EQ(mock_log_source.Log(), static_cast<const char*>(NULL)) 216 << mock_log_source.Log(); 217#endif 218} 219 220TEST_F(LoggingTest, Dcheck) { 221#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) 222 // Release build. 223 EXPECT_FALSE(DCHECK_IS_ON()); 224 EXPECT_FALSE(DLOG_IS_ON(DCHECK)); 225#elif defined(NDEBUG) && defined(DCHECK_ALWAYS_ON) 226 // Release build with real DCHECKS. 227 SetLogAssertHandler(&LogSink); 228 EXPECT_TRUE(DCHECK_IS_ON()); 229 EXPECT_TRUE(DLOG_IS_ON(DCHECK)); 230#else 231 // Debug build. 232 SetLogAssertHandler(&LogSink); 233 EXPECT_TRUE(DCHECK_IS_ON()); 234 EXPECT_TRUE(DLOG_IS_ON(DCHECK)); 235#endif 236 237 EXPECT_EQ(0, log_sink_call_count); 238 DCHECK(false); 239 EXPECT_EQ(DCHECK_IS_ON() ? 1 : 0, log_sink_call_count); 240 DPCHECK(false); 241 EXPECT_EQ(DCHECK_IS_ON() ? 2 : 0, log_sink_call_count); 242 DCHECK_EQ(0, 1); 243 EXPECT_EQ(DCHECK_IS_ON() ? 3 : 0, log_sink_call_count); 244 245 // Test DCHECK on std::nullptr_t 246 log_sink_call_count = 0; 247 const void* p_null = nullptr; 248 const void* p_not_null = &p_null; 249 DCHECK_EQ(p_null, nullptr); 250 DCHECK_EQ(nullptr, p_null); 251 DCHECK_NE(p_not_null, nullptr); 252 DCHECK_NE(nullptr, p_not_null); 253 EXPECT_EQ(0, log_sink_call_count); 254 255 // Test DCHECK on a scoped enum. 256 enum class Animal { DOG, CAT }; 257 DCHECK_EQ(Animal::DOG, Animal::DOG); 258 EXPECT_EQ(0, log_sink_call_count); 259 DCHECK_EQ(Animal::DOG, Animal::CAT); 260 EXPECT_EQ(DCHECK_IS_ON() ? 1 : 0, log_sink_call_count); 261} 262 263TEST_F(LoggingTest, DcheckReleaseBehavior) { 264 int some_variable = 1; 265 // These should still reference |some_variable| so we don't get 266 // unused variable warnings. 267 DCHECK(some_variable) << "test"; 268 DPCHECK(some_variable) << "test"; 269 DCHECK_EQ(some_variable, 1) << "test"; 270} 271 272TEST_F(LoggingTest, DCheckEqStatements) { 273 bool reached = false; 274 if (false) 275 DCHECK_EQ(false, true); // Unreached. 276 else 277 DCHECK_EQ(true, reached = true); // Reached, passed. 278 ASSERT_EQ(DCHECK_IS_ON() ? true : false, reached); 279 280 if (false) 281 DCHECK_EQ(false, true); // Unreached. 282} 283 284TEST_F(LoggingTest, CheckEqStatements) { 285 bool reached = false; 286 if (false) 287 CHECK_EQ(false, true); // Unreached. 288 else 289 CHECK_EQ(true, reached = true); // Reached, passed. 290 ASSERT_TRUE(reached); 291 292 if (false) 293 CHECK_EQ(false, true); // Unreached. 294} 295 296// Test that defining an operator<< for a type in a namespace doesn't prevent 297// other code in that namespace from calling the operator<<(ostream, wstring) 298// defined by logging.h. This can fail if operator<<(ostream, wstring) can't be 299// found by ADL, since defining another operator<< prevents name lookup from 300// looking in the global namespace. 301namespace nested_test { 302 class Streamable {}; 303 ALLOW_UNUSED_TYPE std::ostream& operator<<(std::ostream& out, 304 const Streamable&) { 305 return out << "Streamable"; 306 } 307 TEST_F(LoggingTest, StreamingWstringFindsCorrectOperator) { 308 std::wstring wstr = L"Hello World"; 309 std::ostringstream ostr; 310 ostr << wstr; 311 EXPECT_EQ("Hello World", ostr.str()); 312 } 313} // namespace nested_test 314 315} // namespace 316 317} // namespace logging 318