• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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)
LogSink(const std::string & str)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:
LogStateSaver()31   LogStateSaver() : old_min_log_level_(GetMinLogLevel()) {}
32 
~LogStateSaver()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 
TEST_F(LoggingTest,BasicLogging)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 
TEST_F(LoggingTest,LogIsOn)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 
TEST_F(LoggingTest,LoggingIsLazyBySeverity)125 TEST_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 
TEST_F(LoggingTest,LoggingIsLazyByDestination)154 TEST_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 
TEST_F(LoggingTest,CheckStreamsAreLazy)175 TEST_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 
TEST_F(LoggingTest,DebugLoggingReleaseBehavior)193 TEST_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 
TEST_F(LoggingTest,DcheckStreamsAreLazy)205 TEST_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 
TEST_F(LoggingTest,Dcheck)220 TEST_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 
TEST_F(LoggingTest,DcheckReleaseBehavior)263 TEST_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 
TEST_F(LoggingTest,DCheckEqStatements)272 TEST_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 
TEST_F(LoggingTest,CheckEqStatements)284 TEST_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.
301 namespace nested_test {
302   class Streamable {};
operator <<(std::ostream & out,const Streamable &)303   ALLOW_UNUSED_TYPE std::ostream& operator<<(std::ostream& out,
304                                              const Streamable&) {
305     return out << "Streamable";
306   }
TEST_F(LoggingTest,StreamingWstringFindsCorrectOperator)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