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 11namespace logging { 12 13namespace { 14 15using ::testing::Return; 16 17// Needs to be global since log assert handlers can't maintain state. 18int log_sink_call_count = 0; 19 20#if !defined(OFFICIAL_BUILD) || defined(DCHECK_ALWAYS_ON) || !defined(NDEBUG) 21void 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). 28class 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 44class LoggingTest : public testing::Test { 45 private: 46 LogStateSaver log_state_saver_; 47}; 48 49class MockLogSource { 50 public: 51 MOCK_METHOD0(Log, const char*()); 52}; 53 54TEST_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 87TEST_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 124TEST_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 156TEST_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 174TEST_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 186TEST_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 201TEST_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 227TEST_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// Test that defining an operator<< for a type in a namespace doesn't prevent 237// other code in that namespace from calling the operator<<(ostream, wstring) 238// defined by logging.h. This can fail if operator<<(ostream, wstring) can't be 239// found by ADL, since defining another operator<< prevents name lookup from 240// looking in the global namespace. 241namespace nested_test { 242 class Streamable {}; 243 ALLOW_UNUSED std::ostream& operator<<(std::ostream& out, const Streamable&) { 244 return out << "Streamable"; 245 } 246 TEST_F(LoggingTest, StreamingWstringFindsCorrectOperator) { 247 std::wstring wstr = L"Hello World"; 248 std::ostringstream ostr; 249 ostr << wstr; 250 EXPECT_EQ("Hello World", ostr.str()); 251 } 252} // namespace nested_test 253 254} // namespace 255 256} // namespace logging 257