• 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 #if defined(OS_POSIX)
13 #include <signal.h>
14 #include <unistd.h>
15 #include "base/posix/eintr_wrapper.h"
16 #endif  // OS_POSIX
17 
18 #if defined(OS_LINUX) || defined(OS_ANDROID)
19 #include <ucontext.h>
20 #endif
21 
22 #if defined(OS_WIN)
23 #include <excpt.h>
24 #include <windows.h>
25 #endif  // OS_WIN
26 
27 namespace logging {
28 
29 namespace {
30 
31 using ::testing::Return;
32 
33 // Needs to be global since log assert handlers can't maintain state.
34 int log_sink_call_count = 0;
35 
36 #if !defined(OFFICIAL_BUILD) || defined(DCHECK_ALWAYS_ON) || !defined(NDEBUG)
LogSink(const std::string & str)37 void LogSink(const std::string& str) {
38   ++log_sink_call_count;
39 }
40 #endif
41 
42 // Class to make sure any manipulations we do to the min log level are
43 // contained (i.e., do not affect other unit tests).
44 class LogStateSaver {
45  public:
LogStateSaver()46   LogStateSaver() : old_min_log_level_(GetMinLogLevel()) {}
47 
~LogStateSaver()48   ~LogStateSaver() {
49     SetMinLogLevel(old_min_log_level_);
50     SetLogAssertHandler(NULL);
51     log_sink_call_count = 0;
52   }
53 
54  private:
55   int old_min_log_level_;
56 
57   DISALLOW_COPY_AND_ASSIGN(LogStateSaver);
58 };
59 
60 class LoggingTest : public testing::Test {
61  private:
62   LogStateSaver log_state_saver_;
63 };
64 
65 class MockLogSource {
66  public:
67   MOCK_METHOD0(Log, const char*());
68 };
69 
TEST_F(LoggingTest,BasicLogging)70 TEST_F(LoggingTest, BasicLogging) {
71   MockLogSource mock_log_source;
72   EXPECT_CALL(mock_log_source, Log())
73       .Times(DCHECK_IS_ON() ? 16 : 8)
74       .WillRepeatedly(Return("log message"));
75 
76   SetMinLogLevel(LOG_INFO);
77 
78   EXPECT_TRUE(LOG_IS_ON(INFO));
79   EXPECT_TRUE((DCHECK_IS_ON() != 0) == DLOG_IS_ON(INFO));
80   EXPECT_TRUE(VLOG_IS_ON(0));
81 
82   LOG(INFO) << mock_log_source.Log();
83   LOG_IF(INFO, true) << mock_log_source.Log();
84   PLOG(INFO) << mock_log_source.Log();
85   PLOG_IF(INFO, true) << mock_log_source.Log();
86   VLOG(0) << mock_log_source.Log();
87   VLOG_IF(0, true) << mock_log_source.Log();
88   VPLOG(0) << mock_log_source.Log();
89   VPLOG_IF(0, true) << mock_log_source.Log();
90 
91   DLOG(INFO) << mock_log_source.Log();
92   DLOG_IF(INFO, true) << mock_log_source.Log();
93   DPLOG(INFO) << mock_log_source.Log();
94   DPLOG_IF(INFO, true) << mock_log_source.Log();
95   DVLOG(0) << mock_log_source.Log();
96   DVLOG_IF(0, true) << mock_log_source.Log();
97   DVPLOG(0) << mock_log_source.Log();
98   DVPLOG_IF(0, true) << mock_log_source.Log();
99 }
100 
TEST_F(LoggingTest,LogIsOn)101 TEST_F(LoggingTest, LogIsOn) {
102 #if defined(NDEBUG)
103   const bool kDfatalIsFatal = false;
104 #else  // defined(NDEBUG)
105   const bool kDfatalIsFatal = true;
106 #endif  // defined(NDEBUG)
107 
108   SetMinLogLevel(LOG_INFO);
109   EXPECT_TRUE(LOG_IS_ON(INFO));
110   EXPECT_TRUE(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   SetMinLogLevel(LOG_WARNING);
116   EXPECT_FALSE(LOG_IS_ON(INFO));
117   EXPECT_TRUE(LOG_IS_ON(WARNING));
118   EXPECT_TRUE(LOG_IS_ON(ERROR));
119   EXPECT_TRUE(LOG_IS_ON(FATAL));
120   EXPECT_TRUE(LOG_IS_ON(DFATAL));
121 
122   SetMinLogLevel(LOG_ERROR);
123   EXPECT_FALSE(LOG_IS_ON(INFO));
124   EXPECT_FALSE(LOG_IS_ON(WARNING));
125   EXPECT_TRUE(LOG_IS_ON(ERROR));
126   EXPECT_TRUE(LOG_IS_ON(FATAL));
127   EXPECT_TRUE(LOG_IS_ON(DFATAL));
128 
129   // LOG_IS_ON(FATAL) should always be true.
130   SetMinLogLevel(LOG_FATAL + 1);
131   EXPECT_FALSE(LOG_IS_ON(INFO));
132   EXPECT_FALSE(LOG_IS_ON(WARNING));
133   EXPECT_FALSE(LOG_IS_ON(ERROR));
134   EXPECT_TRUE(LOG_IS_ON(FATAL));
135   EXPECT_TRUE(kDfatalIsFatal == LOG_IS_ON(DFATAL));
136 }
137 
TEST_F(LoggingTest,LoggingIsLazyBySeverity)138 TEST_F(LoggingTest, LoggingIsLazyBySeverity) {
139   MockLogSource mock_log_source;
140   EXPECT_CALL(mock_log_source, Log()).Times(0);
141 
142   SetMinLogLevel(LOG_WARNING);
143 
144   EXPECT_FALSE(LOG_IS_ON(INFO));
145   EXPECT_FALSE(DLOG_IS_ON(INFO));
146   EXPECT_FALSE(VLOG_IS_ON(1));
147 
148   LOG(INFO) << mock_log_source.Log();
149   LOG_IF(INFO, false) << mock_log_source.Log();
150   PLOG(INFO) << mock_log_source.Log();
151   PLOG_IF(INFO, false) << mock_log_source.Log();
152   VLOG(1) << mock_log_source.Log();
153   VLOG_IF(1, true) << mock_log_source.Log();
154   VPLOG(1) << mock_log_source.Log();
155   VPLOG_IF(1, true) << mock_log_source.Log();
156 
157   DLOG(INFO) << mock_log_source.Log();
158   DLOG_IF(INFO, true) << mock_log_source.Log();
159   DPLOG(INFO) << mock_log_source.Log();
160   DPLOG_IF(INFO, true) << mock_log_source.Log();
161   DVLOG(1) << mock_log_source.Log();
162   DVLOG_IF(1, true) << mock_log_source.Log();
163   DVPLOG(1) << mock_log_source.Log();
164   DVPLOG_IF(1, true) << mock_log_source.Log();
165 }
166 
TEST_F(LoggingTest,LoggingIsLazyByDestination)167 TEST_F(LoggingTest, LoggingIsLazyByDestination) {
168   MockLogSource mock_log_source;
169   MockLogSource mock_log_source_error;
170   EXPECT_CALL(mock_log_source, Log()).Times(0);
171 
172   // Severity >= ERROR is always printed to stderr.
173   EXPECT_CALL(mock_log_source_error, Log()).Times(1).
174       WillRepeatedly(Return("log message"));
175 
176   LoggingSettings settings;
177   settings.logging_dest = LOG_NONE;
178   InitLogging(settings);
179 
180   LOG(INFO) << mock_log_source.Log();
181   LOG(WARNING) << mock_log_source.Log();
182   LOG(ERROR) << mock_log_source_error.Log();
183 }
184 
185 // Official builds have CHECKs directly call BreakDebugger.
186 #if !defined(OFFICIAL_BUILD)
187 
TEST_F(LoggingTest,CheckStreamsAreLazy)188 TEST_F(LoggingTest, CheckStreamsAreLazy) {
189   MockLogSource mock_log_source, uncalled_mock_log_source;
190   EXPECT_CALL(mock_log_source, Log()).Times(8).
191       WillRepeatedly(Return("check message"));
192   EXPECT_CALL(uncalled_mock_log_source, Log()).Times(0);
193 
194   SetLogAssertHandler(&LogSink);
195 
196   CHECK(mock_log_source.Log()) << uncalled_mock_log_source.Log();
197   PCHECK(!mock_log_source.Log()) << mock_log_source.Log();
198   CHECK_EQ(mock_log_source.Log(), mock_log_source.Log())
199       << uncalled_mock_log_source.Log();
200   CHECK_NE(mock_log_source.Log(), mock_log_source.Log())
201       << mock_log_source.Log();
202 }
203 
204 #endif
205 
206 #if defined(OFFICIAL_BUILD) && defined(OS_WIN)
CheckContainingFunc(int death_location)207 NOINLINE void CheckContainingFunc(int death_location) {
208   CHECK(death_location != 1);
209   CHECK(death_location != 2);
210   CHECK(death_location != 3);
211 }
212 
GetCheckExceptionData(EXCEPTION_POINTERS * p,DWORD * code,void ** addr)213 int GetCheckExceptionData(EXCEPTION_POINTERS* p, DWORD* code, void** addr) {
214   *code = p->ExceptionRecord->ExceptionCode;
215   *addr = p->ExceptionRecord->ExceptionAddress;
216   return EXCEPTION_EXECUTE_HANDLER;
217 }
218 
TEST_F(LoggingTest,CheckCausesDistinctBreakpoints)219 TEST_F(LoggingTest, CheckCausesDistinctBreakpoints) {
220   DWORD code1 = 0;
221   DWORD code2 = 0;
222   DWORD code3 = 0;
223   void* addr1 = nullptr;
224   void* addr2 = nullptr;
225   void* addr3 = nullptr;
226 
227   // Record the exception code and addresses.
228   __try {
229     CheckContainingFunc(1);
230   } __except (
231       GetCheckExceptionData(GetExceptionInformation(), &code1, &addr1)) {
232   }
233 
234   __try {
235     CheckContainingFunc(2);
236   } __except (
237       GetCheckExceptionData(GetExceptionInformation(), &code2, &addr2)) {
238   }
239 
240   __try {
241     CheckContainingFunc(3);
242   } __except (
243       GetCheckExceptionData(GetExceptionInformation(), &code3, &addr3)) {
244   }
245 
246   // Ensure that the exception codes are correct (in particular, breakpoints,
247   // not access violations).
248   EXPECT_EQ(STATUS_BREAKPOINT, code1);
249   EXPECT_EQ(STATUS_BREAKPOINT, code2);
250   EXPECT_EQ(STATUS_BREAKPOINT, code3);
251 
252   // Ensure that none of the CHECKs are colocated.
253   EXPECT_NE(addr1, addr2);
254   EXPECT_NE(addr1, addr3);
255   EXPECT_NE(addr2, addr3);
256 }
257 
258 #elif defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_IOS) && \
259     (defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY))
260 
261 int g_child_crash_pipe;
262 
CheckCrashTestSighandler(int,siginfo_t * info,void * context_ptr)263 void CheckCrashTestSighandler(int, siginfo_t* info, void* context_ptr) {
264   // Conversely to what clearly stated in "man 2 sigaction", some Linux kernels
265   // do NOT populate the |info->si_addr| in the case of a SIGTRAP. Hence we
266   // need the arch-specific boilerplate below, which is inspired by breakpad.
267   // At the same time, on OSX, ucontext.h is deprecated but si_addr works fine.
268   uintptr_t crash_addr = 0;
269 #if defined(OS_MACOSX)
270   crash_addr = reinterpret_cast<uintptr_t>(info->si_addr);
271 #else  // OS_POSIX && !OS_MACOSX
272   struct ucontext* context = reinterpret_cast<struct ucontext*>(context_ptr);
273 #if defined(ARCH_CPU_X86)
274   crash_addr = static_cast<uintptr_t>(context->uc_mcontext.gregs[REG_EIP]);
275 #elif defined(ARCH_CPU_X86_64)
276   crash_addr = static_cast<uintptr_t>(context->uc_mcontext.gregs[REG_RIP]);
277 #elif defined(ARCH_CPU_ARMEL)
278   crash_addr = static_cast<uintptr_t>(context->uc_mcontext.arm_pc);
279 #elif defined(ARCH_CPU_ARM64)
280   crash_addr = static_cast<uintptr_t>(context->uc_mcontext.pc);
281 #endif  // ARCH_*
282 #endif  // OS_POSIX && !OS_MACOSX
283   HANDLE_EINTR(write(g_child_crash_pipe, &crash_addr, sizeof(uintptr_t)));
284   _exit(0);
285 }
286 
287 // CHECK causes a direct crash (without jumping to another function) only in
288 // official builds. Unfortunately, continuous test coverage on official builds
289 // is lower. DO_CHECK here falls back on a home-brewed implementation in
290 // non-official builds, to catch regressions earlier in the CQ.
291 #if defined(OFFICIAL_BUILD)
292 #define DO_CHECK CHECK
293 #else
294 #define DO_CHECK(cond) \
295   if (!(cond))         \
296   IMMEDIATE_CRASH()
297 #endif
298 
CrashChildMain(int death_location)299 void CrashChildMain(int death_location) {
300   struct sigaction act = {};
301   act.sa_sigaction = CheckCrashTestSighandler;
302   act.sa_flags = SA_SIGINFO;
303   ASSERT_EQ(0, sigaction(SIGTRAP, &act, NULL));
304   ASSERT_EQ(0, sigaction(SIGBUS, &act, NULL));
305   ASSERT_EQ(0, sigaction(SIGILL, &act, NULL));
306   DO_CHECK(death_location != 1);
307   DO_CHECK(death_location != 2);
308   printf("\n");
309   DO_CHECK(death_location != 3);
310 
311   // Should never reach this point.
312   const uintptr_t failed = 0;
313   HANDLE_EINTR(write(g_child_crash_pipe, &failed, sizeof(uintptr_t)));
314 };
315 
SpawnChildAndCrash(int death_location,uintptr_t * child_crash_addr)316 void SpawnChildAndCrash(int death_location, uintptr_t* child_crash_addr) {
317   int pipefd[2];
318   ASSERT_EQ(0, pipe(pipefd));
319 
320   int pid = fork();
321   ASSERT_GE(pid, 0);
322 
323   if (pid == 0) {      // child process.
324     close(pipefd[0]);  // Close reader (parent) end.
325     g_child_crash_pipe = pipefd[1];
326     CrashChildMain(death_location);
327     FAIL() << "The child process was supposed to crash. It didn't.";
328   }
329 
330   close(pipefd[1]);  // Close writer (child) end.
331   DCHECK(child_crash_addr);
332   int res = HANDLE_EINTR(read(pipefd[0], child_crash_addr, sizeof(uintptr_t)));
333   ASSERT_EQ(static_cast<int>(sizeof(uintptr_t)), res);
334 }
335 
TEST_F(LoggingTest,CheckCausesDistinctBreakpoints)336 TEST_F(LoggingTest, CheckCausesDistinctBreakpoints) {
337   uintptr_t child_crash_addr_1 = 0;
338   uintptr_t child_crash_addr_2 = 0;
339   uintptr_t child_crash_addr_3 = 0;
340 
341   SpawnChildAndCrash(1, &child_crash_addr_1);
342   SpawnChildAndCrash(2, &child_crash_addr_2);
343   SpawnChildAndCrash(3, &child_crash_addr_3);
344 
345   ASSERT_NE(0u, child_crash_addr_1);
346   ASSERT_NE(0u, child_crash_addr_2);
347   ASSERT_NE(0u, child_crash_addr_3);
348   ASSERT_NE(child_crash_addr_1, child_crash_addr_2);
349   ASSERT_NE(child_crash_addr_1, child_crash_addr_3);
350   ASSERT_NE(child_crash_addr_2, child_crash_addr_3);
351 }
352 #endif  // OS_POSIX
353 
TEST_F(LoggingTest,DebugLoggingReleaseBehavior)354 TEST_F(LoggingTest, DebugLoggingReleaseBehavior) {
355 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
356   int debug_only_variable = 1;
357 #endif
358   // These should avoid emitting references to |debug_only_variable|
359   // in release mode.
360   DLOG_IF(INFO, debug_only_variable) << "test";
361   DLOG_ASSERT(debug_only_variable) << "test";
362   DPLOG_IF(INFO, debug_only_variable) << "test";
363   DVLOG_IF(1, debug_only_variable) << "test";
364 }
365 
TEST_F(LoggingTest,DcheckStreamsAreLazy)366 TEST_F(LoggingTest, DcheckStreamsAreLazy) {
367   MockLogSource mock_log_source;
368   EXPECT_CALL(mock_log_source, Log()).Times(0);
369 #if DCHECK_IS_ON()
370   DCHECK(true) << mock_log_source.Log();
371   DCHECK_EQ(0, 0) << mock_log_source.Log();
372 #else
373   DCHECK(mock_log_source.Log()) << mock_log_source.Log();
374   DPCHECK(mock_log_source.Log()) << mock_log_source.Log();
375   DCHECK_EQ(0, 0) << mock_log_source.Log();
376   DCHECK_EQ(mock_log_source.Log(), static_cast<const char*>(NULL))
377       << mock_log_source.Log();
378 #endif
379 }
380 
DcheckEmptyFunction1()381 void DcheckEmptyFunction1() {
382   // Provide a body so that Release builds do not cause the compiler to
383   // optimize DcheckEmptyFunction1 and DcheckEmptyFunction2 as a single
384   // function, which breaks the Dcheck tests below.
385   LOG(INFO) << "DcheckEmptyFunction1";
386 }
DcheckEmptyFunction2()387 void DcheckEmptyFunction2() {}
388 
TEST_F(LoggingTest,Dcheck)389 TEST_F(LoggingTest, Dcheck) {
390 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
391   // Release build.
392   EXPECT_FALSE(DCHECK_IS_ON());
393   EXPECT_FALSE(DLOG_IS_ON(DCHECK));
394 #elif defined(NDEBUG) && defined(DCHECK_ALWAYS_ON)
395   // Release build with real DCHECKS.
396   SetLogAssertHandler(&LogSink);
397   EXPECT_TRUE(DCHECK_IS_ON());
398   EXPECT_TRUE(DLOG_IS_ON(DCHECK));
399 #else
400   // Debug build.
401   SetLogAssertHandler(&LogSink);
402   EXPECT_TRUE(DCHECK_IS_ON());
403   EXPECT_TRUE(DLOG_IS_ON(DCHECK));
404 #endif
405 
406   EXPECT_EQ(0, log_sink_call_count);
407   DCHECK(false);
408   EXPECT_EQ(DCHECK_IS_ON() ? 1 : 0, log_sink_call_count);
409   DPCHECK(false);
410   EXPECT_EQ(DCHECK_IS_ON() ? 2 : 0, log_sink_call_count);
411   DCHECK_EQ(0, 1);
412   EXPECT_EQ(DCHECK_IS_ON() ? 3 : 0, log_sink_call_count);
413 
414   // Test DCHECK on std::nullptr_t
415   log_sink_call_count = 0;
416   const void* p_null = nullptr;
417   const void* p_not_null = &p_null;
418   DCHECK_EQ(p_null, nullptr);
419   DCHECK_EQ(nullptr, p_null);
420   DCHECK_NE(p_not_null, nullptr);
421   DCHECK_NE(nullptr, p_not_null);
422   EXPECT_EQ(0, log_sink_call_count);
423 
424   // Test DCHECK on a scoped enum.
425   enum class Animal { DOG, CAT };
426   DCHECK_EQ(Animal::DOG, Animal::DOG);
427   EXPECT_EQ(0, log_sink_call_count);
428   DCHECK_EQ(Animal::DOG, Animal::CAT);
429   EXPECT_EQ(DCHECK_IS_ON() ? 1 : 0, log_sink_call_count);
430 
431   // Test DCHECK on functions and function pointers.
432   log_sink_call_count = 0;
433   struct MemberFunctions {
434     void MemberFunction1() {
435       // See the comment in DcheckEmptyFunction1().
436       LOG(INFO) << "Do not merge with MemberFunction2.";
437     }
438     void MemberFunction2() {}
439   };
440   void (MemberFunctions::*mp1)() = &MemberFunctions::MemberFunction1;
441   void (MemberFunctions::*mp2)() = &MemberFunctions::MemberFunction2;
442   void (*fp1)() = DcheckEmptyFunction1;
443   void (*fp2)() = DcheckEmptyFunction2;
444   void (*fp3)() = DcheckEmptyFunction1;
445   DCHECK_EQ(fp1, fp3);
446   EXPECT_EQ(0, log_sink_call_count);
447   DCHECK_EQ(mp1, &MemberFunctions::MemberFunction1);
448   EXPECT_EQ(0, log_sink_call_count);
449   DCHECK_EQ(mp2, &MemberFunctions::MemberFunction2);
450   EXPECT_EQ(0, log_sink_call_count);
451   DCHECK_EQ(fp1, fp2);
452   EXPECT_EQ(DCHECK_IS_ON() ? 1 : 0, log_sink_call_count);
453   DCHECK_EQ(mp2, &MemberFunctions::MemberFunction1);
454   EXPECT_EQ(DCHECK_IS_ON() ? 2 : 0, log_sink_call_count);
455 }
456 
TEST_F(LoggingTest,DcheckReleaseBehavior)457 TEST_F(LoggingTest, DcheckReleaseBehavior) {
458   int some_variable = 1;
459   // These should still reference |some_variable| so we don't get
460   // unused variable warnings.
461   DCHECK(some_variable) << "test";
462   DPCHECK(some_variable) << "test";
463   DCHECK_EQ(some_variable, 1) << "test";
464 }
465 
TEST_F(LoggingTest,DCheckEqStatements)466 TEST_F(LoggingTest, DCheckEqStatements) {
467   bool reached = false;
468   if (false)
469     DCHECK_EQ(false, true);           // Unreached.
470   else
471     DCHECK_EQ(true, reached = true);  // Reached, passed.
472   ASSERT_EQ(DCHECK_IS_ON() ? true : false, reached);
473 
474   if (false)
475     DCHECK_EQ(false, true);           // Unreached.
476 }
477 
TEST_F(LoggingTest,CheckEqStatements)478 TEST_F(LoggingTest, CheckEqStatements) {
479   bool reached = false;
480   if (false)
481     CHECK_EQ(false, true);           // Unreached.
482   else
483     CHECK_EQ(true, reached = true);  // Reached, passed.
484   ASSERT_TRUE(reached);
485 
486   if (false)
487     CHECK_EQ(false, true);           // Unreached.
488 }
489 
490 // Test that defining an operator<< for a type in a namespace doesn't prevent
491 // other code in that namespace from calling the operator<<(ostream, wstring)
492 // defined by logging.h. This can fail if operator<<(ostream, wstring) can't be
493 // found by ADL, since defining another operator<< prevents name lookup from
494 // looking in the global namespace.
495 namespace nested_test {
496   class Streamable {};
operator <<(std::ostream & out,const Streamable &)497   ALLOW_UNUSED_TYPE std::ostream& operator<<(std::ostream& out,
498                                              const Streamable&) {
499     return out << "Streamable";
500   }
TEST_F(LoggingTest,StreamingWstringFindsCorrectOperator)501   TEST_F(LoggingTest, StreamingWstringFindsCorrectOperator) {
502     std::wstring wstr = L"Hello World";
503     std::ostringstream ostr;
504     ostr << wstr;
505     EXPECT_EQ("Hello World", ostr.str());
506   }
507 }  // namespace nested_test
508 
509 }  // namespace
510 
511 }  // namespace logging
512