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 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, 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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 {};
    303   ALLOW_UNUSED_TYPE std::ostream& operator<<(std::ostream& out,
    304                                              const Streamable&) {
    305     return out << "Streamable";
    306   }
    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