1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include <array> 17#include <cstdlib> 18#include <ctime> 19#include <iostream> 20#include <sstream> 21#include <string> 22 23#include <unistd.h> 24 25#include <gtest/gtest.h> 26 27#include "hilog/log.h" 28#include "parameters.h" 29 30#undef LOG_DOMAIN 31#define LOG_DOMAIN 0xD002D00 32 33#undef LOG_TAG 34#define LOG_TAG "HILOGTEST_C" 35 36using namespace testing::ext; 37 38namespace OHOS { 39namespace HiviewDFX { 40namespace HiLogTest { 41const HiLogLabel APP_LABEL = { LOG_APP, 0x002a, "HILOGTEST_CPP" }; 42const HiLogLabel LABEL = { LOG_CORE, 0xD002D00, "HILOGTEST_CPP" }; 43const HiLogLabel ILLEGAL_DOMAIN_LABEL = { LOG_CORE, 0xD00EEEE, "HILOGTEST_CPP" }; 44static constexpr unsigned int SOME_LOGS = 10; 45static constexpr unsigned int MORE_LOGS = 100; 46static constexpr unsigned int OVER_LOGS = 1000; 47 48enum LogInterfaceType { 49 DEBUG_METHOD = 0, 50 INFO_METHOD = 1, 51 WARN_METHOD = 2, 52 ERROR_METHOD = 3, 53 FATAL_METHOD = 4, 54 METHODS_NUMBER = 5, 55}; 56 57using LogMethodFunc = std::function<void(const std::string &msg)>; 58 59static const std::array<LogMethodFunc, METHODS_NUMBER> LOG_C_METHODS = { 60 [] (const std::string &msg) { 61 HILOG_DEBUG(LOG_CORE, "%{public}s", msg.c_str()); 62 }, 63 [] (const std::string &msg) { 64 HILOG_INFO(LOG_CORE, "%{public}s", msg.c_str()); 65 }, 66 [] (const std::string &msg) { 67 HILOG_WARN(LOG_CORE, "%{public}s", msg.c_str()); 68 }, 69 [] (const std::string &msg) { 70 HILOG_ERROR(LOG_CORE, "%{public}s", msg.c_str()); 71 }, 72 [] (const std::string &msg) { 73 HILOG_FATAL(LOG_CORE, "%{public}s", msg.c_str()); 74 }, 75}; 76 77static const std::array<LogMethodFunc, METHODS_NUMBER> LOG_CPP_METHODS = { 78 [] (const std::string &msg) { 79 HiLog::Debug(LABEL, "%{public}s", msg.c_str()); 80 }, 81 [] (const std::string &msg) { 82 HiLog::Info(LABEL, "%{public}s", msg.c_str()); 83 }, 84 [] (const std::string &msg) { 85 HiLog::Warn(LABEL, "%{public}s", msg.c_str()); 86 }, 87 [] (const std::string &msg) { 88 HiLog::Error(LABEL, "%{public}s", msg.c_str()); 89 }, 90 [] (const std::string &msg) { 91 HiLog::Fatal(LABEL, "%{public}s", msg.c_str()); 92 }, 93}; 94 95static std::string PopenToString(const std::string &command) 96{ 97 std::string str; 98 constexpr int bufferSize = 1024; 99 FILE *fp = popen(command.c_str(), "re"); 100 if (fp != nullptr) { 101 char buf[bufferSize] = {0}; 102 size_t n = fread(buf, 1, sizeof(buf), fp); 103 while (n > 0) { 104 str.append(buf, n); 105 n = fread(buf, 1, sizeof(buf), fp); 106 } 107 pclose(fp); 108 } 109 std::cout << "PopenToString res: " << str << std::endl; 110 return str; 111} 112 113class HiLogNDKTest : public testing::Test { 114public: 115 static void SetUpTestCase(); 116 static void TearDownTestCase() {} 117 void SetUp(); 118 void TearDown() {} 119}; 120 121void HiLogNDKTest::SetUpTestCase() 122{ 123 (void)PopenToString("hilog -Q pidoff"); 124 (void)PopenToString("hilog -Q domainoff"); 125} 126 127void HiLogNDKTest::SetUp() 128{ 129 (void)PopenToString("hilog -r"); 130} 131 132static std::string RandomStringGenerator() 133{ 134 std::string str; 135 int logLen = 16; 136 char index; 137 for (int i = 0; i < logLen; ++i) { 138 index = rand() % ('z' - 'a') + 'a'; 139 str.append(1, index); 140 } 141 return str; 142} 143 144static void HiLogWriteTest(LogInterfaceType methodType, unsigned int count, 145 const std::array<LogMethodFunc, METHODS_NUMBER> &logMethods) 146{ 147 std::string logMsg(RandomStringGenerator()); 148 for (unsigned int i = 0; i < count; ++i) { 149 logMethods.at(methodType)(logMsg + std::to_string(i)); 150 } 151 usleep(1000); /* 1000: sleep 1 ms */ 152 std::string logMsgs = PopenToString("/system/bin/hilog -x"); 153 unsigned int realCount = 0; 154 std::stringstream ss(logMsgs); 155 std::string str; 156 while (!ss.eof()) { 157 getline(ss, str); 158 if (str.find(logMsg) != std::string::npos) { 159 ++realCount; 160 } 161 } 162 unsigned int allowedLeastLogCount = count - count * 1 / 10; /* 1 / 10: loss rate less than 10% */ 163 if (methodType == DEBUG_METHOD) { 164 allowedLeastLogCount = 0; /* 0: debug log is allowed to be closed */ 165 } 166 EXPECT_GE(realCount, allowedLeastLogCount); 167} 168 169static void FlowCtlTest(const HiLogLabel &label, const std::string keyWord) 170{ 171 const std::string str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 172 for (unsigned int i = 0; i < OVER_LOGS; ++i) { 173 HiLog::Info(label, "%{public}s:%{public}d", str.c_str(), i); 174 } 175 sleep(1); /* 1: sleep 1 s */ 176 HiLog::Info(label, "%{public}s", str.c_str()); 177 std::string logMsgs = PopenToString("hilog -x -T LOGLIMIT"); 178 EXPECT_TRUE(logMsgs.find(keyWord) != std::string::npos); 179} 180 181/** 182 * @tc.name: Dfx_HiLogNDKTest_PrintDebugLog_001 183 * @tc.desc: Call HILOG_DEBUG to print logs. 184 * @tc.type: FUNC 185 */ 186HWTEST_F(HiLogNDKTest, PrintDebugLog_001, TestSize.Level1) 187{ 188 /** 189 * @tc.steps: step1. Call HILOG_DEBUG to print logs and call hilog to read it 190 * @tc.expected: step1. Logs can be printed only if hilog.debug is enabled. 191 */ 192 HiLogWriteTest(DEBUG_METHOD, SOME_LOGS, LOG_C_METHODS); 193} 194 195/** 196 * @tc.name: Dfx_HiLogNDKTest_PrintInfoLog_001 197 * @tc.desc: Call HILOG_INFO to print logs. 198 * @tc.type: FUNC 199 */ 200HWTEST_F(HiLogNDKTest, PrintInfoLog_001, TestSize.Level1) 201{ 202 /** 203 * @tc.steps: step1. Call HILOG_INFO to print logs and call hilog to read it 204 * @tc.expected: step1. Logs printed without loss. 205 */ 206 HiLogWriteTest(INFO_METHOD, SOME_LOGS, LOG_C_METHODS); 207} 208 209/** 210 * @tc.name: Dfx_HiLogNDKTest_PrintWarnLog_001 211 * @tc.desc: Call HILOG_WARN to print logs. 212 * @tc.type: FUNC 213 */ 214HWTEST_F(HiLogNDKTest, PrintWarnLog_001, TestSize.Level1) 215{ 216 /** 217 * @tc.steps: step1. Call HILOG_WARN to print logs and call hilog to read it 218 * @tc.expected: step1. Logs printed without loss. 219 */ 220 HiLogWriteTest(WARN_METHOD, SOME_LOGS, LOG_C_METHODS); 221} 222 223/** 224 * @tc.name: Dfx_HiLogNDKTest_PrintErrorLog_001 225 * @tc.desc: Call HILOG_ERROR to print logs. 226 * @tc.type: FUNC 227 */ 228HWTEST_F(HiLogNDKTest, PrintErrorLog_001, TestSize.Level1) 229{ 230 /** 231 * @tc.steps: step1. Call HILOG_ERROR to print logs and call hilog to read it 232 * @tc.expected: step1. Logs printed without loss. 233 */ 234 HiLogWriteTest(ERROR_METHOD, SOME_LOGS, LOG_C_METHODS); 235} 236 237/** 238 * @tc.name: Dfx_HiLogNDKTest_PrintFatalLog_001 239 * @tc.desc: Call HILOG_FATAL to print logs. 240 * @tc.type: FUNC 241 */ 242HWTEST_F(HiLogNDKTest, PrintFatalLog_001, TestSize.Level1) 243{ 244 /** 245 * @tc.steps: step1. Call HILOG_FATAL to print logs and call hilog to read it 246 * @tc.expected: step1. Logs printed without loss. 247 */ 248 HiLogWriteTest(FATAL_METHOD, SOME_LOGS, LOG_C_METHODS); 249} 250 251/** 252 * @tc.name: Dfx_HiLogNDKTest_LogLossCheck_001 253 * @tc.desc: HiLog log loss rate must less than 10%. 254 * @tc.type: FUNC 255 */ 256HWTEST_F(HiLogNDKTest, LogLossCheck_001, TestSize.Level1) 257{ 258 /** 259 * @tc.steps: step1. Call HILOG_INFO to print logs and call hilog to read it 260 * @tc.expected: step1. Calculate log loss rate and it should less than 10% 261 */ 262 HiLogWriteTest(INFO_METHOD, MORE_LOGS, LOG_C_METHODS); 263} 264 265/** 266 * @tc.name: Dfx_HiLogNDKTest_PrintDebugLog_002 267 * @tc.desc: Call HiLog::Debug to print logs. 268 * @tc.type: FUNC 269 */ 270HWTEST_F(HiLogNDKTest, PrintDebugLog_002, TestSize.Level1) 271{ 272 /** 273 * @tc.steps: step1. Call HiLog::Debug to print logs and call hilog to read it 274 * @tc.expected: step1. Logs can be printed only if hilog.debug is enabled. 275 */ 276 HiLogWriteTest(DEBUG_METHOD, SOME_LOGS, LOG_CPP_METHODS); 277} 278 279/** 280 * @tc.name: Dfx_HiLogNDKTest_PrintInfoLog_002 281 * @tc.desc: Call HiLog::Info to print logs. 282 * @tc.type: FUNC 283 */ 284HWTEST_F(HiLogNDKTest, PrintInfoLog_002, TestSize.Level1) 285{ 286 /** 287 * @tc.steps: step1. Call HiLog::Info to print logs and call hilog to read it 288 * @tc.expected: step1. Logs printed without loss. 289 */ 290 HiLogWriteTest(INFO_METHOD, SOME_LOGS, LOG_CPP_METHODS); 291} 292 293/** 294 * @tc.name: Dfx_HiLogNDKTest_PrintWarnLog_002 295 * @tc.desc: Call HiLog::Warn print logs. 296 * @tc.type: FUNC 297 */ 298HWTEST_F(HiLogNDKTest, PrintWarnLog_002, TestSize.Level1) 299{ 300 /** 301 * @tc.steps: step1. Call HiLog::Warn to print logs and call hilog to read it 302 * @tc.expected: step1. Logs printed without loss. 303 */ 304 HiLogWriteTest(WARN_METHOD, SOME_LOGS, LOG_CPP_METHODS); 305} 306 307/** 308 * @tc.name: Dfx_HiLogNDKTest_PrintErrorLog_002 309 * @tc.desc: Call HiLog::Error to print logs. 310 * @tc.type: FUNC 311 */ 312HWTEST_F(HiLogNDKTest, PrintErrorLog_002, TestSize.Level1) 313{ 314 /** 315 * @tc.steps: step1. Call HiLog::Error to print logs and call hilog to read it 316 * @tc.expected: step1. Logs printed without loss. 317 */ 318 HiLogWriteTest(ERROR_METHOD, SOME_LOGS, LOG_CPP_METHODS); 319} 320 321/** 322 * @tc.name: Dfx_HiLogNDKTest_PrintFatalLog_002 323 * @tc.desc: Call HiLog::Fatal to print logs. 324 * @tc.type: FUNC 325 */ 326HWTEST_F(HiLogNDKTest, PrintFatalLog_002, TestSize.Level1) 327{ 328 /** 329 * @tc.steps: step1. Call HiLog::Fatal to print logs and call hilog to read it 330 * @tc.expected: step1. Logs printed without loss. 331 */ 332 HiLogWriteTest(FATAL_METHOD, SOME_LOGS, LOG_CPP_METHODS); 333} 334 335/** 336 * @tc.name: Dfx_HiLogNDKTest_LogLossCheck_002 337 * @tc.desc: HiLog log loss rate must less than 10% 338 * @tc.type: FUNC 339 */ 340HWTEST_F(HiLogNDKTest, LogLossCheck_002, TestSize.Level1) 341{ 342 /** 343 * @tc.steps: step1. Call HiLog::Info to print logs and call hilog to read it 344 * @tc.expected: step1. Calculate log loss rate and it should less than 10% 345 */ 346 HiLogWriteTest(INFO_METHOD, MORE_LOGS, LOG_CPP_METHODS); 347} 348 349/** 350 * @tc.name: Dfx_HiLogNDKTest_IsLoggable_001 351 * @tc.desc: Check whether is loggable for each log level 352 * @tc.type: FUNC 353 */ 354HWTEST_F(HiLogNDKTest, IsLoggable_001, TestSize.Level1) 355{ 356 /** 357 * @tc.steps: step1. Call HiLogIsLoggable to check whether is loggable for each log level. 358 * @tc.expected: step1. LOG_DEBUG and lower level should return false in release version, and others return true. 359 */ 360 if (OHOS::system::GetParameter("hilog.loggable.global", "D") == "D") { 361 EXPECT_TRUE(HiLogIsLoggable(0xD002D00, LOG_TAG, LOG_DEBUG)); 362 } else { 363 EXPECT_FALSE(HiLogIsLoggable(0xD002D00, LOG_TAG, LOG_DEBUG)); 364 } 365 EXPECT_TRUE(HiLogIsLoggable(0xD002D00, LOG_TAG, LOG_INFO)); 366 EXPECT_TRUE(HiLogIsLoggable(0xD002D00, LOG_TAG, LOG_WARN)); 367 EXPECT_TRUE(HiLogIsLoggable(0xD002D00, LOG_TAG, LOG_ERROR)); 368 EXPECT_TRUE(HiLogIsLoggable(0xD002D00, LOG_TAG, LOG_FATAL)); 369 EXPECT_TRUE(HiLogIsLoggable(0xD002D00, "abc", LOG_WARN)); 370} 371 372/** 373 * @tc.name: Dfx_HiLogNDKTest_DomainCheck_001 374 * @tc.desc: test illegal domainID 375 * @tc.type: FUNC 376 * @tc.require:issueI5NU4L 377 */ 378HWTEST_F(HiLogNDKTest, DomainCheck_001, TestSize.Level1) 379{ 380 (void)PopenToString("param set hilog.debug.on false"); 381 (void)PopenToString("param set persist.sys.hilog.debug.on false"); 382 std::string logMsg(RandomStringGenerator()); 383 for (unsigned int i = 0; i < SOME_LOGS; ++i) { 384 HiLog::Info(ILLEGAL_DOMAIN_LABEL, "%{public}s", logMsg.c_str()); 385 } 386 usleep(1000); /* 1000: sleep 1 ms */ 387 std::string logMsgs = PopenToString("/system/bin/hilog -x"); 388 unsigned int realCount = 0; 389 std::stringstream ss(logMsgs); 390 std::string str; 391 while (!ss.eof()) { 392 getline(ss, str); 393 if (str.find(logMsg) != std::string::npos) { 394 ++realCount; 395 } 396 } 397 EXPECT_EQ(realCount, 0); 398} 399 400/** 401 * @tc.name: Dfx_HiLogNDKTest_hilogSocketTest 402 * @tc.desc: Query hilog socket rights 403 * @tc.type: FUNC 404 * @tc.require:issueI5NU7F 405 */ 406HWTEST_F(HiLogNDKTest, hilogSocketTest, TestSize.Level1) 407{ 408 std::string str; 409 std::string hilogControlRights = "srw-rw----"; 410 std::string logMsgs = PopenToString("ls -al //dev/unix/socket/hilogControl"); 411 std::stringstream ss(logMsgs); 412 getline(ss, str); 413 EXPECT_TRUE(str.find(hilogControlRights) != std::string::npos); 414} 415 416/** 417 * @tc.name: Dfx_HiLogNDKTest_pidFlowCtrlTest 418 * @tc.desc: hilog pidFlowCtrlTest 419 * @tc.type: FUNC 420 */ 421HWTEST_F(HiLogNDKTest, pidFlowCtrlTest, TestSize.Level1) 422{ 423 (void)PopenToString("hilog -Q pidon"); 424 const std::string pidCtrlLog = "DROPPED"; 425 FlowCtlTest(APP_LABEL, pidCtrlLog); 426 (void)PopenToString("hilog -Q pidoff"); 427} 428 429/** 430 * @tc.name: Dfx_HiLogNDKTest_domainFlowCtrlTest 431 * @tc.desc: hilog domainFlowCtrlTest 432 * @tc.type: FUNC 433 */ 434HWTEST_F(HiLogNDKTest, domainFlowCtrlTest, TestSize.Level1) 435{ 436 (void)PopenToString("hilog -Q domainon"); 437 const std::string domainCtrlLog = "dropped"; 438 FlowCtlTest(LABEL, domainCtrlLog); 439 (void)PopenToString("hilog -Q domainoff"); 440} 441} // namespace HiLogTest 442} // namespace HiviewDFX 443} // namespace OHOS 444