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: 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 36 ~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 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: 74 DCheckEnabledTest() : LogTest() { 75 // Ensure DCHECKS() always run. 76 mSavedLevel = setDcheckLevel(true); 77 } 78 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: 90 DCheckDisabledTest() : LogTest() { 91 mSavedLevel = setDcheckLevel(false); 92 } 93 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: 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", 120 suffix, 121 strerror(errnoCode)); 122 } 123 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|. 150 static const char* setFlag(bool* flag, const char* string) { 151 *flag = true; 152 return string; 153 } 154 155 TEST(LogString, EmptyString) { 156 LogString ls(""); 157 EXPECT_STREQ("", ls.string()); 158 } 159 160 TEST(LogString, SimpleString) { 161 LogString ls("Hello"); 162 EXPECT_STREQ("Hello", ls.string()); 163 } 164 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 170 TEST_F(LogTest, LogInfoEmpty) { 171 setExpected(LOG_INFO, __LINE__ + 1, ""); 172 LOG(INFO); 173 CHECK_EXPECTATIONS(); 174 } 175 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 183 TEST_F(LogTest, LogInfoWithTwoStrings) { 184 setExpected(LOG_INFO, __LINE__ + 1, "Hello Globe!"); 185 LOG(INFO) << "Hello " << "Globe!"; 186 CHECK_EXPECTATIONS(); 187 } 188 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 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 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 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 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 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. 238 TEST_F(CheckTest, CheckFalse) { 239 setExpected(LOG_FATAL, __LINE__ + 1, "Check failed: false. "); 240 CHECK(false); 241 CHECK_EXPECTATIONS(); 242 } 243 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 252 TEST_F(CheckTest, CheckTrue) { 253 CHECK(true); 254 EXPECT_FALSE(mFatal); 255 } 256 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 265 TEST_F(DCheckEnabledTest, DCheckIsOnReturnsTrue) { 266 EXPECT_TRUE(DCHECK_IS_ON()); 267 } 268 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 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 285 TEST_F(DCheckDisabledTest, DCheckIsOnReturnsFalse) { 286 EXPECT_FALSE(DCHECK_IS_ON()); 287 } 288 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 296 TEST_F(DCheckDisabledTest, DCheckTrue) { 297 DCHECK(true); 298 } 299 #endif // ENABLE_DCHECK != 2 300 301 TEST_F(PLogTest, PLogInfoEmpty) { 302 setExpectedErrno(LOG_INFO, __LINE__ + 2, EINVAL, ""); 303 errno = EINVAL; 304 PLOG(INFO); 305 CHECK_EXPECTATIONS(); 306 } 307 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