| OLD | NEW |
| (Empty) |
| 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/compiler_specific.h" | |
| 7 #include "base/logging.h" | |
| 8 | |
| 9 #include "testing/gmock/include/gmock/gmock.h" | |
| 10 #include "testing/gtest/include/gtest/gtest.h" | |
| 11 | |
| 12 namespace logging { | |
| 13 | |
| 14 namespace { | |
| 15 | |
| 16 using ::testing::Return; | |
| 17 | |
| 18 // Needs to be global since log assert handlers can't maintain state. | |
| 19 int log_sink_call_count = 0; | |
| 20 | |
| 21 #if !defined(OFFICIAL_BUILD) || defined(DCHECK_ALWAYS_ON) || !defined(NDEBUG) | |
| 22 void 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). | |
| 29 class 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 | |
| 45 class LoggingTest : public testing::Test { | |
| 46 private: | |
| 47 LogStateSaver log_state_saver_; | |
| 48 }; | |
| 49 | |
| 50 class MockLogSource { | |
| 51 public: | |
| 52 MOCK_METHOD0(Log, const char*()); | |
| 53 }; | |
| 54 | |
| 55 TEST_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 | |
| 88 TEST_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 | |
| 125 TEST_F(LoggingTest, LoggingIsLazy) { | |
| 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 | |
| 154 // Official builds have CHECKs directly call BreakDebugger. | |
| 155 #if !defined(OFFICIAL_BUILD) | |
| 156 | |
| 157 TEST_F(LoggingTest, CheckStreamsAreLazy) { | |
| 158 MockLogSource mock_log_source, uncalled_mock_log_source; | |
| 159 EXPECT_CALL(mock_log_source, Log()).Times(8). | |
| 160 WillRepeatedly(Return("check message")); | |
| 161 EXPECT_CALL(uncalled_mock_log_source, Log()).Times(0); | |
| 162 | |
| 163 SetLogAssertHandler(&LogSink); | |
| 164 | |
| 165 CHECK(mock_log_source.Log()) << uncalled_mock_log_source.Log(); | |
| 166 PCHECK(!mock_log_source.Log()) << mock_log_source.Log(); | |
| 167 CHECK_EQ(mock_log_source.Log(), mock_log_source.Log()) | |
| 168 << uncalled_mock_log_source.Log(); | |
| 169 CHECK_NE(mock_log_source.Log(), mock_log_source.Log()) | |
| 170 << mock_log_source.Log(); | |
| 171 } | |
| 172 | |
| 173 #endif | |
| 174 | |
| 175 TEST_F(LoggingTest, DebugLoggingReleaseBehavior) { | |
| 176 #if !defined(NDEBUG) | |
| 177 int debug_only_variable = 1; | |
| 178 #endif | |
| 179 // These should avoid emitting references to |debug_only_variable| | |
| 180 // in release mode. | |
| 181 DLOG_IF(INFO, debug_only_variable) << "test"; | |
| 182 DLOG_ASSERT(debug_only_variable) << "test"; | |
| 183 DPLOG_IF(INFO, debug_only_variable) << "test"; | |
| 184 DVLOG_IF(1, debug_only_variable) << "test"; | |
| 185 } | |
| 186 | |
| 187 TEST_F(LoggingTest, DcheckStreamsAreLazy) { | |
| 188 MockLogSource mock_log_source; | |
| 189 EXPECT_CALL(mock_log_source, Log()).Times(0); | |
| 190 #if DCHECK_IS_ON() | |
| 191 DCHECK(true) << mock_log_source.Log(); | |
| 192 DCHECK_EQ(0, 0) << mock_log_source.Log(); | |
| 193 #else | |
| 194 DCHECK(mock_log_source.Log()) << mock_log_source.Log(); | |
| 195 DPCHECK(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 DPCHECK(false); | |
| 223 EXPECT_EQ(DCHECK_IS_ON() ? 2 : 0, log_sink_call_count); | |
| 224 DCHECK_EQ(0, 1); | |
| 225 EXPECT_EQ(DCHECK_IS_ON() ? 3 : 0, log_sink_call_count); | |
| 226 } | |
| 227 | |
| 228 TEST_F(LoggingTest, DcheckReleaseBehavior) { | |
| 229 int some_variable = 1; | |
| 230 // These should still reference |some_variable| so we don't get | |
| 231 // unused variable warnings. | |
| 232 DCHECK(some_variable) << "test"; | |
| 233 DPCHECK(some_variable) << "test"; | |
| 234 DCHECK_EQ(some_variable, 1) << "test"; | |
| 235 } | |
| 236 | |
| 237 // Test that defining an operator<< for a type in a namespace doesn't prevent | |
| 238 // other code in that namespace from calling the operator<<(ostream, wstring) | |
| 239 // defined by logging.h. This can fail if operator<<(ostream, wstring) can't be | |
| 240 // found by ADL, since defining another operator<< prevents name lookup from | |
| 241 // looking in the global namespace. | |
| 242 namespace nested_test { | |
| 243 class Streamable {}; | |
| 244 ALLOW_UNUSED_TYPE std::ostream& operator<<(std::ostream& out, | |
| 245 const Streamable&) { | |
| 246 return out << "Streamable"; | |
| 247 } | |
| 248 TEST_F(LoggingTest, StreamingWstringFindsCorrectOperator) { | |
| 249 std::wstring wstr = L"Hello World"; | |
| 250 std::ostringstream ostr; | |
| 251 ostr << wstr; | |
| 252 EXPECT_EQ("Hello World", ostr.str()); | |
| 253 } | |
| 254 } // namespace nested_test | |
| 255 | |
| 256 } // namespace | |
| 257 | |
| 258 } // namespace logging | |
| OLD | NEW |