1 /*
2 * Copyright (c) 2021-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 "debug_logger_test.h"
16
17 #include <random>
18
19 #include <debug_logger.h>
20 #include <gtest/gtest_prod.h>
21
22 using namespace testing::ext;
23 using namespace std;
24 using namespace OHOS::HiviewDFX;
25 namespace OHOS {
26 namespace Developtools {
27 namespace HiPerf {
28 DebugLevel DebugLogger::debugLevel_ = DEFAULT_LOG_LEVEL;
29 bool DebugLogger::logDisabled_ = false;
30
31 class DebugLoggerTest : public testing::Test {
32 public:
33 static void SetUpTestCase(void);
34 static void TearDownTestCase(void);
35 void SetUp();
36 void TearDown();
37 void LogLevelTest(DebugLevel testlevel, bool useStdout = false);
38 const std::string TEST_LOG_MESSAGE = "<HELLO_TEST_LOG_MESSAGE>";
39 std::random_device rd_;
40 };
41
SetUpTestCase()42 void DebugLoggerTest::SetUpTestCase()
43 {
44 DebugLogger::GetInstance()->Reset();
45 }
46
TearDownTestCase()47 void DebugLoggerTest::TearDownTestCase()
48 {
49 DebugLogger::GetInstance()->Reset();
50 }
51
SetUp()52 void DebugLoggerTest::SetUp() {}
53
TearDown()54 void DebugLoggerTest::TearDown() {}
55
LogLevelTest(DebugLevel testlevel,bool useStdout)56 void DebugLoggerTest::LogLevelTest(DebugLevel testlevel, bool useStdout)
57 {
58 StdoutRecord stdoutRecord;
59 std::string log;
60 // backup
61 DebugLogger::GetInstance()->exitOnFatal_ = false;
62 DebugLevel oldLevel = DebugLogger::GetInstance()->GetLogLevel();
63 DebugLogger::GetInstance()->SetLogLevel(testlevel);
64
65 const std::string logMessage =
66 TEST_LOG_MESSAGE + std::to_string(rd_()) + std::to_string(testlevel);
67
68 if (useStdout) {
69 stdoutRecord.Start();
70 }
71
72 HLOGF("%s", logMessage.c_str());
73 HLOGE("%s", logMessage.c_str());
74 HLOGW("%s", logMessage.c_str());
75 HLOGI("%s", logMessage.c_str());
76 HLOGD("%s", logMessage.c_str());
77 HLOGV("%s", logMessage.c_str());
78 HLOGM("%s", logMessage.c_str());
79
80 if (useStdout) {
81 log = stdoutRecord.Stop();
82 } else {
83 fflush(DebugLogger::GetInstance()->file_);
84 log = ReadFileToString(DebugLogger::GetInstance()->logPath_);
85 }
86
87 // we have 7 level log
88 // so the logout line is : (all log level - curr log level) + curr log level self
89 if (testlevel > LEVEL_FATAL or DebugLogger::GetInstance()->enableHilog_ or
90 DebugLogger::GetInstance()->logDisabled_) {
91 EXPECT_EQ(SubStringCount(log, logMessage), 0u);
92 } else {
93 EXPECT_EQ(SubStringCount(log, logMessage),
94 static_cast<size_t>(LEVEL_FATAL) - static_cast<size_t>(testlevel) + 1u);
95 }
96 if (HasFailure()) {
97 HLOGD("LogLevelTest failed. testlevel is %d, logMessage is '%s'", testlevel,
98 logMessage.c_str());
99 if (useStdout) {
100 printf("%s", log.c_str());
101 }
102 }
103 // restore
104 DebugLogger::GetInstance()->SetLogLevel(oldLevel);
105 DebugLogger::GetInstance()->exitOnFatal_ = true;
106 }
107
108 /**
109 * @tc.name: Log
110 * @tc.desc:
111 * @tc.type: FUNC
112 */
113 HWTEST_F(DebugLoggerTest, Log, TestSize.Level1)
114 {
115 DebugLogger::GetInstance()->SetMixLogOutput(true);
116 StdoutRecord stdoutRecord;
117 std::string log;
118
119 stdoutRecord.Start();
120 HLOGD("123");
121 log = stdoutRecord.Stop();
122 ASSERT_TRUE(log.size() >= 4u);
123 EXPECT_STREQ(log.substr(log.size() - 4u).c_str(), "123\n");
124
125 stdoutRecord.Start();
126 HLOGD("%% %% %%");
127 log = stdoutRecord.Stop();
128 EXPECT_STREQ(log.substr(log.size() - 6u).c_str(), "% % %\n");
129
130 DebugLogger::GetInstance()->SetMixLogOutput(false);
131
132 stdoutRecord.Start();
133 printf("123\n");
134 log = stdoutRecord.Stop();
135 EXPECT_STREQ(log.c_str(), "123\n");
136
137 stdoutRecord.Start();
138 printf("%% %% %%\n");
139 log = stdoutRecord.Stop();
140 EXPECT_STREQ(log.c_str(), "% % %\n");
141 }
142
143 /**
144 * @tc.name: SetMixLogOutput
145 * @tc.desc:
146 * @tc.type: FUNC
147 */
148 HWTEST_F(DebugLoggerTest, SetMixLogOutput, TestSize.Level1)
149 {
150 DebugLogger::GetInstance()->SetMixLogOutput(true);
151 for (int loglevel = LEVEL_MUCH; loglevel < LEVEL_MAX; loglevel++) {
152 LogLevelTest(static_cast<DebugLevel>(loglevel), true);
153 }
154
155 DebugLogger::GetInstance()->SetMixLogOutput(false);
156 for (int loglevel = LEVEL_MUCH; loglevel < LEVEL_MAX; loglevel++) {
157 LogLevelTest(static_cast<DebugLevel>(loglevel), false);
158 }
159 }
160
161 /**
162 * @tc.name: SetLogLevel
163 * @tc.desc:
164 * @tc.type: FUNC
165 */
166 HWTEST_F(DebugLoggerTest, SetLogLevel, TestSize.Level1)
167 {
168 for (int loglevel = LEVEL_MUCH; loglevel < LEVEL_MAX; loglevel++) {
169 LogLevelTest(static_cast<DebugLevel>(loglevel));
170 }
171 }
172
173 /**
174 * @tc.name: GetInstance
175 * @tc.desc:
176 * @tc.type: FUNC
177 */
178 HWTEST_F(DebugLoggerTest, GetInstance, TestSize.Level1)
179 {
180 EXPECT_NE(DebugLogger::GetInstance(), nullptr);
181 }
182
183 /**
184 * @tc.name: SetLogPath
185 * @tc.desc:
186 * @tc.type: FUNC
187 */
188 HWTEST_F(DebugLoggerTest, SetLogPath, TestSize.Level1)
189 {
190 const std::string logFile1 = "log1.txt";
191 const std::string logFile2 = "log2.txt";
192 const std::string logFile3 = "log3.txt";
193
194 EXPECT_EQ(access(DEFAULT_LOG_PATH.c_str(), F_OK), 0);
195
196 DebugLogger::GetInstance()->SetLogPath(logFile1);
197 EXPECT_NE(access(DEFAULT_LOG_PATH.c_str(), F_OK), 0);
198 EXPECT_EQ(access(logFile1.c_str(), F_OK), 0);
199
200 DebugLogger::GetInstance()->SetLogPath(logFile2);
201 EXPECT_NE(access(logFile1.c_str(), F_OK), 0);
202 EXPECT_EQ(access(logFile2.c_str(), F_OK), 0);
203
204 DebugLogger::GetInstance()->SetLogPath(logFile3);
205 EXPECT_NE(access(logFile2.c_str(), F_OK), 0);
206 EXPECT_EQ(access(logFile3.c_str(), F_OK), 0);
207
208 DebugLogger::GetInstance()->SetLogPath(DEFAULT_LOG_PATH);
209 EXPECT_NE(access(logFile3.c_str(), F_OK), 0);
210 EXPECT_EQ(access(DEFAULT_LOG_PATH.c_str(), F_OK), 0);
211 }
212
213 /**
214 * @tc.name: SetLogPath
215 * @tc.desc:
216 * @tc.type: FUNC
217 */
218 HWTEST_F(DebugLoggerTest, SetLogTags, TestSize.Level1)
219 {
220 const std::string errorLogTag = "errtag";
221 const std::string errorLogTags = "errtag,errtag,errtag";
222 const std::string mixLogTags = "errtag,errtag,DebugTest,errtag";
223
224 DebugLogger::GetInstance()->SetLogTags("DebugTest");
225
226 EXPECT_EQ(DebugLogger::GetInstance()->ShouldLog(LEVEL_MUCH, "DebugTest"), true);
227 EXPECT_EQ(DebugLogger::GetInstance()->ShouldLog(LEVEL_DEBUG, "DebugTest"), true);
228
229 EXPECT_EQ(DebugLogger::GetInstance()->ShouldLog(LEVEL_MUCH, errorLogTag), false);
230 EXPECT_EQ(DebugLogger::GetInstance()->ShouldLog(LEVEL_DEBUG, errorLogTag), true);
231
232 DebugLogger::GetInstance()->SetLogTags(errorLogTags);
233
234 EXPECT_EQ(DebugLogger::GetInstance()->ShouldLog(LEVEL_MUCH, "DebugTest"), false);
235 EXPECT_EQ(DebugLogger::GetInstance()->ShouldLog(LEVEL_DEBUG, "DebugTest"), true);
236
237 EXPECT_EQ(DebugLogger::GetInstance()->ShouldLog(LEVEL_MUCH, errorLogTag), true);
238 EXPECT_EQ(DebugLogger::GetInstance()->ShouldLog(LEVEL_DEBUG, errorLogTag), true);
239
240 DebugLogger::GetInstance()->SetLogTags(mixLogTags);
241
242 EXPECT_EQ(DebugLogger::GetInstance()->ShouldLog(LEVEL_MUCH, "DebugTest"), true);
243 EXPECT_EQ(DebugLogger::GetInstance()->ShouldLog(LEVEL_DEBUG, "DebugTest"), true);
244
245 // back to default
246 DebugLogger::GetInstance()->SetLogTags("");
247 }
248
249 /**
250 * @tc.name: Disable
251 * @tc.desc:
252 * @tc.type: FUNC
253 */
254 HWTEST_F(DebugLoggerTest, Disable, TestSize.Level1)
255 {
256 HLOGD("log disabled");
257 DebugLogger::GetInstance()->Disable(true);
258 ASSERT_EQ(DebugLogger::GetInstance()->logDisabled_, true);
259 for (int loglevel = LEVEL_MUCH; loglevel < LEVEL_MAX; loglevel++) {
260 LogLevelTest(static_cast<DebugLevel>(loglevel));
261 }
262 ASSERT_EQ(DebugLogger::GetInstance()->logDisabled_, true);
263
264 HLOGD("log enabled");
265 DebugLogger::GetInstance()->Disable(false);
266 ASSERT_EQ(DebugLogger::GetInstance()->logDisabled_, false);
267 for (int loglevel = LEVEL_MUCH; loglevel < LEVEL_MAX; loglevel++) {
268 LogLevelTest(static_cast<DebugLevel>(loglevel));
269 }
270 }
271
272 /**
273 * @tc.name: EnableHiLog
274 * @tc.desc:
275 * @tc.type: FUNC
276 */
277 HWTEST_F(DebugLoggerTest, EnableHiLog, TestSize.Level1)
278 {
279 #if is_ohos
280 DebugLogger::GetInstance()->EnableHiLog(true);
281 for (int loglevel = LEVEL_MUCH; loglevel < LEVEL_MAX; loglevel++) {
282 LogLevelTest(static_cast<DebugLevel>(loglevel));
283 }
284 DebugLogger::GetInstance()->EnableHiLog(false);
285 #endif
286 }
287 } // namespace HiPerf
288 } // namespace Developtools
289 } // namespace OHOS
290