blob: fd25efb93f37befe4a97c832453c9bf8a4cd63f7 [file] [log] [blame]
David 'Digit' Turner7a41eef2014-02-07 15:56:41 +01001// Copyright 2014 The Android Open Source Project
2//
3// This software is licensed under the terms of the GNU General Public
4// License version 2, as published by the Free Software Foundation, and
5// may be copied, distributed, and modified under those terms.
6//
7// This program is distributed in the hope that it will be useful,
8// but WITHOUT ANY WARRANTY; without even the implied warranty of
9// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10// GNU General Public License for more details.
11
12#include "android/base/Log.h"
13
14#include <errno.h>
15#include <stdio.h>
16#include <string.h>
17
18#include <gtest/gtest.h>
19
20namespace android {
21namespace base {
22
23// Create a severity level which is guaranteed to never generate a log
24// message. See LogOnlyEvaluatesArgumentsIfNeeded for usage.
David 'Digit' Turnerc0052462014-02-25 18:39:29 +010025const LogSeverity LOG_INVISIBLE = -10000;
26
David 'Digit' Turner7a41eef2014-02-07 15:56:41 +010027class LogTest : public ::testing::Test, android::base::testing::LogOutput {
28public:
29 LogTest() : mFatal(false) {
30 mSavedOutput = ::android::base::testing::LogOutput::setNewOutput(this);
31 mExpected[0] = '\0';
32 mBuffer[0] = '\x7f';
33 mBuffer[1] = '\0';
34 }
David 'Digit' Turnerc0052462014-02-25 18:39:29 +010035
David 'Digit' Turner7a41eef2014-02-07 15:56:41 +010036 ~LogTest() {
37 ::android::base::testing::LogOutput::setNewOutput(mSavedOutput);
38 }
39
40 void setExpected(LogSeverity severity, int line, const char* suffix) {
41 mExpectedParams.file = __FILE__;
42 mExpectedParams.lineno = line;
43 mExpectedParams.severity = severity;
44 snprintf(mExpected, sizeof(mExpected), "%s", suffix);
45 }
46
47 // LogOutput override
48 void logMessage(const LogParams& params,
49 const char* message,
50 size_t messageLen) {
51 mParams = params;
52 if (messageLen > sizeof(mBuffer) - 1)
53 messageLen = sizeof(mBuffer) - 1;
54 ::memcpy(mBuffer, message, messageLen);
55 mBuffer[messageLen] = '\0';
56 mFatal = (params.severity >= LOG_FATAL);
57 }
58
59protected:
60 ::android::base::testing::LogOutput* mSavedOutput;
61 LogParams mParams;
62 LogParams mExpectedParams;
63 char mExpected[1024];
64 char mBuffer[1024];
65 bool mFatal;
66};
67
68class CheckTest : public LogTest {
69};
70
71#if ENABLE_DCHECK != 0
72class DCheckEnabledTest : public LogTest {
David 'Digit' Turnerc0052462014-02-25 18:39:29 +010073public:
David 'Digit' Turner7a41eef2014-02-07 15:56:41 +010074 DCheckEnabledTest() : LogTest() {
75 // Ensure DCHECKS() always run.
76 mSavedLevel = setDcheckLevel(true);
77 }
David 'Digit' Turnerc0052462014-02-25 18:39:29 +010078
David 'Digit' Turner7a41eef2014-02-07 15:56:41 +010079 ~DCheckEnabledTest() {
80 setDcheckLevel(mSavedLevel);
81 }
82private:
83 bool mSavedLevel;
84};
85#endif // ENABLE_DCHECK == 0
86
87#if ENABLE_DCHECK != 2
88class DCheckDisabledTest : public LogTest {
89public:
90 DCheckDisabledTest() : LogTest() {
91 mSavedLevel = setDcheckLevel(false);
92 }
David 'Digit' Turnerc0052462014-02-25 18:39:29 +010093
David 'Digit' Turner7a41eef2014-02-07 15:56:41 +010094 ~DCheckDisabledTest() {
95 setDcheckLevel(mSavedLevel);
96 }
97private:
98 bool mSavedLevel;
99};
100#endif // ENABLE_DCHECK != 2
101
102class PLogTest : public LogTest {
103public:
104 PLogTest() : LogTest(), mForcedErrno(-1000) {}
105
106 void setForcedErrno(int errnoCode) {
107 mForcedErrno = errnoCode;
108 }
109
110 void setExpectedErrno(LogSeverity severity,
111 int line,
112 int errnoCode,
113 const char* suffix) {
114 mExpectedParams.file = __FILE__;
115 mExpectedParams.lineno = line;
116 mExpectedParams.severity = severity;
117 snprintf(mExpected,
118 sizeof(mExpected),
119 "%sError message: %s",
David 'Digit' Turnerc0052462014-02-25 18:39:29 +0100120 suffix,
David 'Digit' Turner7a41eef2014-02-07 15:56:41 +0100121 strerror(errnoCode));
122 }
123
124 void logMessage(const LogParams& params,
125 const char* message,
126 size_t messageLen) {
127 LogTest::logMessage(params, message, messageLen);
David 'Digit' Turnerc0052462014-02-25 18:39:29 +0100128
David 'Digit' Turner7a41eef2014-02-07 15:56:41 +0100129 if (mForcedErrno != -1000)
130 errno = mForcedErrno;
131 }
132
133protected:
134 int mForcedErrno;
135};
136
137#define STRINGIFY(x) STRINGIFY_(x)
138#define STRINGIFY_(x) #x
139
140#define EXPECTED_STRING_PREFIX(prefix, line) \
141 prefix ":" __FILE__ ":" STRINGIFY(line) ": "
142
143#define CHECK_EXPECTATIONS() \
144 EXPECT_STREQ(mExpectedParams.file, mParams.file); \
145 EXPECT_EQ(mExpectedParams.lineno, mParams.lineno); \
146 EXPECT_EQ(mExpectedParams.severity, mParams.severity); \
147 EXPECT_STREQ(mExpected, mBuffer)
148
149// Helper function used to set a boolean |flag|, then return |string|.
150static const char* setFlag(bool* flag, const char* string) {
151 *flag = true;
152 return string;
153}
154
155TEST(LogString, EmptyString) {
156 LogString ls("");
157 EXPECT_STREQ("", ls.string());
158}
159
160TEST(LogString, SimpleString) {
161 LogString ls("Hello");
162 EXPECT_STREQ("Hello", ls.string());
163}
164
165TEST(LogString, FormattedString) {
166 LogString ls("%d plus %d equals %d", 12, 23, 35);
167 EXPECT_STREQ("12 plus 23 equals 35", ls.string());
168}
169
170TEST_F(LogTest, LogInfoEmpty) {
171 setExpected(LOG_INFO, __LINE__ + 1, "");
172 LOG(INFO);
173 CHECK_EXPECTATIONS();
174}
175
176TEST_F(LogTest, LogInfoWithString) {
177 static const char kString[] = "Hello World!";
178 setExpected(LOG_INFO, __LINE__ + 1, kString);
179 LOG(INFO) << kString;
180 CHECK_EXPECTATIONS();
181}
182
183TEST_F(LogTest, LogInfoWithTwoStrings) {
184 setExpected(LOG_INFO, __LINE__ + 1, "Hello Globe!");
185 LOG(INFO) << "Hello " << "Globe!";
186 CHECK_EXPECTATIONS();
187}
188
189TEST_F(LogTest, LogInfoWithLogString) {
190 LogString ls("Hello You!");
191 setExpected(LOG_INFO, __LINE__ + 1, ls.string());
192 LOG(INFO) << ls;
193 CHECK_EXPECTATIONS();
194}
195
196TEST_F(LogTest, LogWarning) {
197 static const char kWarning[] = "Elvis has left the building!";
198 setExpected(LOG_WARNING, __LINE__ + 1, kWarning);
199 LOG(WARNING) << kWarning;
200 CHECK_EXPECTATIONS();
201}
202
203TEST_F(LogTest, LogError) {
204 static const char kError[] = "Bad Bad Robot!";
205 setExpected(LOG_ERROR, __LINE__ + 1, kError);
206 LOG(ERROR) << kError;
207
208 CHECK_EXPECTATIONS();
209}
210
211TEST_F(LogTest, LogFatal) {
212 static const char kFatalMessage[] = "I'm dying";
213 setExpected(LOG_FATAL, __LINE__ + 1, kFatalMessage);
214 LOG(FATAL) << kFatalMessage;
215 CHECK_EXPECTATIONS();
216 EXPECT_TRUE(mFatal);
217}
218
219TEST_F(LogTest, LogEvaluatesArgumentsIfNeeded) {
220 // Use LOG_FATAL since it is always active.
221 bool flag = false;
222 setExpected(LOG_FATAL, __LINE__ + 1, "PANIC: Flag was set!");
223 LOG(FATAL) << "PANIC: " << setFlag(&flag, "Flag was set!");
224 CHECK_EXPECTATIONS();
225 EXPECT_TRUE(mFatal);
226 EXPECT_TRUE(flag);
227}
228
229TEST_F(LogTest, LogOnlyEvaluatesArgumentsIfNeeded) {
230 bool flag = false;
231 LOG(INVISIBLE) << setFlag(&flag, "Flag was set!");
232 EXPECT_FALSE(flag);
233}
234
235
236// TODO(digit): Convert this to a real death test when this is supported
237// by our version of GTest.
238TEST_F(CheckTest, CheckFalse) {
239 setExpected(LOG_FATAL, __LINE__ + 1, "Check failed: false. ");
240 CHECK(false);
241 CHECK_EXPECTATIONS();
242}
243
244TEST_F(CheckTest, CheckFalseEvaluatesArguments) {
245 bool flag = false;
246 setExpected(LOG_FATAL, __LINE__ + 1, "Check failed: false. Flag was set!");
247 CHECK(false) << setFlag(&flag, "Flag was set!");
248 EXPECT_TRUE(flag);
249 CHECK_EXPECTATIONS();
250}
251
252TEST_F(CheckTest, CheckTrue) {
253 CHECK(true);
254 EXPECT_FALSE(mFatal);
255}
256
257TEST_F(CheckTest, CheckTrueDoesNotEvaluateArguments) {
258 bool flag = false;
259 CHECK(true) << setFlag(&flag, "Flag was set!");
260 EXPECT_FALSE(flag);
261 EXPECT_FALSE(mFatal);
262}
263
264#if ENABLE_DCHECK != 0
265TEST_F(DCheckEnabledTest, DCheckIsOnReturnsTrue) {
266 EXPECT_TRUE(DCHECK_IS_ON());
267}
268
269TEST_F(DCheckEnabledTest, DCheckFalse) {
270 bool flag = false;
271 setExpected(LOG_FATAL, __LINE__ + 1, "Check failed: false. Flag was set!");
272 DCHECK(false) << setFlag(&flag, "Flag was set!");
273 CHECK_EXPECTATIONS();
274}
275
276TEST_F(DCheckEnabledTest, DCheckTrue) {
277 bool flag = false;
278 DCHECK(true) << setFlag(&flag, "Flag was set!");
279 EXPECT_FALSE(flag);
280 EXPECT_FALSE(mFatal);
281}
282#endif // ENABLE_DCHECK != 0
283
284#if ENABLE_DCHECK != 2
285TEST_F(DCheckDisabledTest, DCheckIsOnReturnsFalse) {
286 EXPECT_FALSE(DCHECK_IS_ON());
287}
288
289TEST_F(DCheckDisabledTest, DCheckFalse) {
290 bool flag = false;
291 DCHECK(false) << setFlag(&flag, "Flag was set!");
292 EXPECT_FALSE(flag);
293 EXPECT_FALSE(mFatal);
294}
295
296TEST_F(DCheckDisabledTest, DCheckTrue) {
297 DCHECK(true);
298}
299#endif // ENABLE_DCHECK != 2
300
301TEST_F(PLogTest, PLogInfoEmpty) {
302 setExpectedErrno(LOG_INFO, __LINE__ + 2, EINVAL, "");
303 errno = EINVAL;
304 PLOG(INFO);
305 CHECK_EXPECTATIONS();
306}
307
308TEST_F(PLogTest, PLogInfoPreservesErrno) {
309 // Select a value that is unlikely to ever be raised by the logging
310 // machinery.
311 const int kErrnoCode = ENOEXEC;
312 setForcedErrno(EINVAL);
313 setExpectedErrno(LOG_INFO, __LINE__ + 2, kErrnoCode, "Hi");
314 errno = kErrnoCode;
315 PLOG(INFO) << "Hi";
316 EXPECT_EQ(kErrnoCode, errno);
317 CHECK_EXPECTATIONS();
318}
319
320} // namespace base
321} // namespace android