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