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
12namespace logging {
13
14namespace {
15
16using ::testing::Return;
17
18// Needs to be global since log assert handlers can't maintain state.
19int log_sink_call_count = 0;
20
21#if !defined(OFFICIAL_BUILD) || defined(DCHECK_ALWAYS_ON) || !defined(NDEBUG)
22void 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).
29class 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
45class LoggingTest : public testing::Test {
46 private:
47  LogStateSaver log_state_saver_;
48};
49
50class MockLogSource {
51 public:
52  MOCK_METHOD0(Log, const char*());
53};
54
55TEST_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
88TEST_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
125TEST_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
154TEST_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
175TEST_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
193TEST_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
205TEST_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
220TEST_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
263TEST_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
272TEST_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
284TEST_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.
301namespace 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