Home | History | Annotate | Download | only in base
      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)
     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:
     46   LogStateSaver() : old_min_log_level_(GetMinLogLevel()) {}
     47 
     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 
     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 
    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 
    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 
    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 
    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)
    207 NOINLINE void CheckContainingFunc(int death_location) {
    208   CHECK(death_location != 1);
    209   CHECK(death_location != 2);
    210   CHECK(death_location != 3);
    211 }
    212 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 }
    387 void DcheckEmptyFunction2() {}
    388 
    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 
    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 
    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 
    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 {};
    497   ALLOW_UNUSED_TYPE std::ostream& operator<<(std::ostream& out,
    498                                              const Streamable&) {
    499     return out << "Streamable";
    500   }
    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