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/logging.h"
      6 
      7 #include <gmock/gmock.h>
      8 #include <gtest/gtest.h>
      9 
     10 #include "base/compiler_specific.h"
     11 #include "base/macros.h"
     12 
     13 namespace logging {
     14 
     15 namespace {
     16 
     17 using ::testing::Return;
     18 
     19 // Needs to be global since log assert handlers can't maintain state.
     20 int log_sink_call_count = 0;
     21 
     22 #if !defined(OFFICIAL_BUILD) || defined(DCHECK_ALWAYS_ON) || !defined(NDEBUG)
     23 void LogSink(const std::string& str) {
     24   ++log_sink_call_count;
     25 }
     26 #endif
     27 
     28 // Class to make sure any manipulations we do to the min log level are
     29 // contained (i.e., do not affect other unit tests).
     30 class LogStateSaver {
     31  public:
     32   LogStateSaver() : old_min_log_level_(GetMinLogLevel()) {}
     33 
     34   ~LogStateSaver() {
     35     SetMinLogLevel(old_min_log_level_);
     36     SetLogAssertHandler(NULL);
     37     log_sink_call_count = 0;
     38   }
     39 
     40  private:
     41   int old_min_log_level_;
     42 
     43   DISALLOW_COPY_AND_ASSIGN(LogStateSaver);
     44 };
     45 
     46 class LoggingTest : public testing::Test {
     47  private:
     48   LogStateSaver log_state_saver_;
     49 };
     50 
     51 class MockLogSource {
     52  public:
     53   MOCK_METHOD0(Log, const char*());
     54 };
     55 
     56 TEST_F(LoggingTest, BasicLogging) {
     57   MockLogSource mock_log_source;
     58   EXPECT_CALL(mock_log_source, Log()).
     59       WillRepeatedly(Return("log message"));
     60 
     61   SetMinLogLevel(LOG_INFO);
     62 
     63   EXPECT_TRUE(LOG_IS_ON(INFO));
     64   // As of g++-4.5, the first argument to EXPECT_EQ cannot be a
     65   // constant expression.
     66   const bool kIsDebugMode = (DEBUG_MODE != 0);
     67   EXPECT_TRUE(kIsDebugMode == DLOG_IS_ON(INFO));
     68   EXPECT_TRUE(VLOG_IS_ON(0));
     69 
     70   LOG(INFO) << mock_log_source.Log();
     71   LOG_IF(INFO, true) << mock_log_source.Log();
     72   VLOG(0) << mock_log_source.Log();
     73   VLOG_IF(0, true) << mock_log_source.Log();
     74 
     75   DLOG(INFO) << mock_log_source.Log();
     76   DLOG_IF(INFO, true) << mock_log_source.Log();
     77   DVLOG(0) << mock_log_source.Log();
     78   DVLOG_IF(0, true) << mock_log_source.Log();
     79 }
     80 
     81 TEST_F(LoggingTest, LogIsOn) {
     82 #if defined(NDEBUG)
     83   const bool kDfatalIsFatal = false;
     84 #else  // defined(NDEBUG)
     85   const bool kDfatalIsFatal = true;
     86 #endif  // defined(NDEBUG)
     87 
     88   SetMinLogLevel(LOG_INFO);
     89   EXPECT_TRUE(LOG_IS_ON(INFO));
     90   EXPECT_TRUE(LOG_IS_ON(WARNING));
     91   EXPECT_TRUE(LOG_IS_ON(ERROR));
     92   EXPECT_TRUE(LOG_IS_ON(FATAL));
     93   EXPECT_TRUE(LOG_IS_ON(DFATAL));
     94 
     95   SetMinLogLevel(LOG_WARNING);
     96   EXPECT_FALSE(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_ERROR);
    103   EXPECT_FALSE(LOG_IS_ON(INFO));
    104   EXPECT_FALSE(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   // LOG_IS_ON(FATAL) should always be true.
    110   SetMinLogLevel(LOG_FATAL + 1);
    111   EXPECT_FALSE(LOG_IS_ON(INFO));
    112   EXPECT_FALSE(LOG_IS_ON(WARNING));
    113   EXPECT_FALSE(LOG_IS_ON(ERROR));
    114   EXPECT_TRUE(LOG_IS_ON(FATAL));
    115   EXPECT_TRUE(kDfatalIsFatal == LOG_IS_ON(DFATAL));
    116 }
    117 
    118 TEST_F(LoggingTest, LoggingIsLazyBySeverity) {
    119   MockLogSource mock_log_source;
    120   EXPECT_CALL(mock_log_source, Log()).Times(0);
    121 
    122   SetMinLogLevel(LOG_WARNING);
    123 
    124   EXPECT_FALSE(LOG_IS_ON(INFO));
    125   EXPECT_FALSE(DLOG_IS_ON(INFO));
    126   EXPECT_FALSE(VLOG_IS_ON(1));
    127 
    128   LOG(INFO) << mock_log_source.Log();
    129   LOG_IF(INFO, false) << mock_log_source.Log();
    130   VLOG(1) << mock_log_source.Log();
    131   VLOG_IF(1, true) << mock_log_source.Log();
    132 
    133   DLOG(INFO) << mock_log_source.Log();
    134   DLOG_IF(INFO, true) << mock_log_source.Log();
    135   DVLOG(1) << mock_log_source.Log();
    136   DVLOG_IF(1, true) << mock_log_source.Log();
    137 }
    138 
    139 TEST_F(LoggingTest, LoggingIsLazyByDestination) {
    140   MockLogSource mock_log_source;
    141   MockLogSource mock_log_source_error;
    142   EXPECT_CALL(mock_log_source, Log()).Times(0);
    143 
    144   // Severity >= ERROR is always printed to stderr.
    145   EXPECT_CALL(mock_log_source_error, Log()).Times(1).
    146       WillRepeatedly(Return("log message"));
    147 
    148   LoggingSettings settings;
    149   settings.logging_dest = LOG_NONE;
    150   InitLogging(settings);
    151 
    152   LOG(INFO) << mock_log_source.Log();
    153   LOG(WARNING) << mock_log_source.Log();
    154   LOG(ERROR) << mock_log_source_error.Log();
    155 }
    156 
    157 // Official builds have CHECKs directly call BreakDebugger.
    158 #if !defined(OFFICIAL_BUILD)
    159 
    160 TEST_F(LoggingTest, CheckStreamsAreLazy) {
    161   MockLogSource mock_log_source, uncalled_mock_log_source;
    162   EXPECT_CALL(mock_log_source, Log()).
    163       WillRepeatedly(Return("check message"));
    164   EXPECT_CALL(uncalled_mock_log_source, Log()).Times(0);
    165 
    166   SetLogAssertHandler(&LogSink);
    167 
    168   CHECK(mock_log_source.Log()) << uncalled_mock_log_source.Log();
    169   CHECK_EQ(mock_log_source.Log(), mock_log_source.Log())
    170       << uncalled_mock_log_source.Log();
    171   CHECK_NE(mock_log_source.Log(), mock_log_source.Log())
    172       << mock_log_source.Log();
    173 }
    174 
    175 #endif
    176 
    177 TEST_F(LoggingTest, DebugLoggingReleaseBehavior) {
    178 #if !defined(NDEBUG)
    179   int debug_only_variable = 1;
    180 #endif
    181   // These should avoid emitting references to |debug_only_variable|
    182   // in release mode.
    183   DLOG_IF(INFO, debug_only_variable) << "test";
    184   DLOG_ASSERT(debug_only_variable) << "test";
    185   DVLOG_IF(1, debug_only_variable) << "test";
    186 }
    187 
    188 TEST_F(LoggingTest, DcheckStreamsAreLazy) {
    189   MockLogSource mock_log_source;
    190   EXPECT_CALL(mock_log_source, Log()).Times(0);
    191 #if DCHECK_IS_ON()
    192   DCHECK(true) << mock_log_source.Log();
    193   DCHECK_EQ(0, 0) << mock_log_source.Log();
    194 #else
    195   DCHECK(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   DCHECK_EQ(0, 1);
    223   EXPECT_EQ(DCHECK_IS_ON() ? 2 : 0, log_sink_call_count);
    224 }
    225 
    226 TEST_F(LoggingTest, DcheckReleaseBehavior) {
    227   int some_variable = 1;
    228   // These should still reference |some_variable| so we don't get
    229   // unused variable warnings.
    230   DCHECK(some_variable) << "test";
    231   DCHECK_EQ(some_variable, 1) << "test";
    232 }
    233 
    234 TEST_F(LoggingTest, DCheckEqStatements) {
    235   bool reached = false;
    236   if (false)
    237     DCHECK_EQ(false, true);           // Unreached.
    238   else
    239     DCHECK_EQ(true, reached = true);  // Reached, passed.
    240   ASSERT_EQ(DCHECK_IS_ON() ? true : false, reached);
    241 
    242   if (false)
    243     DCHECK_EQ(false, true);           // Unreached.
    244 }
    245 
    246 TEST_F(LoggingTest, CheckEqStatements) {
    247   bool reached = false;
    248   if (false)
    249     CHECK_EQ(false, true);           // Unreached.
    250   else
    251     CHECK_EQ(true, reached = true);  // Reached, passed.
    252   ASSERT_TRUE(reached);
    253 
    254   if (false)
    255     CHECK_EQ(false, true);           // Unreached.
    256 }
    257 
    258 }  // namespace
    259 
    260 }  // namespace logging
    261