• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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