1 // 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
20 namespace android {
21 namespace base {
22
23 // Create a severity level which is guaranteed to never generate a log
24 // message. See LogOnlyEvaluatesArgumentsIfNeeded for usage.
25 const LogSeverity LOG_INVISIBLE = -10000;
26
27 class LogTest : public ::testing::Test, android::base::testing::LogOutput {
28 public:
LogTest()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 }
35
~LogTest()36 ~LogTest() {
37 ::android::base::testing::LogOutput::setNewOutput(mSavedOutput);
38 }
39
setExpected(LogSeverity severity,int line,const char * suffix)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
logMessage(const LogParams & params,const char * message,size_t messageLen)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
59 protected:
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
68 class CheckTest : public LogTest {
69 };
70
71 #if ENABLE_DCHECK != 0
72 class DCheckEnabledTest : public LogTest {
73 public:
DCheckEnabledTest()74 DCheckEnabledTest() : LogTest() {
75 // Ensure DCHECKS() always run.
76 mSavedLevel = setDcheckLevel(true);
77 }
78
~DCheckEnabledTest()79 ~DCheckEnabledTest() {
80 setDcheckLevel(mSavedLevel);
81 }
82 private:
83 bool mSavedLevel;
84 };
85 #endif // ENABLE_DCHECK == 0
86
87 #if ENABLE_DCHECK != 2
88 class DCheckDisabledTest : public LogTest {
89 public:
DCheckDisabledTest()90 DCheckDisabledTest() : LogTest() {
91 mSavedLevel = setDcheckLevel(false);
92 }
93
~DCheckDisabledTest()94 ~DCheckDisabledTest() {
95 setDcheckLevel(mSavedLevel);
96 }
97 private:
98 bool mSavedLevel;
99 };
100 #endif // ENABLE_DCHECK != 2
101
102 class PLogTest : public LogTest {
103 public:
PLogTest()104 PLogTest() : LogTest(), mForcedErrno(-1000) {}
105
setForcedErrno(int errnoCode)106 void setForcedErrno(int errnoCode) {
107 mForcedErrno = errnoCode;
108 }
109
setExpectedErrno(LogSeverity severity,int line,int errnoCode,const char * suffix)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",
120 suffix,
121 strerror(errnoCode));
122 }
123
logMessage(const LogParams & params,const char * message,size_t messageLen)124 void logMessage(const LogParams& params,
125 const char* message,
126 size_t messageLen) {
127 LogTest::logMessage(params, message, messageLen);
128
129 if (mForcedErrno != -1000)
130 errno = mForcedErrno;
131 }
132
133 protected:
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|.
setFlag(bool * flag,const char * string)150 static const char* setFlag(bool* flag, const char* string) {
151 *flag = true;
152 return string;
153 }
154
TEST(LogString,EmptyString)155 TEST(LogString, EmptyString) {
156 LogString ls("");
157 EXPECT_STREQ("", ls.string());
158 }
159
TEST(LogString,SimpleString)160 TEST(LogString, SimpleString) {
161 LogString ls("Hello");
162 EXPECT_STREQ("Hello", ls.string());
163 }
164
TEST(LogString,FormattedString)165 TEST(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
TEST_F(LogTest,LogInfoEmpty)170 TEST_F(LogTest, LogInfoEmpty) {
171 setExpected(LOG_INFO, __LINE__ + 1, "");
172 LOG(INFO);
173 CHECK_EXPECTATIONS();
174 }
175
TEST_F(LogTest,LogInfoWithString)176 TEST_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
TEST_F(LogTest,LogInfoWithTwoStrings)183 TEST_F(LogTest, LogInfoWithTwoStrings) {
184 setExpected(LOG_INFO, __LINE__ + 1, "Hello Globe!");
185 LOG(INFO) << "Hello " << "Globe!";
186 CHECK_EXPECTATIONS();
187 }
188
TEST_F(LogTest,LogInfoWithLogString)189 TEST_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
TEST_F(LogTest,LogWarning)196 TEST_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
TEST_F(LogTest,LogError)203 TEST_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
TEST_F(LogTest,LogFatal)211 TEST_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
TEST_F(LogTest,LogEvaluatesArgumentsIfNeeded)219 TEST_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
TEST_F(LogTest,LogOnlyEvaluatesArgumentsIfNeeded)229 TEST_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.
TEST_F(CheckTest,CheckFalse)238 TEST_F(CheckTest, CheckFalse) {
239 setExpected(LOG_FATAL, __LINE__ + 1, "Check failed: false. ");
240 CHECK(false);
241 CHECK_EXPECTATIONS();
242 }
243
TEST_F(CheckTest,CheckFalseEvaluatesArguments)244 TEST_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
TEST_F(CheckTest,CheckTrue)252 TEST_F(CheckTest, CheckTrue) {
253 CHECK(true);
254 EXPECT_FALSE(mFatal);
255 }
256
TEST_F(CheckTest,CheckTrueDoesNotEvaluateArguments)257 TEST_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
TEST_F(DCheckEnabledTest,DCheckIsOnReturnsTrue)265 TEST_F(DCheckEnabledTest, DCheckIsOnReturnsTrue) {
266 EXPECT_TRUE(DCHECK_IS_ON());
267 }
268
TEST_F(DCheckEnabledTest,DCheckFalse)269 TEST_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
TEST_F(DCheckEnabledTest,DCheckTrue)276 TEST_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
TEST_F(DCheckDisabledTest,DCheckIsOnReturnsFalse)285 TEST_F(DCheckDisabledTest, DCheckIsOnReturnsFalse) {
286 EXPECT_FALSE(DCHECK_IS_ON());
287 }
288
TEST_F(DCheckDisabledTest,DCheckFalse)289 TEST_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
TEST_F(DCheckDisabledTest,DCheckTrue)296 TEST_F(DCheckDisabledTest, DCheckTrue) {
297 DCHECK(true);
298 }
299 #endif // ENABLE_DCHECK != 2
300
TEST_F(PLogTest,PLogInfoEmpty)301 TEST_F(PLogTest, PLogInfoEmpty) {
302 setExpectedErrno(LOG_INFO, __LINE__ + 2, EINVAL, "");
303 errno = EINVAL;
304 PLOG(INFO);
305 CHECK_EXPECTATIONS();
306 }
307
TEST_F(PLogTest,PLogInfoPreservesErrno)308 TEST_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
322