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/basictypes.h"
6#include "base/logging.h"
7
8#include "testing/gmock/include/gmock/gmock.h"
9#include "testing/gtest/include/gtest/gtest.h"
10
11namespace logging {
12
13namespace {
14
15using ::testing::Return;
16
17// Needs to be global since log assert handlers can't maintain state.
18int log_sink_call_count = 0;
19
20#if !defined(OFFICIAL_BUILD) || defined(DCHECK_ALWAYS_ON) || !defined(NDEBUG)
21void LogSink(const std::string& str) {
22  ++log_sink_call_count;
23}
24#endif
25
26// Class to make sure any manipulations we do to the min log level are
27// contained (i.e., do not affect other unit tests).
28class LogStateSaver {
29 public:
30  LogStateSaver() : old_min_log_level_(GetMinLogLevel()) {}
31
32  ~LogStateSaver() {
33    SetMinLogLevel(old_min_log_level_);
34    SetLogAssertHandler(NULL);
35    log_sink_call_count = 0;
36  }
37
38 private:
39  int old_min_log_level_;
40
41  DISALLOW_COPY_AND_ASSIGN(LogStateSaver);
42};
43
44class LoggingTest : public testing::Test {
45 private:
46  LogStateSaver log_state_saver_;
47};
48
49class MockLogSource {
50 public:
51  MOCK_METHOD0(Log, const char*());
52};
53
54TEST_F(LoggingTest, BasicLogging) {
55  MockLogSource mock_log_source;
56  EXPECT_CALL(mock_log_source, Log()).Times(DEBUG_MODE ? 16 : 8).
57      WillRepeatedly(Return("log message"));
58
59  SetMinLogLevel(LOG_INFO);
60
61  EXPECT_TRUE(LOG_IS_ON(INFO));
62  // As of g++-4.5, the first argument to EXPECT_EQ cannot be a
63  // constant expression.
64  const bool kIsDebugMode = (DEBUG_MODE != 0);
65  EXPECT_TRUE(kIsDebugMode == DLOG_IS_ON(INFO));
66  EXPECT_TRUE(VLOG_IS_ON(0));
67
68  LOG(INFO) << mock_log_source.Log();
69  LOG_IF(INFO, true) << mock_log_source.Log();
70  PLOG(INFO) << mock_log_source.Log();
71  PLOG_IF(INFO, true) << mock_log_source.Log();
72  VLOG(0) << mock_log_source.Log();
73  VLOG_IF(0, true) << mock_log_source.Log();
74  VPLOG(0) << mock_log_source.Log();
75  VPLOG_IF(0, true) << mock_log_source.Log();
76
77  DLOG(INFO) << mock_log_source.Log();
78  DLOG_IF(INFO, true) << mock_log_source.Log();
79  DPLOG(INFO) << mock_log_source.Log();
80  DPLOG_IF(INFO, true) << mock_log_source.Log();
81  DVLOG(0) << mock_log_source.Log();
82  DVLOG_IF(0, true) << mock_log_source.Log();
83  DVPLOG(0) << mock_log_source.Log();
84  DVPLOG_IF(0, true) << mock_log_source.Log();
85}
86
87TEST_F(LoggingTest, LogIsOn) {
88#if defined(NDEBUG)
89  const bool kDfatalIsFatal = false;
90#else  // defined(NDEBUG)
91  const bool kDfatalIsFatal = true;
92#endif  // defined(NDEBUG)
93
94  SetMinLogLevel(LOG_INFO);
95  EXPECT_TRUE(LOG_IS_ON(INFO));
96  EXPECT_TRUE(LOG_IS_ON(WARNING));
97  EXPECT_TRUE(LOG_IS_ON(ERROR));
98  EXPECT_TRUE(LOG_IS_ON(FATAL));
99  EXPECT_TRUE(LOG_IS_ON(DFATAL));
100
101  SetMinLogLevel(LOG_WARNING);
102  EXPECT_FALSE(LOG_IS_ON(INFO));
103  EXPECT_TRUE(LOG_IS_ON(WARNING));
104  EXPECT_TRUE(LOG_IS_ON(ERROR));
105  EXPECT_TRUE(LOG_IS_ON(FATAL));
106  EXPECT_TRUE(LOG_IS_ON(DFATAL));
107
108  SetMinLogLevel(LOG_ERROR);
109  EXPECT_FALSE(LOG_IS_ON(INFO));
110  EXPECT_FALSE(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  // LOG_IS_ON(FATAL) should always be true.
116  SetMinLogLevel(LOG_FATAL + 1);
117  EXPECT_FALSE(LOG_IS_ON(INFO));
118  EXPECT_FALSE(LOG_IS_ON(WARNING));
119  EXPECT_FALSE(LOG_IS_ON(ERROR));
120  EXPECT_TRUE(LOG_IS_ON(FATAL));
121  EXPECT_TRUE(kDfatalIsFatal == LOG_IS_ON(DFATAL));
122}
123
124TEST_F(LoggingTest, LoggingIsLazy) {
125  MockLogSource mock_log_source;
126  EXPECT_CALL(mock_log_source, Log()).Times(0);
127
128  SetMinLogLevel(LOG_WARNING);
129
130  EXPECT_FALSE(LOG_IS_ON(INFO));
131  EXPECT_FALSE(DLOG_IS_ON(INFO));
132  EXPECT_FALSE(VLOG_IS_ON(1));
133
134  LOG(INFO) << mock_log_source.Log();
135  LOG_IF(INFO, false) << mock_log_source.Log();
136  PLOG(INFO) << mock_log_source.Log();
137  PLOG_IF(INFO, false) << mock_log_source.Log();
138  VLOG(1) << mock_log_source.Log();
139  VLOG_IF(1, true) << mock_log_source.Log();
140  VPLOG(1) << mock_log_source.Log();
141  VPLOG_IF(1, true) << mock_log_source.Log();
142
143  DLOG(INFO) << mock_log_source.Log();
144  DLOG_IF(INFO, true) << mock_log_source.Log();
145  DPLOG(INFO) << mock_log_source.Log();
146  DPLOG_IF(INFO, true) << mock_log_source.Log();
147  DVLOG(1) << mock_log_source.Log();
148  DVLOG_IF(1, true) << mock_log_source.Log();
149  DVPLOG(1) << mock_log_source.Log();
150  DVPLOG_IF(1, true) << mock_log_source.Log();
151}
152
153// Official builds have CHECKs directly call BreakDebugger.
154#if !defined(OFFICIAL_BUILD)
155
156TEST_F(LoggingTest, CheckStreamsAreLazy) {
157  MockLogSource mock_log_source, uncalled_mock_log_source;
158  EXPECT_CALL(mock_log_source, Log()).Times(8).
159      WillRepeatedly(Return("check message"));
160  EXPECT_CALL(uncalled_mock_log_source, Log()).Times(0);
161
162  SetLogAssertHandler(&LogSink);
163
164  CHECK(mock_log_source.Log()) << uncalled_mock_log_source.Log();
165  PCHECK(!mock_log_source.Log()) << mock_log_source.Log();
166  CHECK_EQ(mock_log_source.Log(), mock_log_source.Log())
167      << uncalled_mock_log_source.Log();
168  CHECK_NE(mock_log_source.Log(), mock_log_source.Log())
169      << mock_log_source.Log();
170}
171
172#endif
173
174TEST_F(LoggingTest, DebugLoggingReleaseBehavior) {
175#if !defined(NDEBUG)
176  int debug_only_variable = 1;
177#endif
178  // These should avoid emitting references to |debug_only_variable|
179  // in release mode.
180  DLOG_IF(INFO, debug_only_variable) << "test";
181  DLOG_ASSERT(debug_only_variable) << "test";
182  DPLOG_IF(INFO, debug_only_variable) << "test";
183  DVLOG_IF(1, debug_only_variable) << "test";
184}
185
186TEST_F(LoggingTest, DcheckStreamsAreLazy) {
187  MockLogSource mock_log_source;
188  EXPECT_CALL(mock_log_source, Log()).Times(0);
189#if DCHECK_IS_ON
190  DCHECK(true) << mock_log_source.Log();
191  DCHECK_EQ(0, 0) << mock_log_source.Log();
192#else
193  DCHECK(mock_log_source.Log()) << mock_log_source.Log();
194  DPCHECK(mock_log_source.Log()) << mock_log_source.Log();
195  DCHECK_EQ(0, 0) << mock_log_source.Log();
196  DCHECK_EQ(mock_log_source.Log(), static_cast<const char*>(NULL))
197      << mock_log_source.Log();
198#endif
199}
200
201TEST_F(LoggingTest, Dcheck) {
202#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
203  // Release build.
204  EXPECT_FALSE(DCHECK_IS_ON);
205  EXPECT_FALSE(DLOG_IS_ON(DCHECK));
206#elif defined(NDEBUG) && defined(DCHECK_ALWAYS_ON)
207  // Release build with real DCHECKS.
208  SetLogAssertHandler(&LogSink);
209  EXPECT_TRUE(DCHECK_IS_ON);
210  EXPECT_FALSE(DLOG_IS_ON(DCHECK));
211#else
212  // Debug build.
213  SetLogAssertHandler(&LogSink);
214  EXPECT_TRUE(DCHECK_IS_ON);
215  EXPECT_TRUE(DLOG_IS_ON(DCHECK));
216#endif
217
218  EXPECT_EQ(0, log_sink_call_count);
219  DCHECK(false);
220  EXPECT_EQ(DCHECK_IS_ON ? 1 : 0, log_sink_call_count);
221  DPCHECK(false);
222  EXPECT_EQ(DCHECK_IS_ON ? 2 : 0, log_sink_call_count);
223  DCHECK_EQ(0, 1);
224  EXPECT_EQ(DCHECK_IS_ON ? 3 : 0, log_sink_call_count);
225}
226
227TEST_F(LoggingTest, DcheckReleaseBehavior) {
228  int some_variable = 1;
229  // These should still reference |some_variable| so we don't get
230  // unused variable warnings.
231  DCHECK(some_variable) << "test";
232  DPCHECK(some_variable) << "test";
233  DCHECK_EQ(some_variable, 1) << "test";
234}
235
236// Test that defining an operator<< for a type in a namespace doesn't prevent
237// other code in that namespace from calling the operator<<(ostream, wstring)
238// defined by logging.h. This can fail if operator<<(ostream, wstring) can't be
239// found by ADL, since defining another operator<< prevents name lookup from
240// looking in the global namespace.
241namespace nested_test {
242  class Streamable {};
243  ALLOW_UNUSED std::ostream& operator<<(std::ostream& out, const Streamable&) {
244    return out << "Streamable";
245  }
246  TEST_F(LoggingTest, StreamingWstringFindsCorrectOperator) {
247    std::wstring wstr = L"Hello World";
248    std::ostringstream ostr;
249    ostr << wstr;
250    EXPECT_EQ("Hello World", ostr.str());
251  }
252}  // namespace nested_test
253
254}  // namespace
255
256}  // namespace logging
257