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
20void LogSink(const std::string& str) {
21  ++log_sink_call_count;
22}
23
24// Class to make sure any manipulations we do to the min log level are
25// contained (i.e., do not affect other unit tests).
26class LogStateSaver {
27 public:
28  LogStateSaver() : old_min_log_level_(GetMinLogLevel()) {}
29
30  ~LogStateSaver() {
31    SetMinLogLevel(old_min_log_level_);
32    SetLogAssertHandler(NULL);
33    SetLogReportHandler(NULL);
34    log_sink_call_count = 0;
35  }
36
37 private:
38  int old_min_log_level_;
39
40  DISALLOW_COPY_AND_ASSIGN(LogStateSaver);
41};
42
43class LoggingTest : public testing::Test {
44 private:
45  LogStateSaver log_state_saver_;
46};
47
48class MockLogSource {
49 public:
50  MOCK_METHOD0(Log, const char*());
51};
52
53TEST_F(LoggingTest, BasicLogging) {
54  MockLogSource mock_log_source;
55  const int kExpectedDebugOrReleaseCalls = 6;
56  const int kExpectedDebugCalls = 6;
57  const int kExpectedCalls =
58      kExpectedDebugOrReleaseCalls + (DEBUG_MODE ? kExpectedDebugCalls : 0);
59  EXPECT_CALL(mock_log_source, Log()).Times(kExpectedCalls).
60      WillRepeatedly(Return("log message"));
61
62  SetMinLogLevel(LOG_INFO);
63
64  EXPECT_TRUE(LOG_IS_ON(INFO));
65  // As of g++-4.5, the first argument to EXPECT_EQ cannot be a
66  // constant expression.
67  const bool kIsDebugMode = (DEBUG_MODE != 0);
68  EXPECT_EQ(kIsDebugMode, DLOG_IS_ON(INFO));
69  EXPECT_TRUE(VLOG_IS_ON(0));
70
71  LOG(INFO) << mock_log_source.Log();
72  LOG_IF(INFO, true) << mock_log_source.Log();
73  PLOG(INFO) << mock_log_source.Log();
74  PLOG_IF(INFO, true) << mock_log_source.Log();
75  VLOG(0) << mock_log_source.Log();
76  VLOG_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}
85
86TEST_F(LoggingTest, LogIsOn) {
87#if defined(NDEBUG)
88  const bool kDfatalIsFatal = false;
89#else  // defined(NDEBUG)
90  const bool kDfatalIsFatal = true;
91#endif  // defined(NDEBUG)
92
93  SetMinLogLevel(LOG_INFO);
94  EXPECT_TRUE(LOG_IS_ON(INFO));
95  EXPECT_TRUE(LOG_IS_ON(WARNING));
96  EXPECT_TRUE(LOG_IS_ON(ERROR));
97  EXPECT_TRUE(LOG_IS_ON(ERROR_REPORT));
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(ERROR_REPORT));
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(ERROR_REPORT));
114  EXPECT_TRUE(LOG_IS_ON(FATAL));
115  EXPECT_TRUE(LOG_IS_ON(DFATAL));
116
117  SetMinLogLevel(LOG_ERROR_REPORT);
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(ERROR_REPORT));
122  EXPECT_TRUE(LOG_IS_ON(FATAL));
123  EXPECT_EQ(kDfatalIsFatal, LOG_IS_ON(DFATAL));
124
125  // LOG_IS_ON(ERROR_REPORT) should always be true.
126  SetMinLogLevel(LOG_FATAL);
127  EXPECT_FALSE(LOG_IS_ON(INFO));
128  EXPECT_FALSE(LOG_IS_ON(WARNING));
129  EXPECT_FALSE(LOG_IS_ON(ERROR));
130  EXPECT_TRUE(LOG_IS_ON(ERROR_REPORT));
131  EXPECT_TRUE(LOG_IS_ON(FATAL));
132  EXPECT_EQ(kDfatalIsFatal, LOG_IS_ON(DFATAL));
133
134  // So should LOG_IS_ON(FATAL).
135  SetMinLogLevel(LOG_FATAL + 1);
136  EXPECT_FALSE(LOG_IS_ON(INFO));
137  EXPECT_FALSE(LOG_IS_ON(WARNING));
138  EXPECT_FALSE(LOG_IS_ON(ERROR));
139  EXPECT_TRUE(LOG_IS_ON(ERROR_REPORT));
140  EXPECT_TRUE(LOG_IS_ON(FATAL));
141  EXPECT_EQ(kDfatalIsFatal, LOG_IS_ON(DFATAL));
142}
143
144TEST_F(LoggingTest, LoggingIsLazy) {
145  MockLogSource mock_log_source;
146  EXPECT_CALL(mock_log_source, Log()).Times(0);
147
148  SetMinLogLevel(LOG_WARNING);
149
150  EXPECT_FALSE(LOG_IS_ON(INFO));
151  EXPECT_FALSE(DLOG_IS_ON(INFO));
152  EXPECT_FALSE(VLOG_IS_ON(1));
153
154  LOG(INFO) << mock_log_source.Log();
155  LOG_IF(INFO, false) << mock_log_source.Log();
156  PLOG(INFO) << mock_log_source.Log();
157  PLOG_IF(INFO, false) << mock_log_source.Log();
158  VLOG(1) << mock_log_source.Log();
159  VLOG_IF(1, true) << mock_log_source.Log();
160
161  DLOG(INFO) << mock_log_source.Log();
162  DLOG_IF(INFO, true) << mock_log_source.Log();
163  DPLOG(INFO) << mock_log_source.Log();
164  DPLOG_IF(INFO, true) << mock_log_source.Log();
165  DVLOG(1) << mock_log_source.Log();
166  DVLOG_IF(1, true) << mock_log_source.Log();
167}
168
169TEST_F(LoggingTest, CheckStreamsAreLazy) {
170  MockLogSource mock_log_source, uncalled_mock_log_source;
171  EXPECT_CALL(mock_log_source, Log()).Times(8).
172      WillRepeatedly(Return("check message"));
173  EXPECT_CALL(uncalled_mock_log_source, Log()).Times(0);
174
175  SetLogAssertHandler(&LogSink);
176
177  CHECK(mock_log_source.Log()) << uncalled_mock_log_source.Log();
178  PCHECK(!mock_log_source.Log()) << mock_log_source.Log();
179  CHECK_EQ(mock_log_source.Log(), mock_log_source.Log())
180      << uncalled_mock_log_source.Log();
181  CHECK_NE(mock_log_source.Log(), mock_log_source.Log())
182      << mock_log_source.Log();
183}
184
185TEST_F(LoggingTest, DebugLoggingReleaseBehavior) {
186#if !defined(NDEBUG)
187  int debug_only_variable = 1;
188#endif
189  // These should avoid emitting references to |debug_only_variable|
190  // in release mode.
191  DLOG_IF(INFO, debug_only_variable) << "test";
192  DLOG_ASSERT(debug_only_variable) << "test";
193  DPLOG_IF(INFO, debug_only_variable) << "test";
194  DVLOG_IF(1, debug_only_variable) << "test";
195}
196
197TEST_F(LoggingTest, DcheckStreamsAreLazy) {
198  MockLogSource mock_log_source;
199  EXPECT_CALL(mock_log_source, Log()).Times(0);
200
201#if !defined(LOGGING_IS_OFFICIAL_BUILD) && defined(NDEBUG)
202  // Unofficial release build.
203  g_dcheck_state = DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS;
204  DCHECK(mock_log_source.Log()) << mock_log_source.Log();
205  DPCHECK(mock_log_source.Log()) << mock_log_source.Log();
206  DCHECK_EQ(0, 0) << mock_log_source.Log();
207  DCHECK_EQ(mock_log_source.Log(), static_cast<const char*>(NULL))
208      << mock_log_source.Log();
209#endif  // !defined(LOGGING_IS_OFFICIAL_BUILD) && defined(NDEBUG)
210}
211
212TEST_F(LoggingTest, Dcheck) {
213#if defined(LOGGING_IS_OFFICIAL_BUILD)
214  // Official build.
215  EXPECT_FALSE(DCHECK_IS_ON());
216  EXPECT_FALSE(DLOG_IS_ON(DCHECK));
217#elif defined(NDEBUG)
218  // Unofficial release build.
219  g_dcheck_state = ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS;
220  SetLogReportHandler(&LogSink);
221  EXPECT_TRUE(DCHECK_IS_ON());
222  EXPECT_FALSE(DLOG_IS_ON(DCHECK));
223#else
224  // Unofficial debug build.
225  SetLogAssertHandler(&LogSink);
226  EXPECT_TRUE(DCHECK_IS_ON());
227  EXPECT_TRUE(DLOG_IS_ON(DCHECK));
228#endif  // defined(LOGGING_IS_OFFICIAL_BUILD)
229
230  EXPECT_EQ(0, log_sink_call_count);
231  DCHECK(false);
232  EXPECT_EQ(DCHECK_IS_ON() ? 1 : 0, log_sink_call_count);
233  DPCHECK(false);
234  EXPECT_EQ(DCHECK_IS_ON() ? 2 : 0, log_sink_call_count);
235  DCHECK_EQ(0, 1);
236  EXPECT_EQ(DCHECK_IS_ON() ? 3 : 0, log_sink_call_count);
237}
238
239TEST_F(LoggingTest, DcheckReleaseBehavior) {
240  int some_variable = 1;
241  // These should still reference |some_variable| so we don't get
242  // unused variable warnings.
243  DCHECK(some_variable) << "test";
244  DPCHECK(some_variable) << "test";
245  DCHECK_EQ(some_variable, 1) << "test";
246}
247
248}  // namespace
249
250}  // namespace logging
251