1/*
2 * Copyright (c) 2022 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#include "hilogtool_test.h"
16#include "hilog/log_c.h"
17#include <dirent.h>
18#include <log_utils.h>
19#include <properties.h>
20#include <hilog_common.h>
21#include <list>
22#include <regex>
23
24using namespace std;
25using namespace testing::ext;
26using namespace OHOS;
27using namespace OHOS::HiviewDFX;
28
29static int GetCmdLinesFromPopen(const std::string& cmd)
30{
31    if (cmd.empty()) {
32        return 0;
33    }
34    FILE* fp = popen(cmd.c_str(), "r");
35    if (fp == nullptr) {
36        return 0;
37    }
38    int ret = 0;
39    char* buffer = nullptr;
40    size_t len = 0;
41    while (getline(&buffer, &len, fp) != -1) {
42        ret++;
43    }
44    if (buffer != nullptr) {
45        free(buffer);
46        buffer = nullptr;
47    }
48    pclose(fp);
49    return ret;
50}
51
52static std::string GetCmdResultFromPopen(const std::string& cmd)
53{
54    if (cmd.empty()) {
55        return "";
56    }
57    FILE* fp = popen(cmd.c_str(), "r");
58    if (fp == nullptr) {
59        return "";
60    }
61    std::string ret = "";
62    char* buffer = nullptr;
63    size_t len = 0;
64    while (getline(&buffer, &len, fp) != -1) {
65        std::string line = buffer;
66        ret += line;
67    }
68    if (buffer != nullptr) {
69        free(buffer);
70        buffer = nullptr;
71    }
72    pclose(fp);
73    return ret;
74}
75
76static bool IsExistInCmdResult(const std::string &cmd, const std::string &str)
77{
78    if (cmd.empty()) {
79        return false;
80    }
81    FILE* fp = popen(cmd.c_str(), "r");
82    if (fp == nullptr) {
83        return false;
84    }
85    bool ret = false;
86    char* buffer = nullptr;
87    size_t len = 0;
88    while (getline(&buffer, &len, fp) != -1) {
89        std::string line = buffer;
90        if (line.find(str) != string::npos) {
91            ret = true;
92            break;
93        }
94    }
95    if (buffer != nullptr) {
96        free(buffer);
97        buffer = nullptr;
98    }
99    pclose(fp);
100    return ret;
101}
102
103void HilogToolTest::TearDownTestCase()
104{
105    (void)GetCmdResultFromPopen("hilog -b I");
106    (void)GetCmdResultFromPopen("hilog -G 256K");
107    (void)GetCmdResultFromPopen("hilog -w stop");
108    (void)GetCmdResultFromPopen("hilog -w start");
109}
110
111namespace {
112const std::list<pair<string, string>> helperList = {
113    /* help cmd suffix, information key word */
114    {"", "Usage"},
115    {"query", "Query"},
116    {"clear", "Remove"},
117    {"buffer", "buffer"},
118    {"stats", "statistics"},
119    {"persist", "persistance"},
120    {"private", "privacy"},
121    {"kmsg", "kmsg"},
122    {"flowcontrol", "flow-control"},
123    {"baselevel", "baselevel"},
124    {"combo", "combination"},
125    {"domain", "domain"},
126};
127
128/**
129 * @tc.name: Dfx_HilogToolTest_HelperTest_001
130 * @tc.desc: hilog help information.
131 * @tc.type: FUNC
132 */
133HWTEST_F(HilogToolTest, HelperTest_001, TestSize.Level1)
134{
135    /**
136     * @tc.steps: step1. show hilog help information.
137     * @tc.steps: step2. invalid cmd.
138     */
139    GTEST_LOG_(INFO) << "HelperTest_001: start.";
140    std::string prefix = "hilog -h ";
141    std::string cmd = "";
142    for (auto &it : helperList) {
143        cmd = prefix + it.first;
144        EXPECT_TRUE(IsExistInCmdResult(cmd, it.second));
145    }
146
147    prefix = "hilog --help ";
148    for (auto &it : helperList) {
149        cmd = prefix + it.first;
150        EXPECT_TRUE(IsExistInCmdResult(cmd, it.second));
151    }
152}
153
154/**
155 * @tc.name: Dfx_HilogToolTest_HandleTest_001
156 * @tc.desc: BaseLogLevelHandler.
157 * @tc.type: FUNC
158 */
159HWTEST_F(HilogToolTest, HandleTest_001, TestSize.Level1)
160{
161    /**
162     * @tc.steps: step1. set global log level to INFO.
163     * @tc.steps: step2. invalid log level.
164     */
165    GTEST_LOG_(INFO) << "HandleTest_001: start.";
166    std::string level = "I";
167    std::string cmd = "hilog -b " + level;
168    std::string str = "Set global log level to " + level + " successfully\n";
169    std::string query = "param get hilog.loggable.global";
170    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
171    EXPECT_EQ(GetCmdResultFromPopen(query), level + " \n");
172
173    // stderr redirect to stdout
174    cmd = "hilog -b test_level 2>&1";
175    std::string errMsg = ErrorCode2Str(ERR_LOG_LEVEL_INVALID) + "\n";
176    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
177}
178
179/**
180 * @tc.name: Dfx_HilogToolTest_HandleTest_002
181 * @tc.desc: DomainHandler.
182 * @tc.type: FUNC
183 */
184HWTEST_F(HilogToolTest, HandleTest_002, TestSize.Level1)
185{
186    /**
187     * @tc.steps: step1. set domain xxx log level to INFO.
188     * @tc.steps: step2. invaild domain.
189     */
190    GTEST_LOG_(INFO) << "HandleTest_002: start.";
191    uint32_t domain = 0xd002d00;
192    std::string level = "I";
193    std::string cmd = "hilog -b " + level + " -D " + Uint2HexStr(domain);
194    std::string str = "Set domain 0x" + Uint2HexStr(domain) + " log level to " + level + " successfully\n";
195    std::string query = "param get hilog.loggable.domain." + Uint2HexStr(domain);
196    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
197    EXPECT_EQ(GetCmdResultFromPopen(query), level + " \n");
198
199    cmd = "hilog -D test_domain 2>&1";
200    std::string errMsg = ErrorCode2Str(ERR_INVALID_DOMAIN_STR) + "\n";
201    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
202}
203
204/**
205 * @tc.name: Dfx_HilogToolTest_HandleTest_003
206 * @tc.desc: TagHandler.
207 * @tc.type: FUNC
208 */
209HWTEST_F(HilogToolTest, HandleTest_003, TestSize.Level1)
210{
211    /**
212     * @tc.steps: step1. set tag xxx log level to INFO.
213     * @tc.steps: step2. invalid tag.
214     */
215    GTEST_LOG_(INFO) << "HandleTest_003: start.";
216    std::string tag = "test";
217    std::string level = "I";
218    std::string cmd = "hilog -b " + level + " -T " + tag;
219    std::string str = "Set tag " +  tag + " log level to " + level + " successfully\n";
220    std::string query = "param get hilog.loggable.tag." + tag;
221    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
222    EXPECT_EQ(GetCmdResultFromPopen(query), level + " \n");
223
224    cmd = "hilog -T abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 2>&1";
225    std::string errMsg = ErrorCode2Str(ERR_TAG_STR_TOO_LONG) + "\n";
226    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
227}
228
229/**
230 * @tc.name: Dfx_HilogToolTest_HandleTest_004
231 * @tc.desc: BufferSizeSetHandler.
232 * @tc.type: FUNC
233 */
234HWTEST_F(HilogToolTest, HandleTest_004, TestSize.Level1)
235{
236    /**
237     * @tc.steps: step1. set app,init.core buffer size [valid].
238     * @tc.expected: step1. set app,init.core buffer size successfully.
239     * @tc.steps: step2. set app,init.core buffer size [invalid].
240     * @tc.expected: step2  set app,init.core buffer size failed.
241     * buffer size should be in range [64.0K, 512.0M].
242     * @tc.expected: step3  invalid buffer size str.
243     */
244    GTEST_LOG_(INFO) << "HandleTest_004: start.";
245    std::string cmd = "hilog -G 512K";
246    std::string str = "Set log type app buffer size to 512.0K successfully\n"
247        "Set log type init buffer size to 512.0K successfully\n"
248        "Set log type core buffer size to 512.0K successfully\n"
249        "Set log type only_prerelease buffer size to 512.0K successfully\n";
250    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
251
252    cmd = "hilog -G 512G";
253    str = "failed";
254    EXPECT_TRUE(IsExistInCmdResult(cmd, str));
255
256    std::string inValidStrCmd = "hilog -G test_buffersize 2>&1";
257    std::string errMsg = ErrorCode2Str(ERR_INVALID_SIZE_STR) + "\n";
258    EXPECT_EQ(GetCmdResultFromPopen(inValidStrCmd), errMsg);
259}
260
261/**
262 * @tc.name: Dfx_HilogToolTest_HandleTest_005
263 * @tc.desc: BufferSizeGetHandler.
264 * @tc.type: FUNC
265 */
266HWTEST_F(HilogToolTest, HandleTest_005, TestSize.Level1)
267{
268    /**
269     * @tc.steps: step1. get app,init.core valid buffer size.
270     */
271    GTEST_LOG_(INFO) << "HandleTest_005: start.";
272    std::string cmd = "hilog -g";
273    std::string str = "Log type app buffer size is 512.0K\n"
274        "Log type init buffer size is 512.0K\n"
275        "Log type core buffer size is 512.0K\n"
276        "Log type only_prerelease buffer size is 512.0K\n";
277    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
278}
279
280/**
281 * @tc.name: Dfx_HilogToolTest_HandleTest_006
282 * @tc.desc: KmsgFeatureSetHandler.
283 * @tc.type: FUNC
284 */
285HWTEST_F(HilogToolTest, HandleTest_006, TestSize.Level1)
286{
287    /**
288     * @tc.steps: step1. set hilogd storing kmsg log feature on.
289     * @tc.steps: step2. set hilogd storing kmsg log feature off.
290     * @tc.steps: step3. set hilogd storing kmsg log feature invalid.
291     */
292    GTEST_LOG_(INFO) << "HandleTest_006: start.";
293    std::string cmd = "hilog -k on";
294    std::string str = "Set hilogd storing kmsg log on successfully\n";
295    std::string query = "param get persist.sys.hilog.kmsg.on";
296    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
297    EXPECT_EQ(GetCmdResultFromPopen(query), "true \n");
298
299    cmd = "hilog -k off";
300    str = "Set hilogd storing kmsg log off successfully\n";
301    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
302    EXPECT_EQ(GetCmdResultFromPopen(query), "false \n");
303
304    cmd = "hilog -k test_feature 2>&1";
305    std::string errMsg = ErrorCode2Str(ERR_INVALID_ARGUMENT) + "\n";
306    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
307}
308
309/**
310 * @tc.name: Dfx_HilogToolTest_HandleTest_007
311 * @tc.desc: PrivateFeatureSetHandler.
312 * @tc.type: FUNC
313 */
314HWTEST_F(HilogToolTest, HandleTest_007, TestSize.Level1)
315{
316    /**
317     * @tc.steps: step1. set hilog api privacy formatter feature on.
318     * @tc.steps: step2. set hilog api privacy formatter feature off.
319     * @tc.steps: step3. set hilog api privacy formatter feature invalid.
320     */
321    GTEST_LOG_(INFO) << "HandleTest_007: start.";
322    std::string cmd = "hilog -p on";
323    std::string str = "Set hilog privacy format on successfully\n";
324    std::string query = "param get hilog.private.on";
325    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
326    EXPECT_EQ(GetCmdResultFromPopen(query), "true \n");
327
328    cmd = "hilog -p off";
329    str = "Set hilog privacy format off successfully\n";
330    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
331    EXPECT_EQ(GetCmdResultFromPopen(query), "false \n");
332
333    cmd = "hilog -p test_feature 2>&1";
334    std::string errMsg = ErrorCode2Str(ERR_INVALID_ARGUMENT) + "\n";
335    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
336}
337
338/**
339 * @tc.name: Dfx_HilogToolTest_HandleTest_008
340 * @tc.desc: FlowControlFeatureSetHandler.
341 * @tc.type: FUNC
342 */
343HWTEST_F(HilogToolTest, HandleTest_008, TestSize.Level1)
344{
345    /**
346     * @tc.steps: step1. set process flow control on.
347     * @tc.steps: step2. set process flow control off.
348     * @tc.steps: step3. set domain flow control on.
349     * @tc.steps: step4. set domain flow control off.
350     * @tc.steps: step5. invalid cmd.
351     */
352    GTEST_LOG_(INFO) << "HandleTest_008: start.";
353    std::string cmd = "hilog -Q pidon";
354    std::string str = "Set flow control by process to enabled, result: Success [CODE: 0]\n";
355    std::string query = "param get hilog.flowctrl.proc.on";
356    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
357    EXPECT_EQ(GetCmdResultFromPopen(query), "true \n");
358
359    cmd = "hilog -Q pidoff";
360    str = "Set flow control by process to disabled, result: Success [CODE: 0]\n";
361    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
362    EXPECT_EQ(GetCmdResultFromPopen(query), "false \n");
363
364    cmd = "hilog -Q domainon";
365    str = "Set flow control by domain to enabled, result: Success [CODE: 0]\n";
366    query = "param get hilog.flowctrl.domain.on";
367    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
368    EXPECT_EQ(GetCmdResultFromPopen(query), "true \n");
369
370    cmd = "hilog -Q domainoff";
371    str = "Set flow control by domain to disabled, result: Success [CODE: 0]\n";
372    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
373    EXPECT_EQ(GetCmdResultFromPopen(query), "false \n");
374
375    cmd = "hilog -Q test_cmd 2>&1";
376    std::string errMsg = ErrorCode2Str(ERR_INVALID_ARGUMENT) + "\n";
377    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
378}
379
380/**
381 * @tc.name: Dfx_HilogToolTest_HandleTest_009
382 * @tc.desc: HeadHandler & TailHandler.
383 * @tc.type: FUNC
384 */
385HWTEST_F(HilogToolTest, HandleTest_009, TestSize.Level1)
386{
387    /**
388     * @tc.steps: step1. show n lines logs on head of buffer.
389     * @tc.steps: step2. show n lines logs on tail of buffer.
390     * @tc.steps: step3. invalid cmd.
391     */
392    GTEST_LOG_(INFO) << "HandleTest_009: start.";
393    int lines = 5;
394    std::string cmd = "hilog -a " + std::to_string(lines);
395    EXPECT_EQ(GetCmdLinesFromPopen(cmd), lines);
396
397    cmd = "hilog -z " + std::to_string(lines);
398    EXPECT_EQ(GetCmdLinesFromPopen(cmd), lines);
399
400    cmd = "hilog -a test 2>&1";
401    std::string errMsg = ErrorCode2Str(ERR_NOT_NUMBER_STR) + "\n";
402    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
403
404    cmd = "hilog -z test 2>&1";
405    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
406
407    cmd = "hilog -a 10 -z 10 2>&1";
408    errMsg = ErrorCode2Str(ERR_COMMAND_INVALID) + "\n";
409    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
410}
411
412/**
413 * @tc.name: Dfx_HilogToolTest_HandleTest_010
414 * @tc.desc: RemoveHandler.
415 * @tc.type: FUNC
416 */
417HWTEST_F(HilogToolTest, HandleTest_010, TestSize.Level1)
418{
419    /**
420     * @tc.steps: step1. get the localtime.
421     * @tc.steps: step2. remove all logs in hilogd buffer.
422     * @tc.steps: step3. compare the logtime to localtime.
423     */
424    GTEST_LOG_(INFO) << "HandleTest_010: start.";
425    time_t tnow = time(nullptr);
426    struct tm *tmNow = localtime(&tnow);
427    char clearTime[32] = {0};
428    if (tmNow != nullptr) {
429        strftime(clearTime, sizeof(clearTime), "%m-%d %H:%M:%S.%s", tmNow);
430    }
431    std::string cmd = "hilog -r";
432    std::string str = "Log type core,app,only_prerelease buffer clear successfully\n";
433    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
434
435    sleep(1);
436    std::string res = GetCmdResultFromPopen("hilog -a 5");
437    std::string initStr = "HiLog: ========Zeroth log of type: init";
438    vector<string> vec;
439    std::string logTime = "";
440    Split(res, vec, "\n");
441    for (auto& it : vec) {
442        if (it.find(initStr) == string::npos) {
443            logTime = it.substr(0, 18);
444            EXPECT_LT(clearTime, logTime);
445        }
446    }
447}
448
449/**
450 * @tc.name: Dfx_HilogToolTest_HandleTest_011
451 * @tc.desc: TypeHandler.
452 * @tc.type: FUNC
453 */
454HWTEST_F(HilogToolTest, HandleTest_011, TestSize.Level1)
455{
456    /**
457     * @tc.steps: step1. remove app logs in hilogd buffer.
458     * @tc.steps: step2. remove core logs in hilogd buffer.
459     * @tc.steps: step3. invalid log type.
460     */
461    GTEST_LOG_(INFO) << "HandleTest_011: start.";
462    std::string cmd = "hilog -r -t app";
463    std::string str = "Log type app buffer clear successfully\n";
464    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
465
466    cmd = "hilog -r -t core";
467    str = "Log type core buffer clear successfully\n";
468    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
469
470    cmd = "hilog -r -t test_type 2>&1";
471    std::string errMsg = ErrorCode2Str(ERR_LOG_TYPE_INVALID) + "\n";
472    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
473}
474
475/**
476 * @tc.name: Dfx_HilogToolTest_HandleTest_012
477 * @tc.desc: PersistTaskHandler FileNameHandler JobIdHandler FileLengthHandler FileNumberHandler.
478 * @tc.type: FUNC
479 */
480HWTEST_F(HilogToolTest, HandleTest_012, TestSize.Level1)
481{
482    /**
483     * @tc.steps: step1. start hilog persistance task control.
484     * @tc.steps: step2. stop hilog persistance task control.
485     * @tc.steps: step3. start hilog persistance task control with advanced options.
486     * @tc.steps: step4. query tasks informations.
487     * @tc.steps: step5. invalid persistance cmd.
488     * @tc.steps: step6. query invalid filename.
489     * @tc.steps: step7. query invalid jobid.
490     * @tc.steps: step8. query invalid filelength.
491     * @tc.steps: step9. query invalid filenumber.
492     */
493    GTEST_LOG_(INFO) << "HandleTest_012: start.";
494    (void)GetCmdResultFromPopen("hilog -w stop");
495    std::string cmd = "hilog -w start";
496    std::string str = "Persist task [jobid:1] start successfully\n";
497    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
498
499    cmd = "hilog -w stop";
500    str = "Persist task [jobid:1] stop successfully\n";
501    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
502
503    std::string filename = "test";
504    uint64_t length = 2 * 1024 * 1024;
505    std::string unit = "B";
506    std::string compress = "zlib";
507    int num = 25;
508    int jobid = 200;
509    cmd = "hilog -w start -f " + filename + " -l " + std::to_string(length) + unit
510        + " -n " + std::to_string(num) + " -m " + compress + " -j " + std::to_string(jobid);
511    str = "Persist task [jobid:" + std::to_string(jobid) + "] start successfully\n";
512    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
513
514    cmd = "hilog -w query";
515    str = std::to_string(jobid) + " init,core,app,only_prerelease " + compress + " /data/log/hilog/" + filename
516        + " " + Size2Str(length) + " " + std::to_string(num) + "\n";
517    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
518
519    cmd = "hilog -w test 2>&1";
520    std::string errMsg = ErrorCode2Str(ERR_INVALID_ARGUMENT) + "\n";
521    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
522
523    filename = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
524                "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
525    cmd = "hilog -w query -f " + filename + " 2>&1";
526    errMsg = ErrorCode2Str(ERR_FILE_NAME_TOO_LONG) + "\n";
527    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
528
529    cmd = "hilog -w query -j test 2>&1";
530    errMsg = ErrorCode2Str(ERR_NOT_NUMBER_STR) + "\n";
531    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
532
533    cmd = "hilog -w query -l test 2>&1";
534    errMsg = ErrorCode2Str(ERR_INVALID_SIZE_STR) + "\n";
535    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
536
537    cmd = "hilog -w query -n test 2>&1";
538    errMsg = ErrorCode2Str(ERR_NOT_NUMBER_STR) + "\n";
539    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
540}
541
542/**
543 * @tc.name: Dfx_HilogToolTest_HandleTest_013
544 * @tc.desc: RegexHandler.
545 * @tc.type: FUNC
546 */
547HWTEST_F(HilogToolTest, HandleTest_013, TestSize.Level1)
548{
549    /**
550     * @tc.steps: step1. show the logs which match the regular expression.
551	 * @tc.steps: step2. invaild regex.
552     */
553    GTEST_LOG_(INFO) << "HandleTest_013: start.";
554    std::string cmd = "hilog -x -e ";
555    std::string regex = "service";
556    std::string res = GetCmdResultFromPopen(cmd + regex);
557    if (res != "") {
558        vector<string> vec;
559        Split(res, vec, "\n");
560        for (auto& it : vec) {
561            EXPECT_TRUE(it.find(regex) != string::npos);
562        }
563    }
564
565    cmd = "hilog -x -e abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
566            "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
567            "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 2>&1";
568    std::string errMsg = ErrorCode2Str(ERR_REGEX_STR_TOO_LONG) + "\n";
569    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
570}
571
572/**
573 * @tc.name: Dfx_HilogToolTest_HandleTest_013
574 * @tc.desc: LevelHandler.
575 * @tc.type: FUNC
576 */
577HWTEST_F(HilogToolTest, HandleTest_014, TestSize.Level1)
578{
579    /**
580     * @tc.steps: step1. filter log level.
581     * @tc.steps: step2. invaild log level usage.
582     */
583    GTEST_LOG_(INFO) << "HandleTest_014: start.";
584    std::string cmd = "hilog -a 10 -L ";
585    std::string level = "I";
586    std::string res = GetCmdResultFromPopen(cmd + level);
587    vector<string> vec;
588    Split(res, vec, "\n");
589    for (auto& it : vec) {
590        std::string logLevel = it.substr(31, 1);
591        EXPECT_EQ(logLevel, level);
592    }
593
594    cmd = "hilog -L test_level 2>&1";
595    std::string errMsg = ErrorCode2Str(ERR_LOG_LEVEL_INVALID) + "\n";
596    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
597
598    cmd = "hilog -L E F 2>&1";
599    errMsg = ErrorCode2Str(ERR_TOO_MANY_ARGUMENTS) + "\n";
600    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
601
602    cmd = "hilog -L E -L F 2>&1";
603    errMsg = ErrorCode2Str(ERR_DUPLICATE_OPTION) + "\n";
604    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
605}
606
607/**
608 * @tc.name: Dfx_HilogToolTest_HandleTest_013
609 * @tc.desc: PidHandler.
610 * @tc.type: FUNC
611 */
612HWTEST_F(HilogToolTest, HandleTest_015, TestSize.Level1)
613{
614    /**
615     * @tc.steps: step1. filter PID.
616     */
617    GTEST_LOG_(INFO) << "HandleTest_015: start.";
618    std::string pid = GetCmdResultFromPopen("hilog -z 1").substr(19, 5);
619    std::string cmd = "hilog -a 10 -P ";
620    std::string res = GetCmdResultFromPopen(cmd + pid);
621    if (res != "") {
622        vector<string> vec;
623        Split(res, vec, "\n");
624        for (auto& it : vec) {
625            std::string logPid = it.substr(19, 5);
626            EXPECT_EQ(logPid, pid);
627        }
628    }
629
630    cmd = "hilog -P test 2>&1";
631    std::string errMsg = ErrorCode2Str(ERR_NOT_NUMBER_STR) + "\n";
632    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
633}
634
635/**
636 * @tc.name: Dfx_HilogToolTest_HandleTest_016
637 * @tc.desc: StatsInfoQueryHandler.
638 * @tc.type: FUNC
639 */
640HWTEST_F(HilogToolTest, HandleTest_016, TestSize.Level1)
641{
642    /**
643     * @tc.steps: step1. set stats property.
644     * @tc.steps: step2. restart hilog service.
645     * @tc.steps: step3. show log statistic report.
646     * @tc.steps: step4. clear hilogd statistic information.
647     */
648    GTEST_LOG_(INFO) << "HandleTest_016: start.";
649    (void)GetCmdResultFromPopen("param set persist.sys.hilog.stats false");
650    (void)GetCmdResultFromPopen("param set persist.sys.hilog.stats.tag false");
651    (void)GetCmdResultFromPopen("service_control stop hilogd");
652    (void)GetCmdResultFromPopen("service_control start hilogd");
653    sleep(3);
654    std::string cmd = "hilog -s";
655    std::string str = "Statistic info query failed";
656    EXPECT_TRUE(IsExistInCmdResult(cmd, str));
657
658    (void)GetCmdResultFromPopen("param set persist.sys.hilog.stats true");
659    (void)GetCmdResultFromPopen("param set persist.sys.hilog.stats.tag true");
660    (void)GetCmdResultFromPopen("service_control stop hilogd");
661    (void)GetCmdResultFromPopen("service_control start hilogd");
662    sleep(10);
663    str = "report";
664    EXPECT_TRUE(IsExistInCmdResult(cmd, str));
665    EXPECT_TRUE(IsStatsEnable());
666    EXPECT_TRUE(IsTagStatsEnable());
667
668    cmd = "hilog -S";
669    str = "Statistic info clear successfully\n";
670    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
671}
672
673/**
674 * @tc.name: Dfx_HilogToolTest_HandleTest_017
675 * @tc.desc: FormatHandler.
676 * @tc.type: FUNC
677 */
678HWTEST_F(HilogToolTest, HandleTest_017, TestSize.Level1)
679{
680    /**
681     * @tc.steps: step1. log format time.
682     * @tc.steps: step2. log format epoch.
683     * @tc.steps: step3. log format monotonic.
684     * @tc.steps: step4. log format msec.
685     * @tc.steps: step5. log format usec.
686     * @tc.steps: step6. log format nsec.
687     * @tc.steps: step7. log format year.
688     * @tc.steps: step8. log format zone.
689     * @tc.steps: step9. invalid log format.
690     */
691    GTEST_LOG_(INFO) << "HandleTest_017: start.";
692    std::string cmd = "hilog -v time -z 5";
693    std::regex pattern("(0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01])\\s(0\\d{1}|1\\d{1}|2[0-3])"
694                        ":[0-5]\\d{1}:([0-5]\\d{1})(\\.(\\d){0,3})?$");
695    std::string res = GetCmdResultFromPopen(cmd);
696    vector<string> vec;
697    Split(res, vec, "\n");
698    for (auto& it : vec) {
699        EXPECT_TRUE(regex_match(it.substr(0, 18), pattern));
700    }
701
702    cmd = "hilog -v epoch -z 5";
703    pattern = ("\\d{0,10}.\\d{3}$");
704    res = GetCmdResultFromPopen(cmd);
705    Split(res, vec, "\n");
706    for (auto& it : vec) {
707        EXPECT_TRUE(regex_match(it.substr(0, 14), pattern));
708    }
709
710    cmd = "hilog -v monotonic -z 5";
711    pattern = ("\\d{0,8}.\\d{3}$");
712    res = GetCmdResultFromPopen(cmd);
713    std::string initStr = "HiLog: ========Zeroth log of type";
714    Split(res, vec, "\n");
715    for (auto& it : vec) {
716        if (it.find(initStr) == string::npos) {
717            std::string str = it.substr(0, 12);
718            // remove the head blank space
719            str.erase(0, str.find_first_not_of(" "));
720            EXPECT_TRUE(regex_match(str, pattern));
721        }
722    }
723
724    cmd = "hilog -v msec -z 5";
725    pattern = ("(0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01])\\s(0\\d{1}|1\\d{1}|2[0-3])"
726                        ":[0-5]\\d{1}:([0-5]\\d{1})(\\.(\\d){0,3})?$");
727    res = GetCmdResultFromPopen(cmd);
728    Split(res, vec, "\n");
729    for (auto& it : vec) {
730        EXPECT_TRUE(regex_match(it.substr(0, 18), pattern));
731    }
732
733    cmd = "hilog -v usec -z 5";
734    pattern = "(0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01])\\s(0\\d{1}|1\\d{1}|2[0-3])"
735                ":[0-5]\\d{1}:([0-5]\\d{1})(\\.(\\d){0,6})?$";
736    res = GetCmdResultFromPopen(cmd);
737    Split(res, vec, "\n");
738    for (auto& it : vec) {
739        EXPECT_TRUE(regex_match(it.substr(0, 21), pattern));
740    }
741
742    cmd = "hilog -v nsec -z 5";
743    pattern = "(0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01])\\s(0\\d{1}|1\\d{1}|2[0-3])"
744                ":[0-5]\\d{1}:([0-5]\\d{1})(\\.(\\d){0,9})?$";
745    res = GetCmdResultFromPopen(cmd);
746    Split(res, vec, "\n");
747    for (auto& it : vec) {
748        EXPECT_TRUE(regex_match(it.substr(0, 24), pattern));
749    }
750
751    cmd = "hilog -v year -z 5";
752    pattern = "(\\d{4})-(0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01])\\s(0\\d{1}|1\\d{1}|2[0-3])"
753            ":[0-5]\\d{1}:([0-5]\\d{1})(\\.(\\d){0,3})?$";
754    res = GetCmdResultFromPopen(cmd);
755    Split(res, vec, "\n");
756    for (auto& it : vec) {
757        EXPECT_TRUE(regex_match(it.substr(0, 23), pattern));
758    }
759
760    cmd = "hilog -v zone -z 5";
761    std::regex gmtPattern("GMT (0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01])\\s(0\\d{1}|1\\d{1}|2[0-3])"
762            ":[0-5]\\d{1}:([0-5]\\d{1})(\\.(\\d){0,3})?$");
763    std::regex cstPattern("CST (0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01])\\s(0\\d{1}|1\\d{1}|2[0-3])"
764            ":[0-5]\\d{1}:([0-5]\\d{1})(\\.(\\d){0,3})?$");
765    res = GetCmdResultFromPopen(cmd);
766    Split(res, vec, "\n");
767    for (auto& it : vec) {
768        EXPECT_TRUE(regex_match(it.substr(0, 22), gmtPattern) || regex_match(it.substr(0, 22), cstPattern));
769    }
770
771    cmd = "hilog -v test 2>&1";
772    std::string errMsg = ErrorCode2Str(ERR_INVALID_ARGUMENT) + "\n";
773    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
774
775    cmd = "hilog -v time -v epoch 2>&1";
776    errMsg = ErrorCode2Str(ERR_DUPLICATE_OPTION) + "\n";
777    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
778
779    cmd = "hilog -v msec -v usec 2>&1";
780    errMsg = ErrorCode2Str(ERR_DUPLICATE_OPTION) + "\n";
781    EXPECT_EQ(GetCmdResultFromPopen(cmd), errMsg);
782
783    cmd = "hilog -x -v color";
784    EXPECT_GT(GetCmdLinesFromPopen(cmd), 0);
785}
786
787/**
788 * @tc.name: Dfx_HilogToolTest_HandleTest_018
789 * @tc.desc: QueryLogHandler.
790 * @tc.type: FUNC
791 */
792HWTEST_F(HilogToolTest, HandleTest_018, TestSize.Level1)
793{
794    /**
795     * @tc.steps: step1. query log of specific pid.
796     * @tc.steps: step2. query log of specific domain.
797     * @tc.steps: step3. query log of specific tag.
798     */
799    GTEST_LOG_(INFO) << "HandleTest_018: start.";
800    std::string res = GetCmdResultFromPopen("hilog -z 1");
801    std::string pid = res.substr(19, 5);
802    std::string domain = res.substr(34, 5);
803    int tagLen = res.substr(40).find(":") + 1;
804    std::string tag = res.substr(40, tagLen);
805    std::string queryDomainCmd = "hilog -x -D d0" + domain;
806    std::string queryPidCmd = "hilog -x -P " + pid;
807    std::string queryTagCmd = "hilog -x -T " + tag;
808    vector<string> vec;
809
810    res = GetCmdResultFromPopen(queryPidCmd);
811    if (res != "") {
812        Split(res, vec, "\n");
813        for (auto& it : vec) {
814            std::string logPid = it.substr(19, 5);
815            EXPECT_EQ(logPid, pid);
816        }
817    }
818
819    res = GetCmdResultFromPopen(queryDomainCmd);
820    if (res != "") {
821        Split(res, vec, "\n");
822        for (auto& it : vec) {
823            std::string logDomain = it.substr(34, 5);
824            EXPECT_EQ(logDomain, domain);
825        }
826    }
827
828    res = GetCmdResultFromPopen(queryTagCmd);
829    if (res != "") {
830        Split(res, vec, "\n");
831        for (auto& it : vec) {
832            std::string logTag = it.substr(40, tagLen);
833            EXPECT_EQ(logTag, tag);
834        }
835    }
836}
837
838/**
839 * @tc.name: Dfx_HilogToolTest_HandleTest_019
840 * @tc.desc: tag & domain level ctl.
841 * @tc.type: FUNC
842 */
843HWTEST_F(HilogToolTest, HandleTest_019, TestSize.Level1)
844{
845    /**
846     * @tc.steps: step1. tag level ctl.
847     * @tc.steps: step2. domain level ctl.
848     */
849    GTEST_LOG_(INFO) << "HandleTest_019: start.";
850    std::string res = GetCmdResultFromPopen("hilog -z 1");
851    uint32_t domain = std::stoi(res.substr(34, 5));
852    int tagLen = res.substr(40).find(":") + 1;
853    std::string tag = res.substr(40, tagLen);
854
855    // Priority: TagLevel > DomainLevel > GlobalLevel
856    SetTagLevel(tag, LOG_ERROR);
857    SetDomainLevel(domain, LOG_INFO);
858    EXPECT_FALSE(HiLogIsLoggable(domain, tag.c_str(), LOG_INFO));
859    EXPECT_TRUE(HiLogIsLoggable(domain, tag.c_str(), LOG_ERROR));
860
861    SetTagLevel(tag, LOG_INFO);
862    SetDomainLevel(domain, LOG_ERROR);
863    EXPECT_TRUE(HiLogIsLoggable(domain, tag.c_str(), LOG_INFO));
864    EXPECT_TRUE(HiLogIsLoggable(domain, tag.c_str(), LOG_ERROR));
865
866    // restore log level
867    SetDomainLevel(domain, LOG_INFO);
868}
869
870/**
871 * @tc.name: Dfx_HilogToolTest_ClearTest_020
872 * @tc.desc: hilog -w clear can delete /data/log/hilog/hilog*.gz.
873 * @tc.type: FUNC
874 */
875HWTEST_F(HilogToolTest, HandleTest_020, TestSize.Level1)
876{
877    GTEST_LOG_(INFO) << "HandleTest_020: start.";
878    (void)GetCmdResultFromPopen("hilog -w stop");
879    std::string cmd = "hilog -w clear";
880    std::string str = "Persist log /data/log/hilog clear successfully\n";
881    EXPECT_EQ(GetCmdResultFromPopen(cmd), str);
882
883    std::regex hilogFilePattern("^hilog.*gz$");
884    DIR *dir = nullptr;
885    struct dirent *ent = nullptr;
886    if ((dir = opendir("/data/log/hilog")) != nullptr) {
887        while ((ent = readdir(dir)) != nullptr) {
888            EXPECT_FALSE(std::regex_match(ent->d_name, hilogFilePattern));
889        }
890    }
891    if (dir != nullptr) {
892        closedir(dir);
893    }
894    (void)GetCmdResultFromPopen("hilog -w start");
895}
896} // namespace
897