1 /*
2 * Copyright (c) 2021-2023 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 <string>
16 #include <vector>
17
18 #include <fcntl.h>
19 #include <fstream>
20 #include <gtest/gtest.h>
21 #include <regex>
22 #include "sys_event.h"
23 #include <sys/stat.h>
24 #include <sys/syscall.h>
25 #include <sys/types.h>
26 #include <sys/inotify.h>
27 #include <sys/ioctl.h>
28 #include <unistd.h>
29
30 #include "bundle_mgr_client.h"
31 #include "event.h"
32 #include "faultlog_util.h"
33 #include "faultlog_database.h"
34 #include "faultlogger.h"
35 #include "faultevent_listener.h"
36 #include "faultlog_formatter.h"
37 #include "faultlog_info_ohos.h"
38 #include "faultlog_query_result_ohos.h"
39 #include "faultlogger_adapter.h"
40 #include "faultlogger_service_ohos.h"
41 #include "file_util.h"
42 #include "hisysevent_manager.h"
43 #include "hiview_global.h"
44 #include "hiview_logger.h"
45 #include "hiview_platform.h"
46 #include "ipc_skeleton.h"
47 #include "json/json.h"
48 #include "log_analyzer.h"
49 #include "sys_event.h"
50 #include "sys_event_dao.h"
51 #include "dfx_bundle_util.h"
52
53 using namespace testing::ext;
54 using namespace OHOS::HiviewDFX;
55 namespace OHOS {
56 namespace HiviewDFX {
57 DEFINE_LOG_LABEL(0xD002D11, "FaultloggerUT");
58 static std::shared_ptr<FaultEventListener> faultEventListener = nullptr;
59 static std::map<int, std::string> fileNames_ = {};
60
InitHiviewContext()61 static HiviewContext& InitHiviewContext()
62 {
63 OHOS::HiviewDFX::HiviewPlatform &platform = HiviewPlatform::GetInstance();
64 bool result = platform.InitEnvironment("/data/test/test_faultlogger_data/hiview_platform_config");
65 printf("InitHiviewContext result:%d\n", result);
66 return platform;
67 }
68
GetHiviewContext()69 static HiviewContext& GetHiviewContext()
70 {
71 static HiviewContext& hiviewContext = InitHiviewContext();
72 return hiviewContext;
73 }
74
StartHisyseventListen(std::string domain,std::string eventName)75 static void StartHisyseventListen(std::string domain, std::string eventName)
76 {
77 faultEventListener = std::make_shared<FaultEventListener>();
78 ListenerRule tagRule(domain, eventName, RuleType::WHOLE_WORD);
79 std::vector<ListenerRule> sysRules = {tagRule};
80 HiSysEventManager::AddListener(faultEventListener, sysRules);
81 }
82
InitFaultloggerInstance()83 static std::shared_ptr<Faultlogger> InitFaultloggerInstance()
84 {
85 auto plugin = std::make_shared<Faultlogger>();
86 plugin->SetName("Faultlogger");
87 plugin->SetHandle(nullptr);
88 plugin->SetHiviewContext(&GetHiviewContext());
89 plugin->OnLoad();
90 return plugin;
91 }
92
GetFaultloggerInstance()93 static std::shared_ptr<Faultlogger> GetFaultloggerInstance()
94 {
95 static std::shared_ptr<Faultlogger> faultloggerInstance = InitFaultloggerInstance();
96 return faultloggerInstance;
97 }
98
99 namespace {
__anon30fc4ce90202(int32_t *ptr) 100 auto g_fdDeleter = [] (int32_t *ptr) {
101 if (*ptr > 0) {
102 close(*ptr);
103 }
104 delete ptr;
105 };
106 }
107
108 class FaultloggerUnittest : public testing::Test {
109 public:
SetUp()110 void SetUp()
111 {
112 sleep(1);
113 GetHiviewContext();
114 };
TearDown()115 void TearDown() {};
116
CheckSumarryParseResult(std::string & info,int & matchCount)117 static void CheckSumarryParseResult(std::string& info, int& matchCount)
118 {
119 Json::Reader reader;
120 Json::Value appEvent;
121 if (!(reader.parse(info, appEvent))) {
122 matchCount--;
123 }
124 auto exception = appEvent["exception"];
125 GTEST_LOG_(INFO) << "========name:" << exception["name"];
126 if (exception["name"] == "" || exception["name"] == "none") {
127 matchCount--;
128 }
129 GTEST_LOG_(INFO) << "========message:" << exception["message"];
130 if (exception["message"] == "" || exception["message"] == "none") {
131 matchCount--;
132 }
133 GTEST_LOG_(INFO) << "========stack:" << exception["stack"];
134 if (exception["stack"] == "" || exception["stack"] == "none") {
135 matchCount--;
136 }
137 }
138
CheckKeyWordsInFile(const std::string & filePath,std::string * keywords,int length,bool isJsError)139 static int CheckKeyWordsInFile(const std::string& filePath, std::string *keywords, int length, bool isJsError)
140 {
141 std::ifstream file;
142 file.open(filePath.c_str(), std::ios::in);
143 std::ostringstream infoStream;
144 infoStream << file.rdbuf();
145 std::string info = infoStream.str();
146 if (info.length() == 0) {
147 std::cout << "file is empty, file:" << filePath << std::endl;
148 return 0;
149 }
150 int matchCount = 0;
151 for (int index = 0; index < length; index++) {
152 if (info.find(keywords[index]) != std::string::npos) {
153 matchCount++;
154 } else {
155 std::cout << "can not find keyword:" << keywords[index] << std::endl;
156 }
157 }
158 if (isJsError) {
159 CheckSumarryParseResult(info, matchCount);
160 }
161 file.close();
162 return matchCount;
163 }
164
ConstructJsErrorAppEvent(std::string summmay,std::shared_ptr<Faultlogger> plugin)165 static void ConstructJsErrorAppEvent(std::string summmay, std::shared_ptr<Faultlogger> plugin)
166 {
167 SysEventCreator sysEventCreator("AAFWK", "JSERROR", SysEventCreator::FAULT);
168 sysEventCreator.SetKeyValue("SUMMARY", summmay);
169 sysEventCreator.SetKeyValue("name_", "JS_ERROR");
170 sysEventCreator.SetKeyValue("happenTime_", 1670248360359); // 1670248360359 : Simulate happenTime_ value
171 sysEventCreator.SetKeyValue("REASON", "TypeError");
172 sysEventCreator.SetKeyValue("tz_", "+0800");
173 sysEventCreator.SetKeyValue("pid_", 2413); // 2413 : Simulate pid_ value
174 sysEventCreator.SetKeyValue("tid_", 2413); // 2413 : Simulate tid_ value
175 sysEventCreator.SetKeyValue("what_", 3); // 3 : Simulate what_ value
176 sysEventCreator.SetKeyValue("PACKAGE_NAME", "com.ohos.systemui");
177 sysEventCreator.SetKeyValue("VERSION", "1.0.0");
178 sysEventCreator.SetKeyValue("TYPE", 3); // 3 : Simulate TYPE value
179 sysEventCreator.SetKeyValue("VERSION", "1.0.0");
180
181 auto sysEvent = std::make_shared<SysEvent>("test", nullptr, sysEventCreator);
182 std::shared_ptr<Event> event = std::dynamic_pointer_cast<Event>(sysEvent);
183 bool result = plugin->OnEvent(event);
184 ASSERT_EQ(result, true);
185 }
186
ConstructJsErrorAppEventWithNoValue(std::string summmay,std::shared_ptr<Faultlogger> plugin)187 static void ConstructJsErrorAppEventWithNoValue(std::string summmay, std::shared_ptr<Faultlogger> plugin)
188 {
189 SysEventCreator sysEventCreator("AAFWK", "JSERROR", SysEventCreator::FAULT);
190 sysEventCreator.SetKeyValue("SUMMARY", summmay);
191 sysEventCreator.SetKeyValue("name_", "JS_ERROR");
192 sysEventCreator.SetKeyValue("happenTime_", 1670248360359); // 1670248360359 : Simulate happenTime_ value
193 sysEventCreator.SetKeyValue("TYPE", 3); // 3 : Simulate TYPE value
194 sysEventCreator.SetKeyValue("VERSION", "1.0.0");
195
196 auto sysEvent = std::make_shared<SysEvent>("test", nullptr, sysEventCreator);
197 std::shared_ptr<Event> event = std::dynamic_pointer_cast<Event>(sysEvent);
198 bool result = plugin->OnEvent(event);
199 ASSERT_EQ(result, true);
200 }
201
CheckKeyWordsInJsErrorAppEventFile(std::string name)202 static void CheckKeyWordsInJsErrorAppEventFile(std::string name)
203 {
204 std::string keywords[] = {
205 "\"bundle_name\":", "\"bundle_version\":", "\"crash_type\":", "\"exception\":",
206 "\"foreground\":", "\"hilog\":", "\"pid\":", "\"time\":", "\"uid\":", "\"uuid\":",
207 "\"name\":", "\"message\":", "\"stack\":"
208 };
209 int length = sizeof(keywords) / sizeof(keywords[0]);
210 std::cout << "length:" << length << std::endl;
211 std::string oldFileName = "/data/test_jsError_info";
212 int count = CheckKeyWordsInFile(oldFileName, keywords, length, true);
213 std::cout << "count:" << count << std::endl;
214 ASSERT_EQ(count, length) << "ReportJsErrorToAppEventTest001-" + name + " check keywords failed";
215 if (FileUtil::FileExists(oldFileName)) {
216 std::string newFileName = oldFileName + "_" + name;
217 rename(oldFileName.c_str(), newFileName.c_str());
218 }
219 auto ret = remove("/data/test_jsError_info");
220 if (ret == 0) {
221 GTEST_LOG_(INFO) << "remove /data/test_jsError_info failed";
222 }
223 }
224
ConstructCjErrorAppEvent(std::string summmay,std::shared_ptr<Faultlogger> plugin)225 static void ConstructCjErrorAppEvent(std::string summmay, std::shared_ptr<Faultlogger> plugin)
226 {
227 SysEventCreator sysEventCreator("CJ_RUNTIME", "CJERROR", SysEventCreator::FAULT);
228 sysEventCreator.SetKeyValue("SUMMARY", summmay);
229 sysEventCreator.SetKeyValue("name_", "CJ_ERROR");
230 sysEventCreator.SetKeyValue("happenTime_", 1670248360359); // 1670248360359 : Simulate happenTime_ value
231 sysEventCreator.SetKeyValue("REASON", "std.core:Exception");
232 sysEventCreator.SetKeyValue("tz_", "+0800");
233 sysEventCreator.SetKeyValue("pid_", 2413); // 2413 : Simulate pid_ value
234 sysEventCreator.SetKeyValue("tid_", 2413); // 2413 : Simulate tid_ value
235 sysEventCreator.SetKeyValue("what_", 3); // 3 : Simulate what_ value
236 sysEventCreator.SetKeyValue("PACKAGE_NAME", "com.ohos.systemui");
237 sysEventCreator.SetKeyValue("VERSION", "1.0.0");
238 sysEventCreator.SetKeyValue("TYPE", 3); // 3 : Simulate TYPE value
239 sysEventCreator.SetKeyValue("VERSION", "1.0.0");
240
241 auto sysEvent = std::make_shared<SysEvent>("test", nullptr, sysEventCreator);
242 std::shared_ptr<Event> event = std::dynamic_pointer_cast<Event>(sysEvent);
243 bool result = plugin->OnEvent(event);
244 ASSERT_EQ(result, true);
245 }
246
CheckKeyWordsInCjErrorAppEventFile(std::string name)247 static void CheckKeyWordsInCjErrorAppEventFile(std::string name)
248 {
249 std::string keywords[] = {
250 "\"bundle_name\":", "\"bundle_version\":", "\"crash_type\":", "\"exception\":",
251 "\"foreground\":", "\"hilog\":", "\"pid\":", "\"time\":", "\"uid\":", "\"uuid\":",
252 "\"name\":", "\"message\":", "\"stack\":"
253 };
254 int length = sizeof(keywords) / sizeof(keywords[0]);
255 std::cout << "length:" << length << std::endl;
256 std::string oldFileName = "/data/test_cjError_info";
257 int count = CheckKeyWordsInFile(oldFileName, keywords, length, false);
258 std::cout << "count:" << count << std::endl;
259 ASSERT_EQ(count, length) << "ReportCjErrorToAppEventTest001-" + name + " check keywords failed";
260 if (FileUtil::FileExists(oldFileName)) {
261 std::string newFileName = oldFileName + "_" + name;
262 rename(oldFileName.c_str(), newFileName.c_str());
263 }
264 auto ret = remove("/data/test_cjError_info");
265 if (ret == 0) {
266 GTEST_LOG_(INFO) << "remove /data/test_cjError_info failed";
267 }
268 }
269
CheckDeleteStackErrorMessage(std::string name)270 static void CheckDeleteStackErrorMessage(std::string name)
271 {
272 std::string keywords[] = {"\"Cannot get SourceMap info, dump raw stack:"};
273 int length = sizeof(keywords) / sizeof(keywords[0]);
274 std::cout << "========length:" << length << std::endl;
275 std::string oldFileName = "/data/test_jsError_info";
276 int count = CheckKeyWordsInFile(oldFileName, keywords, length, true);
277 std::cout << "========count:" << count << std::endl;
278 ASSERT_NE(count, length) << "check delete stack error message failed";
279 }
280 };
281
282 static const std::string APPFREEZE_FAULT_FILE = "/data/test/test_data/SmartParser/test_faultlogger_data/";
283
284 /**
285 * @tc.name: dumpFileListTest001
286 * @tc.desc: dump with cmds, check the result
287 * @tc.type: FUNC
288 */
289 HWTEST_F(FaultloggerUnittest, dumpFileListTest001, testing::ext::TestSize.Level3)
290 {
291 /**
292 * @tc.steps: step1. add multiple cmds to faultlogger
293 * @tc.expected: check the content size of the dump function
294 */
295 auto plugin = GetFaultloggerInstance();
296 int fd = TEMP_FAILURE_RETRY(open("/data/test/testFile", O_CREAT | O_WRONLY | O_TRUNC, 770));
297 bool isSuccess = fd >= 0;
298 if (!isSuccess) {
299 ASSERT_FALSE(isSuccess);
300 printf("Fail to create test result file.\n");
301 return;
302 }
303 std::vector<std::string> cmds;
304 plugin->Dump(fd, cmds);
305 cmds.push_back("Faultlogger");
306 plugin->Dump(fd, cmds);
307 cmds.push_back("-l");
308 plugin->Dump(fd, cmds);
309 cmds.push_back("-f");
310 plugin->Dump(fd, cmds);
311 cmds.push_back("cppcrash-ModuleName-10-20201209103823");
312 plugin->Dump(fd, cmds);
313 cmds.push_back("-d");
314 plugin->Dump(fd, cmds);
315 cmds.push_back("-t");
316 plugin->Dump(fd, cmds);
317 cmds.push_back("20201209103823");
318 plugin->Dump(fd, cmds);
319 cmds.push_back("-m");
320 plugin->Dump(fd, cmds);
321 cmds.push_back("FAULTLOGGER");
322 close(fd);
323 fd = -1;
324
325 std::string result;
326 if (FileUtil::LoadStringFromFile("/data/test/testFile", result)) {
327 ASSERT_GT(result.length(), 0uL);
328 } else {
329 FAIL();
330 }
331 }
332
333 /**
334 * @tc.name: DumpTest002
335 * @tc.desc: dump with cmds, check the result
336 * @tc.type: FUNC
337 */
338 HWTEST_F(FaultloggerUnittest, DumpTest002, testing::ext::TestSize.Level3)
339 {
340 /**
341 * @tc.steps: step1. add multiple cmds to faultlogger
342 * @tc.expected: check the content size of the dump function
343 */
344 auto plugin = GetFaultloggerInstance();
345 int fd = TEMP_FAILURE_RETRY(open("/data/test/testFile", O_CREAT | O_WRONLY | O_TRUNC, 770));
346 bool isSuccess = fd >= 0;
347 if (!isSuccess) {
348 ASSERT_FALSE(isSuccess);
349 printf("Fail to create test result file.\n");
350 return;
351 }
352 std::vector<std::vector<std::string>> cmds = {
353 {"-f", "1cppcrash-10-20201209103823"},
354 {"-f", "1cppcrash-ModuleName-10-20201209103823"},
355 {"-f", "cppcrash--10-20201209103823"},
356 {"-f", "cppcrash-ModuleName-a10-20201209103823"}
357 };
358
359 for (auto& cmd : cmds) {
360 plugin->Dump(fd, cmd);
361 }
362
363 close(fd);
364 fd = -1;
365
366 std::string result;
367 if (FileUtil::LoadStringFromFile("/data/test/testFile", result)) {
368 ASSERT_GT(result.length(), 0uL);
369 } else {
370 FAIL();
371 }
372 }
373
374 /**
375 * @tc.name: DumpTest003
376 * @tc.desc: dump with cmds, check the result
377 * @tc.type: FUNC
378 */
379 HWTEST_F(FaultloggerUnittest, DumpTest003, testing::ext::TestSize.Level3)
380 {
381 /**
382 * @tc.steps: step1. add multiple cmds to faultlogger
383 * @tc.expected: check the content size of the dump function
384 */
385 auto plugin = GetFaultloggerInstance();
386 int fd = TEMP_FAILURE_RETRY(open("/data/test/testFile", O_CREAT | O_WRONLY | O_TRUNC, 770));
387 bool isSuccess = fd >= 0;
388 if (!isSuccess) {
389 ASSERT_FALSE(isSuccess);
390 printf("Fail to create test result file.\n");
391 return;
392 }
393 std::vector<std::vector<std::string>> cmds = {
394 {"-t", "cppcrash--10-20201209103823"},
395 {"-m", ""},
396 {"-l", ""},
397 {"-xx"}
398 };
399
400 for (auto& cmd : cmds) {
401 plugin->Dump(fd, cmd);
402 }
403
404 close(fd);
405 fd = -1;
406
407 std::string result;
408 if (FileUtil::LoadStringFromFile("/data/test/testFile", result)) {
409 ASSERT_GT(result.length(), 0uL);
410 } else {
411 FAIL();
412 }
413 }
414
415 /**
416 * @tc.name: DumpTest004
417 * @tc.desc: dump with cmds, check the result
418 * @tc.type: FUNC
419 */
420 HWTEST_F(FaultloggerUnittest, DumpTest004, testing::ext::TestSize.Level3)
421 {
422 /**
423 * @tc.steps: step1. add multiple cmds to faultlogger
424 * @tc.expected: check the content size of the dump function
425 */
426
427 auto plugin = GetFaultloggerInstance();
428 FaultLogInfo info;
429 info.time = 1607161163; // 1607161163 : analog value of time
430 info.id = 10001;
431 info.pid = 7496; // 7496 : analog value of pid
432 info.faultLogType = 2; // 2 : CPP_CRASH
433 info.module = "com.example.myapplication";
434 plugin->AddFaultLog(info);
435 std::string timeStr = GetFormatedTimeWithMillsec(info.time);
436 std::string appName = GetApplicationNameById(info.id);
437 if (appName.size() == 0) {
438 appName = info.module;
439 }
440 std::string fileName = "cppcrash-" + appName + "-" + std::to_string(info.id) + "-" + timeStr + ".log";
441 auto path = "/data/log/faultlog/faultlogger/" + fileName;
442 ASSERT_EQ(FileUtil::FileExists(path), true);
443
444 int fd = TEMP_FAILURE_RETRY(open("/data/test/testFile", O_CREAT | O_WRONLY | O_TRUNC, 770));
445 bool isSuccess = fd >= 0;
446 if (!isSuccess) {
447 ASSERT_FALSE(isSuccess);
448 printf("Fail to create test result file.\n");
449 return;
450 }
451 std::vector<std::vector<std::string>> cmds = {
452 {"-LogSuffixWithMs", ""},
453 {"-f", fileName}
454 };
455
456 for (auto& cmd : cmds) {
457 plugin->Dump(fd, cmd);
458 }
459
460 close(fd);
461 fd = -1;
462 std::string keywords[] = { "Device info", "Build info", "Fingerprint", "Module name" };
463 int length = sizeof(keywords) / sizeof(keywords[0]);
464 ASSERT_EQ(CheckKeyWordsInFile("/data/test/testFile", keywords, length, false), length);
465 }
466
GenCppCrashLogTestCommon(int32_t uid,bool ifFileExist)467 static void GenCppCrashLogTestCommon(int32_t uid, bool ifFileExist)
468 {
469 int pipeFd[2] = {-1, -1};
470 ASSERT_EQ(pipe(pipeFd), 0) << "create pipe failed";
471 auto plugin = GetFaultloggerInstance();
472 FaultLogInfo info;
473 info.time = 1607161163; // 1607161163 : analog value of time
474 info.id = uid;
475 info.pid = 7496; // 7496 : analog value of pid
476 info.faultLogType = 2; // 2 : CPP_CRASH
477 info.module = "com.example.myapplication";
478 info.sectionMap["APPVERSION"] = "1.0";
479 info.sectionMap["FAULT_MESSAGE"] = "Nullpointer";
480 info.sectionMap["TRACEID"] = "0x1646145645646";
481 info.sectionMap["KEY_THREAD_INFO"] = "Test Thread Info";
482 info.sectionMap["REASON"] = "TestReason";
483 info.sectionMap["STACKTRACE"] = "#01 xxxxxx\n#02 xxxxxx\n";
484 info.pipeFd.reset(new int32_t(pipeFd[0]), g_fdDeleter);
485 std::string jsonInfo = R"~({"crash_type":"NativeCrash", "exception":{"frames":
486 [{"buildId":"", "file":"/system/lib/ld-musl-arm.so.1", "offset":28, "pc":"000ac0a4", "symbol":"test_abc"},
487 {"buildId":"12345abcde", "file":"/system/lib/chipset-pub-sdk/libeventhandler.z.so", "offset":278,
488 "pc":"0000bef3", "symbol":"OHOS::AppExecFwk::EpollIoWaiter::WaitFor(std::__h::unique_lock<std::__h::mutex>&,
489 long long)"}], "message":"", "signal":{"code":0, "signo":6}, "thread_name":"e.myapplication", "tid":1605},
490 "pid":1605, "threads":[{"frames":[{"buildId":"", "file":"/system/lib/ld-musl-arm.so.1", "offset":72, "pc":
491 "000c80b4", "symbol":"ioctl"}, {"buildId":"2349d05884359058d3009e1fe27b15fa", "file":
492 "/system/lib/platformsdk/libipc_core.z.so", "offset":26, "pc":"0002cad7",
493 "symbol":"OHOS::BinderConnector::WriteBinder(unsigned long, void*)"}], "thread_name":"OS_IPC_0_1607",
494 "tid":1607}, {"frames":[{"buildId":"", "file":"/system/lib/ld-musl-arm.so.1", "offset":0, "pc":"000fdf4c",
495 "symbol":""}, {"buildId":"", "file":"/system/lib/ld-musl-arm.so.1", "offset":628, "pc":"000ff7f4",
496 "symbol":"__pthread_cond_timedwait_time64"}], "thread_name":"OS_SignalHandle", "tid":1608}],
497 "time":1701863741296, "uid":20010043, "uuid":""})~";
498 TEMP_FAILURE_RETRY(write(pipeFd[1], jsonInfo.c_str(), jsonInfo.size()));
499 close(pipeFd[1]);
500 plugin->AddFaultLog(info);
501 std::string timeStr = GetFormatedTimeWithMillsec(info.time);
502 std::string appName = GetApplicationNameById(info.id);
503 if (appName.size() == 0) {
504 appName = info.module;
505 }
506 std::string fileName = "/data/log/faultlog/faultlogger/cppcrash-" + appName + "-" +
507 std::to_string(info.id) + "-" + timeStr + ".log";
508 ASSERT_EQ(FileUtil::FileExists(fileName), true);
509 ASSERT_GT(FileUtil::GetFileSize(fileName), 0ul);
510 // check appevent json info
511 ASSERT_EQ(FileUtil::FileExists("/data/test_cppcrash_info_7496"), ifFileExist);
512 }
513
514 /**
515 * @tc.name: genCppCrashLogTest001
516 * @tc.desc: create cpp crash event and send it to faultlogger
517 * check info which send to appevent
518 * @tc.type: FUNC
519 */
520 HWTEST_F(FaultloggerUnittest, GenCppCrashLogTest001, testing::ext::TestSize.Level3)
521 {
522 GenCppCrashLogTestCommon(10001, true); // 10001 : analog value of user uid
523 string keywords[] = { "\"time\":", "\"pid\":", "\"exception\":", "\"threads\":", "\"thread_name\":", "\"tid\":" };
524 int length = sizeof(keywords) / sizeof(keywords[0]);
525 ASSERT_EQ(CheckKeyWordsInFile("/data/test_cppcrash_info_7496", keywords, length, false), length);
526 auto ret = remove("/data/test_cppcrash_info_7496");
527 if (ret == 0) {
528 GTEST_LOG_(INFO) << "remove /data/test_jsError_info failed";
529 }
530 }
531
532 /**
533 * @tc.name: genCppCrashLogTest002
534 * @tc.desc: create cpp crash event and send it to faultlogger
535 * check info which send to appevent
536 * @tc.type: FUNC
537 */
538 HWTEST_F(FaultloggerUnittest, GenCppCrashLogTest002, testing::ext::TestSize.Level3)
539 {
540 GenCppCrashLogTestCommon(0, false); // 0 : analog value of system uid
541 }
542
543 /**
544 * @tc.name: AddFaultLogTest001
545 * @tc.desc: create cpp crash event and send it to faultlogger
546 * check info which send to appevent
547 * @tc.type: FUNC
548 */
549 HWTEST_F(FaultloggerUnittest, AddFaultLogTest001, testing::ext::TestSize.Level3)
550 {
551 auto plugin = GetFaultloggerInstance();
552 FaultLogInfo info;
553 plugin->hasInit_ = false;
554 plugin->AddFaultLog(info);
555
556 plugin->hasInit_ = true;
557 info.faultLogType = -1;
558 plugin->AddFaultLog(info);
559
560 info.faultLogType = 8; // 8 : 8 is bigger than FaultLogType::ADDR_SANITIZER
561 plugin->AddFaultLog(info);
562
563 info.faultLogType = FaultLogType::CPP_CRASH;
564 info.id = 1;
565 info.module = "com.example.myapplication";
566 info.time = 1607161163;
567 info.pid = 7496;
568 plugin->AddFaultLog(info);
569 std::string timeStr = GetFormatedTimeWithMillsec(info.time);
570 std::string fileName = "/data/log/faultlog/faultlogger/cppcrash-com.example.myapplication-0-" + timeStr + ".log";
571 ASSERT_EQ(FileUtil::FileExists(fileName), true);
572 }
573
574 /**
575 * @tc.name: AddPublicInfoTest001
576 * @tc.desc: create cpp crash event and send it to faultlogger
577 * check info which send to appevent
578 * @tc.type: FUNC
579 */
580 HWTEST_F(FaultloggerUnittest, AddPublicInfoTest001, testing::ext::TestSize.Level3)
581 {
582 auto plugin = GetFaultloggerInstance();
583 FaultLogInfo info;
584 info.time = 1607161163;
585 info.id = 0;
586 info.pid = 7496;
587 info.faultLogType = 1;
588 info.module = "com.example.myapplication";
589 info.sectionMap["APPVERSION"] = "1.0";
590 info.sectionMap["FAULT_MESSAGE"] = "Nullpointer";
591 info.sectionMap["TRACEID"] = "0x1646145645646";
592 info.sectionMap["KEY_THREAD_INFO"] = "Test Thread Info";
593 info.sectionMap["REASON"] = "TestReason";
594 info.sectionMap["STACKTRACE"] = "#01 xxxxxx\n#02 xxxxxx\n";
595 plugin->AddPublicInfo(info);
596 std::string timeStr = GetFormatedTimeWithMillsec(info.time);
597 std::string fileName = "/data/log/faultlog/faultlogger/cppcrash-com.example.myapplication-0-" + timeStr + ".log";
598 ASSERT_EQ(FileUtil::FileExists(fileName), true);
599 }
600
601 /**
602 * @tc.name: GetFreezeJsonCollectorTest001
603 * @tc.desc: test GetFreezeJsonCollector
604 * @tc.type: FUNC
605 */
606 HWTEST_F(FaultloggerUnittest, GetFreezeJsonCollectorTest001, testing::ext::TestSize.Level3)
607 {
608 auto plugin = GetFaultloggerInstance();
609 FaultLogInfo info;
610 info.time = 20170805172159;
611 info.id = 10006;
612 info.pid = 1;
613 info.faultLogType = 1;
614 info.module = "com.example.myapplication";
615 info.sectionMap["APPVERSION"] = "1.0";
616 info.sectionMap["FAULT_MESSAGE"] = "Nullpointer";
617 info.sectionMap["TRACEID"] = "0x1646145645646";
618 info.sectionMap["KEY_THREAD_INFO"] = "Test Thread Info";
619 info.sectionMap["REASON"] = "TestReason";
620 info.sectionMap["STACKTRACE"] = "#01 xxxxxx\n#02 xxxxxx\n";
621 FreezeJsonUtil::FreezeJsonCollector collector = plugin->GetFreezeJsonCollector(info);
622 ASSERT_EQ(collector.exception, "{}");
623 }
624
625 /**
626 * @tc.name: genCppCrashtoAnalysisFaultlog
627 * @tc.desc: create cpp crash event and check AnalysisFaultlog
628 * @tc.type: FUNC
629 */
630 HWTEST_F(FaultloggerUnittest, genCppCrashtoAnalysisFaultlog001, testing::ext::TestSize.Level3)
631 {
632 /**
633 * @tc.steps: step1. create a cpp crash event and pass it to faultlogger
634 * @tc.expected: AnalysisFaultlog return expected result
635 */
636 FaultLogInfo info;
637 info.time = 1607161163;
638 info.id = 0;
639 info.pid = 7497;
640 info.faultLogType = 2;
641 info.module = "com.example.testapplication";
642 info.reason = "TestReason";
643 std::map<std::string, std::string> eventInfos;
644 ASSERT_EQ(AnalysisFaultlog(info, eventInfos), false);
645 ASSERT_EQ(!eventInfos["FINGERPRINT"].empty(), true);
646 }
647
648 /**
649 * @tc.name: genJsCrashtoAnalysisFaultlog001
650 * @tc.desc: create Js crash FaultLogInfo and check AnalysisFaultlog
651 * @tc.type: FUNC
652 */
653 HWTEST_F(FaultloggerUnittest, genJsCrashtoAnalysisFaultlog001, testing::ext::TestSize.Level3)
654 {
655 /**
656 * @tc.steps: step1. create Js crash FaultLogInfo
657 * @tc.expected: AnalysisFaultlog return expected result
658 */
659 FaultLogInfo info;
660 info.time = 1607161163;
661 info.id = 0;
662 info.pid = 7497;
663 info.faultLogType = 3;
664 info.module = "com.example.testapplication";
665 info.reason = "TestReason";
666 std::map<std::string, std::string> eventInfos;
667 ASSERT_EQ(AnalysisFaultlog(info, eventInfos), false);
668 ASSERT_EQ(!eventInfos["FINGERPRINT"].empty(), true);
669 }
670
671 /**
672 * @tc.name: genjserrorLogTest002
673 * @tc.desc: create JS ERROR event and send it to faultlogger
674 * @tc.type: FUNC
675 */
676 HWTEST_F(FaultloggerUnittest, genjserrorLogTest002, testing::ext::TestSize.Level3)
677 {
678 /**
679 * @tc.steps: step1. create a jss_error event and pass it to faultlogger
680 * @tc.expected: the calling is success and the file has been created
681 */
682 SysEventCreator sysEventCreator("AAFWK", "JSERROR", SysEventCreator::FAULT);
683 sysEventCreator.SetKeyValue("SUMMARY", "Error message:is not callable\nStacktrace:");
684 sysEventCreator.SetKeyValue("name_", "JS_ERROR");
685 sysEventCreator.SetKeyValue("happenTime_", 1670248360359);
686 sysEventCreator.SetKeyValue("REASON", "TypeError");
687 sysEventCreator.SetKeyValue("tz_", "+0800");
688 sysEventCreator.SetKeyValue("pid_", 2413);
689 sysEventCreator.SetKeyValue("tid_", 2413);
690 sysEventCreator.SetKeyValue("what_", 3);
691 sysEventCreator.SetKeyValue("PACKAGE_NAME", "com.ohos.systemui");
692 sysEventCreator.SetKeyValue("VERSION", "1.0.0");
693 sysEventCreator.SetKeyValue("TYPE", 3);
694 sysEventCreator.SetKeyValue("VERSION", "1.0.0");
695
696 auto sysEvent = std::make_shared<SysEvent>("test", nullptr, sysEventCreator);
697 auto testPlugin = GetFaultloggerInstance();
698 std::shared_ptr<Event> event = std::dynamic_pointer_cast<Event>(sysEvent);
699 bool result = testPlugin->OnEvent(event);
700 ASSERT_EQ(result, true);
701 auto ret = remove("/data/test_jsError_info");
702 if (ret < 0) {
703 GTEST_LOG_(INFO) << "remove /data/test_jsError_info failed";
704 }
705 }
706
707 /**
708 * @tc.name: IsInterestedPipelineEvent
709 * @tc.desc: Test calling IsInterestedPipelineEvent Func
710 * @tc.type: FUNC
711 */
712 HWTEST_F(FaultloggerUnittest, IsInterestedPipelineEvent, testing::ext::TestSize.Level3)
713 {
714 auto testPlugin = GetFaultloggerInstance();
715 std::shared_ptr<Event> event = std::make_shared<Event>("test");
716 event->SetEventName("PROCESS_EXIT");
717 EXPECT_TRUE(testPlugin->IsInterestedPipelineEvent(event));
718 event->SetEventName("JS_ERROR");
719 EXPECT_TRUE(testPlugin->IsInterestedPipelineEvent(event));
720 event->SetEventName("RUST_PANIC");
721 EXPECT_TRUE(testPlugin->IsInterestedPipelineEvent(event));
722 event->SetEventName("ADDR_SANITIZER");
723 EXPECT_TRUE(testPlugin->IsInterestedPipelineEvent(event));
724 event->SetEventName("OTHERS");
725 EXPECT_FALSE(testPlugin->IsInterestedPipelineEvent(event));
726 };
727
728 /**
729 * @tc.name: CanProcessEvent
730 * @tc.desc: Test calling CanProcessEvent Func
731 * @tc.type: FUNC
732 */
733 HWTEST_F(FaultloggerUnittest, CanProcessEvent, testing::ext::TestSize.Level3)
734 {
735 auto testPlugin = GetFaultloggerInstance();
736 std::shared_ptr<Event> event = std::make_shared<Event>("test");
737 ASSERT_TRUE(testPlugin->CanProcessEvent(event));
738 };
739
740 /**
741 * @tc.name: ReadyToLoad
742 * @tc.desc: Test calling ReadyToLoad Func
743 * @tc.type: FUNC
744 */
745 HWTEST_F(FaultloggerUnittest, ReadyToLoad, testing::ext::TestSize.Level3)
746 {
747 auto testPlugin = GetFaultloggerInstance();
748 ASSERT_TRUE(testPlugin->ReadyToLoad());
749 };
750
751 /**
752 * @tc.name: SaveFaultLogInfoTest001
753 * @tc.desc: Test calling SaveFaultLogInfo Func
754 * @tc.type: FUNC
755 */
756 HWTEST_F(FaultloggerUnittest, SaveFaultLogInfoTest001, testing::ext::TestSize.Level3)
757 {
758 StartHisyseventListen("RELIABILITY", "CPP_CRASH");
759 time_t now = std::time(nullptr);
760 std::vector<std::string> keyWords = { std::to_string(now) };
761 faultEventListener->SetKeyWords(keyWords);
762 FaultLogDatabase *faultLogDb = new FaultLogDatabase(GetHiviewContext().GetSharedWorkLoop());
763 FaultLogInfo info;
764 info.time = now;
765 info.pid = getpid();
766 info.id = 0;
767 info.faultLogType = 2;
768 info.module = "FaultloggerUnittest";
769 info.reason = "unittest for SaveFaultLogInfo";
770 info.summary = "summary for SaveFaultLogInfo";
771 info.sectionMap["APPVERSION"] = "1.0";
772 info.sectionMap["FAULT_MESSAGE"] = "abort";
773 info.sectionMap["TRACEID"] = "0x1646145645646";
774 info.sectionMap["KEY_THREAD_INFO"] = "Test Thread Info";
775 info.sectionMap["REASON"] = "TestReason";
776 info.sectionMap["STACKTRACE"] = "#01 xxxxxx\n#02 xxxxxx\n";
777 faultLogDb->SaveFaultLogInfo(info);
778 ASSERT_TRUE(faultEventListener->CheckKeyWords());
779 }
780
781 /**
782 * @tc.name: GetFaultInfoListTest001
783 * @tc.desc: Test calling GetFaultInfoList Func
784 * @tc.type: FUNC
785 */
786 HWTEST_F(FaultloggerUnittest, GetFaultInfoListTest001, testing::ext::TestSize.Level3)
787 {
788 std::string jsonStr = R"~({"domain_":"RELIABILITY", "name_":"CPP_CRASH", "type_":1, "time_":1501973701070, "tz_":
789 "+0800", "pid_":1854, "tid_":1854, "uid_":0, "FAULT_TYPE":"2", "PID":1854, "UID":0, "MODULE":"FaultloggerUnittest",
790 "REASON":"unittest for SaveFaultLogInfo", "SUMMARY":"summary for SaveFaultLogInfo", "LOG_PATH":"", "VERSION":"",
791 "HAPPEN_TIME":"1501973701", "PNAME":"/", "FIRST_FRAME":"/", "SECOND_FRAME":"/", "LAST_FRAME":"/", "FINGERPRINT":
792 "04c0d6f03c73da531f00eb112479a8a2f19f59fafba6a474dcbe455a13288f4d", "level_":"CRITICAL", "tag_":"STABILITY", "id_":
793 "17165544771317691984", "info_":""})~";
794 auto sysEvent = std::make_shared<SysEvent>("SysEventSource", nullptr, jsonStr);
795 sysEvent->SetLevel("MINOR");
796 sysEvent->SetEventSeq(447); // 447: test seq
797 EventStore::SysEventDao::Insert(sysEvent);
798 FaultLogDatabase *faultLogDb = new FaultLogDatabase(GetHiviewContext().GetSharedWorkLoop());
799 std::list<FaultLogInfo> infoList = faultLogDb->GetFaultInfoList("FaultloggerUnittest", 0, 2, 10);
800 ASSERT_GT(infoList.size(), 0);
801 }
802
803 /**
804 * @tc.name: FaultLogManager::CreateTempFaultLogFile
805 * @tc.desc: Test calling CreateTempFaultLogFile Func
806 * @tc.type: FUNC
807 */
808 HWTEST_F(FaultloggerUnittest, FaultlogManager001, testing::ext::TestSize.Level3)
809 {
810 std::unique_ptr<FaultLogManager> faultLogManager = std::make_unique<FaultLogManager>(nullptr);
811 faultLogManager->Init();
812 int fd = faultLogManager->CreateTempFaultLogFile(1607161345, 0, 2, "FaultloggerUnittest");
813 ASSERT_GT(fd, 0);
814 std::string content = "testContent";
815 TEMP_FAILURE_RETRY(write(fd, content.data(), content.length()));
816 close(fd);
817 }
818
819 /**
820 * @tc.name: FaultLogManager::GetFaultLogFileList
821 * @tc.desc: Test calling GetFaultLogFileList Func
822 * @tc.type: FUNC
823 */
824 HWTEST_F(FaultloggerUnittest, GetFaultLogFileList001, testing::ext::TestSize.Level3)
825 {
826 std::unique_ptr<FaultLogManager> faultLogManager = std::make_unique<FaultLogManager>(nullptr);
827 faultLogManager->Init();
828 std::list<std::string> fileList = faultLogManager->GetFaultLogFileList("FaultloggerUnittest", 1607161344, 0, 2, 1);
829 ASSERT_EQ(fileList.size(), 1);
830 }
831
832 /**
833 * @tc.name: FaultLogManager::GetFaultLogContent
834 * @tc.desc: Test calling GetFaultLogContent Func
835 * @tc.type: FUNC
836 */
837 HWTEST_F(FaultloggerUnittest, GetFaultLogContent001, testing::ext::TestSize.Level3)
838 {
839 std::unique_ptr<FaultLogManager> faultLogManager = std::make_unique<FaultLogManager>(nullptr);
840 faultLogManager->Init();
841 FaultLogInfo info {
842 .time = 1607161345,
843 .id = 0,
844 .faultLogType = 2,
845 .module = "FaultloggerUnittest"
846 };
847 std::string fileName = GetFaultLogName(info);
848 std::string content;
849 ASSERT_TRUE(faultLogManager->GetFaultLogContent(fileName, content));
850 ASSERT_EQ(content, "testContent");
851 }
852
853 /**
854 * @tc.name: FaultLogManager::SaveFaultInfoToRawDb
855 * @tc.desc: Test calling SaveFaultInfoToRawDb Func
856 * @tc.type: FUNC
857 */
858 HWTEST_F(FaultloggerUnittest, FaultLogManagerTest001, testing::ext::TestSize.Level3)
859 {
860 StartHisyseventListen("RELIABILITY", "CPP_CRASH");
861 time_t now = std::time(nullptr);
862 std::vector<std::string> keyWords = { std::to_string(now) };
863 faultEventListener->SetKeyWords(keyWords);
864 FaultLogInfo info;
865 info.time = now;
866 info.pid = getpid();
867 info.id = 0;
868 info.faultLogType = 2;
869 info.module = "FaultloggerUnittest1111";
870 info.reason = "unittest for SaveFaultLogInfo";
871 info.summary = "summary for SaveFaultLogInfo";
872 info.sectionMap["APPVERSION"] = "1.0";
873 info.sectionMap["FAULT_MESSAGE"] = "abort";
874 info.sectionMap["TRACEID"] = "0x1646145645646";
875 info.sectionMap["KEY_THREAD_INFO"] = "Test Thread Info";
876 info.sectionMap["REASON"] = "TestReason";
877 info.sectionMap["STACKTRACE"] = "#01 xxxxxx\n#02 xxxxxx\n";
878 std::unique_ptr<FaultLogManager> faultLogManager =
879 std::make_unique<FaultLogManager>(GetHiviewContext().GetSharedWorkLoop());
880 faultLogManager->Init();
881 faultLogManager->SaveFaultInfoToRawDb(info);
882 ASSERT_TRUE(faultEventListener->CheckKeyWords());
883 }
884
GetTargetFileName(int32_t faultLogType,int64_t time)885 std::string GetTargetFileName(int32_t faultLogType, int64_t time)
886 {
887 fileNames_.clear();
888 fileNames_ = {
889 {1, "Unknown"},
890 {2, "cppcrash"}, // 2 : faultLogType to cppcrash
891 {3, "jscrash"}, // 3 : faultLogType to jscrash
892 {4, "appfreeze"}, // 4 : faultLogType to appfreeze
893 {5, "sysfreeze"}, // 5 : faultLogType to sysfreeze
894 {6, "syswarning"}, // 6 : faultLogType to syswarning
895 {7, "rustpanic"}, // 7 : faultLogType to rustpanic
896 {8, "sanitizer"}, // 8 : faultLogType to sanitizer
897 };
898 std::string fileName = fileNames_[faultLogType];
899 return fileName + "-FaultloggerUnittest1111-0-" + GetFormatedTimeWithMillsec(time) + ".log";
900 }
901
902 /**
903 * @tc.name: FaultLogManager::SaveFaultLogToFile
904 * @tc.desc: Test calling SaveFaultLogToFile Func
905 * @tc.type: FUNC
906 */
907 HWTEST_F(FaultloggerUnittest, FaultLogManagerTest003, testing::ext::TestSize.Level3)
908 {
909 FaultLogInfo info;
910 std::unique_ptr<FaultLogManager> faultLogManager = std::make_unique<FaultLogManager>(nullptr);
911 faultLogManager->Init();
912 for (int i = 1; i <= fileNames_.size(); i++) {
913 info.time = std::time(nullptr);
914 info.pid = getpid();
915 info.id = 0;
916 info.faultLogType = i;
917 info.module = "FaultloggerUnittest1111";
918 info.reason = "unittest for SaveFaultLogInfo";
919 info.summary = "summary for SaveFaultLogInfo";
920 info.sectionMap["APPVERSION"] = "1.0";
921 info.sectionMap["FAULT_MESSAGE"] = "abort";
922 info.sectionMap["TRACEID"] = "0x1646145645646";
923 info.sectionMap["KEY_THREAD_INFO"] = "Test Thread Info";
924 info.sectionMap["REASON"] = "TestReason";
925 info.sectionMap["STACKTRACE"] = "#01 xxxxxx\n#02 xxxxxx\n";
926
927 std::string fileName = faultLogManager->SaveFaultLogToFile(info);
928 if (fileName.find("FaultloggerUnittest1111") == std::string::npos) {
929 FAIL();
930 }
931 std::string targetFileName = GetTargetFileName(i, info.time);
932 ASSERT_EQ(fileName, targetFileName);
933 }
934 }
935
936 /**
937 * @tc.name: faultLogManager GetFaultInfoListTest001
938 * @tc.desc: Test calling faultLogManager.GetFaultInfoList Func
939 * @tc.type: FUNC
940 */
941 HWTEST_F(FaultloggerUnittest, FaultLogManagerTest002, testing::ext::TestSize.Level3)
942 {
943 std::string jsonStr = R"~({"domain_":"RELIABILITY", "name_":"CPP_CRASH", "type_":1, "time_":1501973701070,
944 "tz_":"+0800", "pid_":1854, "tid_":1854, "uid_":0, "FAULT_TYPE":"2", "PID":1854, "UID":0,
945 "MODULE":"FaultloggerUnittest", "REASON":"unittest for SaveFaultLogInfo",
946 "SUMMARY":"summary for SaveFaultLogInfo", "LOG_PATH":"", "VERSION":"", "HAPPEN_TIME":"1501973701",
947 "PNAME":"/", "FIRST_FRAME":"/", "SECOND_FRAME":"/", "LAST_FRAME":"/",
948 "FINGERPRINT":"04c0d6f03c73da531f00eb112479a8a2f19f59fafba6a474dcbe455a13288f4d",
949 "level_":"CRITICAL", "tag_":"STABILITY", "id_":"17165544771317691984", "info_":""})~";
950 auto sysEvent = std::make_shared<SysEvent>("SysEventSource", nullptr, jsonStr);
951 sysEvent->SetLevel("MINOR");
952 sysEvent->SetEventSeq(448); // 448: test seq
953 EventStore::SysEventDao::Insert(sysEvent);
954
955 std::unique_ptr<FaultLogManager> faultLogManager = std::make_unique<FaultLogManager>(nullptr);
956 auto isProcessedFault1 = faultLogManager->IsProcessedFault(1854, 0, 2);
957 ASSERT_EQ(isProcessedFault1, false);
958
959 faultLogManager->Init();
960
961 auto list = faultLogManager->GetFaultInfoList("FaultloggerUnittest", 0, 2, 10);
962 ASSERT_GT(list.size(), 0);
963
964 auto isProcessedFault2 = faultLogManager->IsProcessedFault(1854, 0, 2);
965 ASSERT_EQ(isProcessedFault2, true);
966
967 auto isProcessedFault3 = faultLogManager->IsProcessedFault(1855, 0, 2);
968 ASSERT_EQ(isProcessedFault3, false);
969
970 auto isProcessedFault4 = faultLogManager->IsProcessedFault(1855, 5, 2);
971 ASSERT_EQ(isProcessedFault4, false);
972 }
973
974 /**
975 * @tc.name: FaultLogUtilTest001
976 * @tc.desc: check ExtractInfoFromFileName Func
977 * @tc.type: FUNC
978 */
979 HWTEST_F(FaultloggerUnittest, FaultLogUtilTest001, testing::ext::TestSize.Level3)
980 {
981 std::string filename = "appfreeze-com.ohos.systemui-10006-20170805172159";
982 auto info = ExtractInfoFromFileName(filename);
983 ASSERT_EQ(info.pid, 0);
984 ASSERT_EQ(info.faultLogType, FaultLogType::APP_FREEZE); // 4 : APP_FREEZE
985 ASSERT_EQ(info.module, "com.ohos.systemui");
986 ASSERT_EQ(info.id, 10006); // 10006 : test uid
987 }
988
989 /**
990 * @tc.name: FaultLogUtilTest002
991 * @tc.desc: check ExtractInfoFromTempFile Func
992 * @tc.type: FUNC
993 */
994 HWTEST_F(FaultloggerUnittest, FaultLogUtilTest002, testing::ext::TestSize.Level3)
995 {
996 std::string filename = "appfreeze-10006-20170805172159";
997 auto info = ExtractInfoFromTempFile(filename);
998 ASSERT_EQ(info.faultLogType, FaultLogType::APP_FREEZE); // 4 : APP_FREEZE
999 ASSERT_EQ(info.pid, 10006); // 10006 : test uid
1000
1001 std::string filename3 = "jscrash-10006-20170805172159";
1002 auto info3 = ExtractInfoFromTempFile(filename3);
1003 ASSERT_EQ(info3.faultLogType, FaultLogType::JS_CRASH); // 3 : JS_CRASH
1004 ASSERT_EQ(info3.pid, 10006); // 10006 : test uid
1005
1006 std::string filename4 = "cppcrash-10006-20170805172159";
1007 auto info4 = ExtractInfoFromTempFile(filename4);
1008 ASSERT_EQ(info4.faultLogType, FaultLogType::CPP_CRASH); // 2 : CPP_CRASH
1009 ASSERT_EQ(info4.pid, 10006); // 10006 : test uid
1010
1011 std::string filename5 = "all-10006-20170805172159";
1012 auto info5 = ExtractInfoFromTempFile(filename5);
1013 ASSERT_EQ(info5.faultLogType, FaultLogType::ALL); // 0 : ALL
1014 ASSERT_EQ(info5.pid, 10006); // 10006 : test uid
1015
1016 std::string filename6 = "other-10006-20170805172159";
1017 auto info6 = ExtractInfoFromTempFile(filename6);
1018 ASSERT_EQ(info6.faultLogType, -1); // -1 : other
1019 ASSERT_EQ(info6.pid, 10006); // 10006 : test uid
1020 }
1021
1022 /**
1023 * @tc.name: FaultloggerAdapter.StartService
1024 * @tc.desc: Test calling FaultloggerAdapter.StartService Func
1025 * @tc.type: FUNC
1026 */
1027 HWTEST_F(FaultloggerUnittest, FaultloggerAdapterTest001, testing::ext::TestSize.Level3)
1028 {
1029 FaultloggerAdapter::StartService(nullptr);
1030 ASSERT_EQ(FaultloggerServiceOhos::GetOrSetFaultlogger(nullptr), nullptr);
1031
1032 Faultlogger faultlogger;
1033 FaultloggerAdapter::StartService(&faultlogger);
1034 ASSERT_EQ(FaultloggerServiceOhos::GetOrSetFaultlogger(nullptr), &faultlogger);
1035 }
1036
1037 /**
1038 * @tc.name: FaultloggerServiceOhos.StartService
1039 * @tc.desc: Test calling FaultloggerServiceOhos.StartService Func
1040 * @tc.type: FUNC
1041 */
1042 HWTEST_F(FaultloggerUnittest, FaultloggerServiceOhosTest001, testing::ext::TestSize.Level3)
1043 {
1044 auto service = GetFaultloggerInstance();
1045 FaultloggerServiceOhos serviceOhos;
1046 FaultloggerServiceOhos::StartService(service.get());
1047 ASSERT_EQ(FaultloggerServiceOhos::GetOrSetFaultlogger(nullptr), service.get());
1048 FaultLogInfoOhos info;
1049 info.time = std::time(nullptr);
1050 info.pid = getpid();
1051 info.uid = 0;
1052 info.faultLogType = 2;
1053 info.module = "FaultloggerUnittest333";
1054 info.reason = "unittest for SaveFaultLogInfo";
1055 serviceOhos.AddFaultLog(info);
1056 auto list = serviceOhos.QuerySelfFaultLog(2, 10);
1057 ASSERT_NE(list, nullptr);
1058 info.time = std::time(nullptr);
1059 info.pid = getpid();
1060 info.uid = 10;
1061 info.faultLogType = 2;
1062 info.module = "FaultloggerUnittest333";
1063 info.reason = "unittest for SaveFaultLogInfo";
1064 serviceOhos.AddFaultLog(info);
1065 list = serviceOhos.QuerySelfFaultLog(2, 10);
1066 ASSERT_EQ(list, nullptr);
1067 info.time = std::time(nullptr);
1068 info.pid = getpid();
1069 info.uid = 0;
1070 info.faultLogType = 2;
1071 info.module = "FaultloggerUnittest333";
1072 info.reason = "unittest for SaveFaultLogInfo";
1073 serviceOhos.AddFaultLog(info);
1074 list = serviceOhos.QuerySelfFaultLog(8, 10);
1075 ASSERT_EQ(list, nullptr);
1076
1077 serviceOhos.Destroy();
1078 }
1079
1080 /**
1081 * @tc.name: FaultloggerServiceOhos.Dump
1082 * @tc.desc: Test calling FaultloggerServiceOhos.Dump Func
1083 * @tc.type: FUNC
1084 */
1085 HWTEST_F(FaultloggerUnittest, FaultloggerServiceOhosTest002, testing::ext::TestSize.Level3)
1086 {
1087 auto service = GetFaultloggerInstance();
1088 FaultloggerServiceOhos serviceOhos;
1089 FaultloggerServiceOhos::StartService(service.get());
1090 ASSERT_EQ(FaultloggerServiceOhos::GetOrSetFaultlogger(nullptr), service.get());
1091 auto fd = TEMP_FAILURE_RETRY(open("/data/test/testFile2", O_CREAT | O_WRONLY | O_TRUNC, 770));
1092 bool isSuccess = fd >= 0;
1093 if (!isSuccess) {
1094 ASSERT_FALSE(isSuccess);
1095 printf("Fail to create test result file.\n");
1096 return;
1097 }
1098 std::vector<std::u16string>args;
1099 args.push_back(u"Faultlogger");
1100 args.push_back(u"-l");
1101 serviceOhos.Dump(fd, args);
1102 args.push_back(u"&@#");
1103 ASSERT_EQ(serviceOhos.Dump(fd, args), -1);
1104 close(fd);
1105 fd = -1;
1106 std::string result;
1107 if (FileUtil::LoadStringFromFile("/data/test/testFile2", result)) {
1108 ASSERT_GT(result.length(), 0uL);
1109 } else {
1110 FAIL();
1111 }
1112 serviceOhos.Destroy();
1113 }
1114
1115 /**
1116 * @tc.name: FaultLogQueryResultOhosTest001
1117 * @tc.desc: test HasNext and GetNext
1118 * @tc.type: FUNC
1119 */
1120 HWTEST_F(FaultloggerUnittest, FaultLogQueryResultOhosTest001, testing::ext::TestSize.Level3)
1121 {
1122 auto service = GetFaultloggerInstance();
1123 FaultloggerServiceOhos serviceOhos;
1124 FaultloggerServiceOhos::StartService(service.get());
1125 bool isSuccess = FaultloggerServiceOhos::GetOrSetFaultlogger(nullptr) == service.get();
1126 if (!isSuccess) {
1127 ASSERT_FALSE(isSuccess);
1128 printf("FaultloggerServiceOhos start service error.\n");
1129 return;
1130 }
1131 auto remoteObject = serviceOhos.QuerySelfFaultLog(FaultLogType::CPP_CRASH, 10); // 10 : maxNum
1132 auto result = iface_cast<FaultLogQueryResultOhos>(remoteObject);
1133 ASSERT_NE(result, nullptr);
1134 if (result != nullptr) {
1135 while (result->HasNext()) {
1136 result->GetNext();
1137 }
1138 }
1139 auto getNextRes = result->GetNext();
1140 ASSERT_NE(result, nullptr);
1141
1142 result->result_ = nullptr;
1143 bool hasNext = result->HasNext();
1144 ASSERT_FALSE(hasNext);
1145 getNextRes = result->GetNext();
1146 ASSERT_NE(result, nullptr);
1147 }
1148
1149 class TestFaultLogQueryResultStub : public FaultLogQueryResultStub {
1150 public:
TestFaultLogQueryResultStub()1151 TestFaultLogQueryResultStub() {}
~TestFaultLogQueryResultStub()1152 virtual ~TestFaultLogQueryResultStub() {}
1153
HasNext()1154 bool HasNext()
1155 {
1156 return false;
1157 }
1158
GetNext()1159 sptr<FaultLogInfoOhos> GetNext()
1160 {
1161 return nullptr;
1162 }
1163
1164 public:
1165 enum Code {
1166 DEFAULT = -1,
1167 HASNEXT = 0,
1168 GETNEXT,
1169 };
1170 };
1171
1172 /**
1173 * @tc.name: FaultLogQueryResultStubTest001
1174 * @tc.desc: test OnRemoteRequest
1175 * @tc.type: FUNC
1176 */
1177 HWTEST_F(FaultloggerUnittest, FaultLogQueryResultStubTest001, testing::ext::TestSize.Level3)
1178 {
1179 TestFaultLogQueryResultStub faultLogQueryResultStub;
1180 MessageParcel data;
1181 MessageParcel reply;
1182 MessageOption option;
1183 int ret = faultLogQueryResultStub.OnRemoteRequest(TestFaultLogQueryResultStub::Code::HASNEXT, data, reply, option);
1184 ASSERT_EQ(ret, -1);
1185 data.WriteInterfaceToken(FaultLogQueryResultStub::GetDescriptor());
1186 ret = faultLogQueryResultStub.OnRemoteRequest(TestFaultLogQueryResultStub::Code::HASNEXT, data, reply, option);
1187 ASSERT_EQ(ret, 0);
1188 data.WriteInterfaceToken(FaultLogQueryResultStub::GetDescriptor());
1189 ret = faultLogQueryResultStub.OnRemoteRequest(TestFaultLogQueryResultStub::Code::GETNEXT, data, reply, option);
1190 ASSERT_EQ(ret, -1);
1191 data.WriteInterfaceToken(FaultLogQueryResultStub::GetDescriptor());
1192 ret = faultLogQueryResultStub.OnRemoteRequest(TestFaultLogQueryResultStub::Code::DEFAULT, data, reply, option);
1193 ASSERT_EQ(ret, 305); // 305 : method not exist
1194 }
1195
1196 class TestFaultLoggerServiceStub : public FaultLoggerServiceStub {
1197 public:
TestFaultLoggerServiceStub()1198 TestFaultLoggerServiceStub() {}
~TestFaultLoggerServiceStub()1199 virtual ~TestFaultLoggerServiceStub() {}
1200
AddFaultLog(const FaultLogInfoOhos & info)1201 void AddFaultLog(const FaultLogInfoOhos& info)
1202 {
1203 }
1204
QuerySelfFaultLog(int32_t faultType,int32_t maxNum)1205 sptr<IRemoteObject> QuerySelfFaultLog(int32_t faultType, int32_t maxNum)
1206 {
1207 return nullptr;
1208 }
1209
Destroy()1210 void Destroy()
1211 {
1212 }
1213
1214 public:
1215 enum Code {
1216 DEFAULT = -1,
1217 ADD_FAULTLOG = 0,
1218 QUERY_SELF_FAULTLOG,
1219 DESTROY,
1220 };
1221 };
1222
1223 /**
1224 * @tc.name: FaultLoggerServiceStubTest001
1225 * @tc.desc: test OnRemoteRequest
1226 * @tc.type: FUNC
1227 */
1228 HWTEST_F(FaultloggerUnittest, FaultLoggerServiceStubTest001, testing::ext::TestSize.Level3)
1229 {
1230 TestFaultLoggerServiceStub faultLoggerServiceStub;
1231 MessageParcel data;
1232 MessageParcel reply;
1233 MessageOption option;
1234 int ret = faultLoggerServiceStub.OnRemoteRequest(TestFaultLoggerServiceStub::Code::ADD_FAULTLOG,
1235 data, reply, option);
1236 ASSERT_EQ(ret, -1);
1237 data.WriteInterfaceToken(FaultLoggerServiceStub::GetDescriptor());
1238 ret = faultLoggerServiceStub.OnRemoteRequest(TestFaultLoggerServiceStub::Code::ADD_FAULTLOG,
1239 data, reply, option);
1240 ASSERT_EQ(ret, 3); // 3 : ERR_FLATTEN_OBJECT
1241 data.WriteInterfaceToken(FaultLoggerServiceStub::GetDescriptor());
1242 ret = faultLoggerServiceStub.OnRemoteRequest(TestFaultLoggerServiceStub::Code::QUERY_SELF_FAULTLOG,
1243 data, reply, option);
1244 ASSERT_EQ(ret, -1);
1245 data.WriteInterfaceToken(FaultLoggerServiceStub::GetDescriptor());
1246 ret = faultLoggerServiceStub.OnRemoteRequest(TestFaultLoggerServiceStub::Code::DESTROY,
1247 data, reply, option);
1248 ASSERT_EQ(ret, 0);
1249 data.WriteInterfaceToken(FaultLoggerServiceStub::GetDescriptor());
1250 ret = faultLoggerServiceStub.OnRemoteRequest(TestFaultLoggerServiceStub::Code::DEFAULT,
1251 data, reply, option);
1252 ASSERT_EQ(ret, 305); // 305 : method not exist
1253 }
1254
1255 /**
1256 * @tc.name: FaultloggerTest001
1257 * @tc.desc: Test calling Faultlogger.StartBootScan Func
1258 * @tc.type: FUNC
1259 */
1260 HWTEST_F(FaultloggerUnittest, FaultloggerTest001, testing::ext::TestSize.Level3)
1261 {
1262 StartHisyseventListen("RELIABILITY", "CPP_CRASH");
1263 time_t now = time(nullptr);
1264 std::vector<std::string> keyWords = { std::to_string(now) };
1265 faultEventListener->SetKeyWords(keyWords);
1266 std::string timeStr = GetFormatedTimeWithMillsec(now);
1267 std::string content = "Pid:101\nUid:0\nProcess name:BootScanUnittest\nReason:unittest for StartBootScan\n"
1268 "Fault thread info:\nTid:101, Name:BootScanUnittest\n#00 xxxxxxx\n#01 xxxxxxx\n";
1269 ASSERT_TRUE(FileUtil::SaveStringToFile("/data/log/faultlog/temp/cppcrash-101-" + std::to_string(now), content));
1270 auto plugin = GetFaultloggerInstance();
1271 plugin->StartBootScan();
1272 //check faultlog file content
1273 std::string fileName = "/data/log/faultlog/faultlogger/cppcrash-BootScanUnittest-0-" + timeStr + ".log";
1274 ASSERT_TRUE(FileUtil::FileExists(fileName));
1275 ASSERT_GT(FileUtil::GetFileSize(fileName), 0ul);
1276
1277 // check event database
1278 ASSERT_TRUE(faultEventListener->CheckKeyWords());
1279 }
1280
1281 /**
1282 * @tc.name: FaultloggerTest002
1283 * @tc.desc: Test calling Faultlogger.StartBootScan Func
1284 * @tc.type: FUNC
1285 */
1286 HWTEST_F(FaultloggerUnittest, FaultloggerTest002, testing::ext::TestSize.Level3)
1287 {
1288 StartHisyseventListen("RELIABILITY", "CPP_CRASH_NO_LOG");
1289 std::vector<std::string> keyWords = { "BootScanUnittest" };
1290 faultEventListener->SetKeyWords(keyWords);
1291 time_t now = time(nullptr);
1292 std::string content = "Pid:102\nUid:0\nProcess name:BootScanUnittest\nReason:unittest for StartBootScan\n"
1293 "Fault thread info:\nTid:102, Name:BootScanUnittest\n";
1294 std::string fileName = "/data/log/faultlog/temp/cppcrash-102-" + std::to_string(now);
1295 ASSERT_TRUE(FileUtil::SaveStringToFile(fileName, content));
1296 auto plugin = GetFaultloggerInstance();
1297 plugin->StartBootScan();
1298 ASSERT_FALSE(FileUtil::FileExists(fileName));
1299
1300 // check event database
1301 ASSERT_TRUE(faultEventListener->CheckKeyWords());
1302 }
1303
1304 /**
1305 * @tc.name: FaultloggerTest003
1306 * @tc.desc: Test calling Faultlogger.StartBootScan Func, for full log
1307 * @tc.type: FUNC
1308 */
1309 HWTEST_F(FaultloggerUnittest, FaultloggerTest003, testing::ext::TestSize.Level3)
1310 {
1311 StartHisyseventListen("RELIABILITY", "CPP_CRASH");
1312 time_t now = time(nullptr);
1313 std::vector<std::string> keyWords = { std::to_string(now) };
1314 faultEventListener->SetKeyWords(keyWords);
1315 std::string timeStr = GetFormatedTimeWithMillsec(now);
1316 std::string regs = "r0:00000019 r1:0097cd3c\nr4:f787fd2c\nfp:f787fd18 ip:7fffffff pc:0097c982\n";
1317 std::string otherThreadInfo =
1318 "Tid:1336, Name:BootScanUnittes\n#00 xxxxxx\nTid:1337, Name:BootScanUnittes\n#00 xx\n";
1319 std::string content = std::string("Pid:111\nUid:0\nProcess name:BootScanUnittest\n") +
1320 "Reason:unittest for StartBootScan\n" +
1321 "Fault thread info:\nTid:111, Name:BootScanUnittest\n#00 xxxxxxx\n#01 xxxxxxx\n" +
1322 "Registers:\n" + regs +
1323 "Other thread info:\n" + otherThreadInfo +
1324 "Memory near registers:\nr1(/data/xxxxx):\n 0097cd34 47886849\n 0097cd38 96059d05\n\n" +
1325 "Maps:\n96e000-978000 r--p 00000000 /data/xxxxx\n978000-9a6000 r-xp 00009000 /data/xxxx\n";
1326 ASSERT_TRUE(FileUtil::SaveStringToFile("/data/log/faultlog/temp/cppcrash-111-" + std::to_string(now), content));
1327 auto plugin = GetFaultloggerInstance();
1328 plugin->StartBootScan();
1329
1330 //check faultlog file content
1331 std::string fileName = "/data/log/faultlog/faultlogger/cppcrash-BootScanUnittest-0-" + timeStr + ".log";
1332 ASSERT_TRUE(FileUtil::FileExists(fileName));
1333 ASSERT_GT(FileUtil::GetFileSize(fileName), 0ul);
1334
1335 // check regs and otherThreadInfo is ok
1336 std::string logInfo;
1337 FileUtil::LoadStringFromFile(fileName, logInfo);
1338 ASSERT_TRUE(logInfo.find(regs) != std::string::npos);
1339 ASSERT_TRUE(logInfo.find(otherThreadInfo) != std::string::npos);
1340
1341 // check event database
1342 ASSERT_TRUE(faultEventListener->CheckKeyWords());
1343 }
1344
1345 /**
1346 * @tc.name: FaultloggerTest004
1347 * @tc.desc: Test calling Faultlogger.StartBootScan Func, for full cpp crash log limit
1348 * @tc.type: FUNC
1349 */
1350 HWTEST_F(FaultloggerUnittest, FaultloggerTest004, testing::ext::TestSize.Level3)
1351 {
1352 StartHisyseventListen("RELIABILITY", "CPP_CRASH");
1353 time_t now = time(nullptr);
1354 std::vector<std::string> keyWords = { std::to_string(now) };
1355 faultEventListener->SetKeyWords(keyWords);
1356 std::string timeStr = GetFormatedTimeWithMillsec(now);
1357 std::string fillMapsContent = "96e000-978000 r--p 00000000 /data/xxxxx\n978000-9a6000 r-xp 00009000 /data/xxxx\n";
1358 std::string regs = "r0:00000019 r1:0097cd3c\nr4:f787fd2c\nfp:f787fd18 ip:7fffffff pc:0097c982\n";
1359 std::string otherThreadInfo =
1360 "Tid:1336, Name:BootScanUnittes\n#00 xxxxxx\nTid:1337, Name:BootScanUnittes\n#00 xx\n";
1361 std::string content = std::string("Pid:111\nUid:0\nProcess name:BootScanUnittest\n") +
1362 "Reason:unittest for StartBootScan\n" +
1363 "Fault thread info:\nTid:111, Name:BootScanUnittest\n#00 xxxxxxx\n#01 xxxxxxx\n" +
1364 "Registers:\n" + regs +
1365 "Other thread info:\n" + otherThreadInfo +
1366 "Memory near registers:\nr1(/data/xxxxx):\n 0097cd34 47886849\n 0097cd38 96059d05\n\n" +
1367 "Maps:\n96e000-978000 r--p 00000000 /data/xxxxx\n978000-9a6000 r-xp 00009000 /data/xxxx\n";
1368 // let content more than 512k, trigger loglimit
1369 for (int i = 0; i < 10000; i++) {
1370 content += fillMapsContent;
1371 }
1372
1373 ASSERT_TRUE(FileUtil::SaveStringToFile("/data/log/faultlog/temp/cppcrash-114-" + std::to_string(now), content));
1374 auto plugin = GetFaultloggerInstance();
1375 plugin->StartBootScan();
1376 // check faultlog file content
1377 std::string fileName = "/data/log/faultlog/faultlogger/cppcrash-BootScanUnittest-0-" + timeStr + ".log";
1378 GTEST_LOG_(INFO) << "========fileName:" << fileName;
1379 ASSERT_TRUE(FileUtil::FileExists(fileName));
1380 ASSERT_GT(FileUtil::GetFileSize(fileName), 0ul);
1381 if (FaultLogger::IsFaultLogLimit()) {
1382 ASSERT_LT(FileUtil::GetFileSize(fileName), 514 * 1024ul);
1383 } else {
1384 ASSERT_GT(FileUtil::GetFileSize(fileName), 512 * 1024ul);
1385 }
1386 // check event database
1387 ASSERT_TRUE(faultEventListener->CheckKeyWords());
1388 }
1389
1390 /**
1391 * @tc.name: ReportJsErrorToAppEventTest001
1392 * @tc.desc: create JS ERROR event and send it to hiappevent
1393 * @tc.type: FUNC
1394 */
1395 HWTEST_F(FaultloggerUnittest, ReportJsErrorToAppEventTest001, testing::ext::TestSize.Level3)
1396 {
1397 auto plugin = GetFaultloggerInstance();
1398 // has Error name、Error message、Error code、SourceCode、Stacktrace
1399 std::string summaryHasAll = R"~(Error name:summaryHasAll TypeError
1400 Error message:Obj is not a Valid object
1401 Error code:get BLO
1402 SourceCode:CKSSvalue() {new Error("TestError");}
1403 Stacktrace:
1404 at anonymous(entry/src/main/ets/pages/index.ets:76:10)
1405 at anonymous2(entry/src/main/ets/pages/index.ets:76:10)
1406 at anonymous3(entry/src/main/ets/pages/index.ets:76:10)
1407 )~";
1408 GTEST_LOG_(INFO) << "========summaryHasAll========";
1409 ConstructJsErrorAppEvent(summaryHasAll, plugin);
1410 CheckKeyWordsInJsErrorAppEventFile("summaryHasAll");
1411 }
1412
1413 /**
1414 * @tc.name: ReportJsErrorToAppEventTest002
1415 * @tc.desc: create JS ERROR event and send it to hiappevent
1416 * @tc.type: FUNC
1417 */
1418 HWTEST_F(FaultloggerUnittest, ReportJsErrorToAppEventTest002, testing::ext::TestSize.Level3)
1419 {
1420 auto plugin = GetFaultloggerInstance();
1421 // has Error name、Error message、Error code、SourceCode、Stacktrace
1422 std::string summaryNotFindSourcemap = R"~(Error name:summaryNotFindSourcemap Error
1423 Error message:BussinessError 2501000: Operation failed.
1424 Error code:2501000
1425 Stacktrace:
1426 Cannot get SourceMap info, dump raw stack:
1427 at anonymous(entry/src/main/ets/pages/index.ets:76:10)
1428 at anonymous2(entry/src/main/ets/pages/index.ets:76:10)
1429 at anonymous3(entry/src/main/ets/pages/index.ets:76:10)
1430 )~";
1431 GTEST_LOG_(INFO) << "========summaryNotFindSourcemap========";
1432 ConstructJsErrorAppEvent(summaryNotFindSourcemap, plugin);
1433 CheckDeleteStackErrorMessage("summaryNotFindSourcemap");
1434 CheckKeyWordsInJsErrorAppEventFile("summaryNotFindSourcemap");
1435 }
1436
1437 /**
1438 * @tc.name: ReportJsErrorToAppEventTest003
1439 * @tc.desc: create JS ERROR event and send it to hiappevent
1440 * @tc.type: FUNC
1441 */
1442 HWTEST_F(FaultloggerUnittest, ReportJsErrorToAppEventTest003, testing::ext::TestSize.Level3)
1443 {
1444 auto plugin = GetFaultloggerInstance();
1445 // has Error name、Error message、SourceCode、Stacktrace
1446 std::string summaryHasNoErrorCode = R"~(Error name:summaryHasNoErrorCode TypeError
1447 Error message:Obj is not a Valid object
1448 SourceCode:CKSSvalue() {new Error("TestError");}
1449 Stacktrace:
1450 at anonymous(entry/src/main/ets/pages/index.ets:76:10)
1451 at anonymous2(entry/src/main/ets/pages/index.ets:76:10)
1452 at anonymous3(entry/src/main/ets/pages/index.ets:76:10)
1453 )~";
1454 GTEST_LOG_(INFO) << "========summaryHasNoErrorCode========";
1455 ConstructJsErrorAppEvent(summaryHasNoErrorCode, plugin);
1456 CheckKeyWordsInJsErrorAppEventFile("summaryHasNoErrorCode");
1457 }
1458
1459 /**
1460 * @tc.name: ReportJsErrorToAppEventTest004
1461 * @tc.desc: create JS ERROR event and send it to hiappevent
1462 * @tc.type: FUNC
1463 */
1464 HWTEST_F(FaultloggerUnittest, ReportJsErrorToAppEventTest004, testing::ext::TestSize.Level3)
1465 {
1466 auto plugin = GetFaultloggerInstance();
1467 // has Error name、Error message、Error code、Stacktrace
1468 std::string summaryHasNoSourceCode = R"~(Error name:summaryHasNoSourceCode TypeError
1469 Error message:Obj is not a Valid object
1470 Error code:get BLO
1471 Stacktrace:
1472 at anonymous(entry/src/main/ets/pages/index.ets:76:10)
1473 at anonymous2(entry/src/main/ets/pages/index.ets:76:10)
1474 at anonymous3(entry/src/main/ets/pages/index.ets:76:10)
1475 )~";
1476 GTEST_LOG_(INFO) << "========summaryHasNoSourceCode========";
1477 ConstructJsErrorAppEvent(summaryHasNoSourceCode, plugin);
1478 CheckKeyWordsInJsErrorAppEventFile("summaryHasNoSourceCode");
1479 }
1480
1481 /**
1482 * @tc.name: ReportJsErrorToAppEventTest005
1483 * @tc.desc: create JS ERROR event and send it to hiappevent
1484 * @tc.type: FUNC
1485 */
1486 HWTEST_F(FaultloggerUnittest, ReportJsErrorToAppEventTest005, testing::ext::TestSize.Level3)
1487 {
1488 auto plugin = GetFaultloggerInstance();
1489 // has Error name、Error message、Stacktrace
1490 std::string summaryHasNoErrorCodeAndSourceCode = R"~(Error name:summaryHasNoErrorCodeAndSourceCode TypeError
1491 Error message:Obj is not a Valid object
1492 Stacktrace:
1493 at anonymous(entry/src/main/ets/pages/index.ets:76:10)
1494 at anonymous2(entry/src/main/ets/pages/index.ets:76:10)
1495 at anonymous3(entry/src/main/ets/pages/index.ets:76:10)
1496 )~";
1497 GTEST_LOG_(INFO) << "========summaryHasNoErrorCodeAndSourceCode========";
1498 ConstructJsErrorAppEvent(summaryHasNoErrorCodeAndSourceCode, plugin);
1499 CheckKeyWordsInJsErrorAppEventFile("summaryHasNoErrorCodeAndSourceCode");
1500 }
1501
1502 /**
1503 * @tc.name: ReportJsErrorToAppEventTest006
1504 * @tc.desc: create JS ERROR event and send it to hiappevent
1505 * @tc.type: FUNC
1506 */
1507 HWTEST_F(FaultloggerUnittest, ReportJsErrorToAppEventTest006, testing::ext::TestSize.Level3)
1508 {
1509 auto plugin = GetFaultloggerInstance();
1510 // has Error name、Error message、Error code、SourceCode
1511 std::string summaryHasNoStacktrace = R"~(Error name:summaryHasNoStacktrace TypeError
1512 Error message:Obj is not a Valid object
1513 Error code:get BLO
1514 SourceCode:CKSSvalue() {new Error("TestError");}
1515 Stacktrace:
1516 )~";
1517 GTEST_LOG_(INFO) << "========summaryHasNoStacktrace========";
1518 ConstructJsErrorAppEvent(summaryHasNoStacktrace, plugin);
1519 CheckKeyWordsInJsErrorAppEventFile("summaryHasNoStacktrace");
1520 }
1521
1522 /**
1523 * @tc.name: ReportJsErrorToAppEventTest007
1524 * @tc.desc: create JS ERROR event and send it to hiappevent
1525 * @tc.type: FUNC
1526 */
1527 HWTEST_F(FaultloggerUnittest, ReportJsErrorToAppEventTest007, testing::ext::TestSize.Level3)
1528 {
1529 auto plugin = GetFaultloggerInstance();
1530 // has Error name、Error message
1531 std::string summaryHasErrorNameAndErrorMessage = R"~(Error name:summaryHasErrorNameAndErrorMessage TypeError
1532 Error message:Obj is not a Valid object
1533 Stacktrace:
1534 )~";
1535 GTEST_LOG_(INFO) << "========summaryHasErrorNameAndErrorMessage========";
1536 ConstructJsErrorAppEvent(summaryHasErrorNameAndErrorMessage, plugin);
1537 CheckKeyWordsInJsErrorAppEventFile("summaryHasErrorNameAndErrorMessage");
1538 }
1539
1540 /**
1541 * @tc.name: ReportJsErrorToAppEventTest008
1542 * @tc.desc: create JS ERROR event and send it to hiappevent
1543 * @tc.type: FUNC
1544 */
1545 HWTEST_F(FaultloggerUnittest, ReportJsErrorToAppEventTest008, testing::ext::TestSize.Level3)
1546 {
1547 auto plugin = GetFaultloggerInstance();
1548 // has Error name、Error message
1549 std::string noKeyValue = R"~(Error name:summaryHasErrorNameAndErrorMessage TypeError
1550 Error message:Obj is not a Valid object
1551 Stacktrace:
1552 )~";
1553 GTEST_LOG_(INFO) << "========noKeyValue========";
1554 ConstructJsErrorAppEventWithNoValue(noKeyValue, plugin);
1555 CheckKeyWordsInJsErrorAppEventFile("noKeyValue");
1556 }
1557
1558 /**
1559 * @tc.name: ReportJsErrorToAppEventTest009
1560 * @tc.desc: create JS ERROR event and send it to hiappevent
1561 * @tc.type: FUNC
1562 */
1563 HWTEST_F(FaultloggerUnittest, ReportJsErrorToAppEventTest009, testing::ext::TestSize.Level3)
1564 {
1565 auto plugin = GetFaultloggerInstance();
1566 GTEST_LOG_(INFO) << "========noKeyValue========";
1567 ConstructJsErrorAppEventWithNoValue("", plugin);
1568 std::string oldFileName = "/data/test_jsError_info";
1569 ASSERT_TRUE(FileUtil::FileExists(oldFileName));
1570 auto ret = remove("/data/test_jsError_info");
1571 if (ret == 0) {
1572 GTEST_LOG_(INFO) << "remove /data/test_jsError_info failed";
1573 }
1574 }
1575
1576 /**
1577 * @tc.name: ReportCjErrorToAppEventTest001
1578 * @tc.desc: create CJ ERROR event and send it to hiappevent
1579 * @tc.type: FUNC
1580 */
1581 HWTEST_F(FaultloggerUnittest, ReportCjErrorToAppEventTest001, testing::ext::TestSize.Level3)
1582 {
1583 auto plugin = GetFaultloggerInstance();
1584 // has Error name、Error message、Error code、SourceCode、Stacktrace
1585 std::string summary = R"~(Uncaught exception was found.
1586 Exception info: throwing foo exception
1587 Stacktrace:
1588 at anonymous(entry/src/main/ets/pages/index.cj:20)
1589 at anonymous2(entry/src/main/ets/pages/index.cj:33)
1590 at anonymous3(entry/src/main/ets/pages/index.cj:77)
1591 )~";
1592 GTEST_LOG_(INFO) << "========CangjieError========";
1593 ConstructCjErrorAppEvent(summary, plugin);
1594 CheckKeyWordsInCjErrorAppEventFile("summary");
1595 }
1596
SendSysEvent(SysEventCreator sysEventCreator)1597 bool SendSysEvent(SysEventCreator sysEventCreator)
1598 {
1599 auto plugin = GetFaultloggerInstance();
1600 auto sysEvent = std::make_shared<SysEvent>("test", nullptr, sysEventCreator);
1601 std::shared_ptr<Event> event = std::dynamic_pointer_cast<Event>(sysEvent);
1602 return plugin->OnEvent(event);
1603 }
1604
1605 /**
1606 * @tc.name: OnEventTest001
1607 * @tc.desc: create JS ERROR event and send it to hiappevent
1608 * @tc.type: FUNC
1609 */
1610 HWTEST_F(FaultloggerUnittest, OnEventTest001, testing::ext::TestSize.Level3)
1611 {
1612 {
1613 SysEventCreator sysEventCreator("AAFWK", "JSERROR", SysEventCreator::FAULT);
1614 sysEventCreator.SetKeyValue("name_", "JS_ERRORS");
1615 auto result = SendSysEvent(sysEventCreator);
1616 ASSERT_EQ(result, true);
1617 }
1618 {
1619 SysEventCreator sysEventCreator("AAFWK", "CPPCRASH", SysEventCreator::FAULT);
1620 sysEventCreator.SetKeyValue("name_", "RUST_PANIC");
1621 auto result = SendSysEvent(sysEventCreator);
1622 ASSERT_EQ(result, true);
1623 }
1624 }
1625
1626 /**
1627 * @tc.name: AppFreezeCrashLogTest001
1628 * @tc.desc: test AddFaultLog, check F1/F2/F3
1629 * @tc.type: FUNC
1630 */
1631 HWTEST_F(FaultloggerUnittest, AppFreezeCrashLogTest001, testing::ext::TestSize.Level3)
1632 {
1633 auto plugin = GetFaultloggerInstance();
1634 FaultLogInfo info;
1635 info.time = 1607161163;
1636 info.id = 20010039;
1637 info.pid = 7497;
1638 info.faultLogType = FaultLogType::APP_FREEZE;
1639 info.module = "com.example.jsinject";
1640 info.logPath = APPFREEZE_FAULT_FILE + "AppFreezeCrashLogTest001/" +
1641 "appfreeze-com.example.jsinject-20010039-19700326211815.tmp";
1642 plugin->AddFaultLog(info);
1643
1644 const std::string firstFrame = "/system/lib64/libeventhandler.z.so"
1645 "(OHOS::AppExecFwk::NoneIoWaiter::WaitFor(std::__1::unique_lock<std::__1::mutex>&, long)+204";
1646 ASSERT_EQ(info.sectionMap["FIRST_FRAME"], firstFrame);
1647 const std::string secondFrame = "/system/lib64/libeventhandler.z.so"
1648 "(OHOS::AppExecFwk::EventQueue::WaitUntilLocked"
1649 "(std::__1::chrono::time_point<std::__1::chrono::steady_clock, "
1650 "std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > > const&, "
1651 "std::__1::unique_lock<std::__1::mutex>&)+96";
1652 ASSERT_EQ(info.sectionMap["SECOND_FRAME"], secondFrame);
1653 }
1654
1655 /**
1656 * @tc.name: AppFreezeCrashLogTest002
1657 * @tc.desc: test AddFaultLog, add TERMINAL_THREAD_STACK, check F1/F2/F3
1658 * @tc.type: FUNC
1659 */
1660 HWTEST_F(FaultloggerUnittest, AppFreezeCrashLogTest002, testing::ext::TestSize.Level3)
1661 {
1662 auto plugin = GetFaultloggerInstance();
1663 FaultLogInfo info;
1664 info.time = 1607161163;
1665 info.id = 20010039;
1666 info.pid = 7497;
1667 info.faultLogType = FaultLogType::APP_FREEZE;
1668 info.module = "com.example.jsinject";
1669 info.logPath = APPFREEZE_FAULT_FILE + "AppFreezeCrashLogTest002/" +
1670 "appfreeze-com.example.jsinject-20010039-19700326211815.tmp";
1671 std::string binderSatck = "#00 pc 000000000006ca3c /system/lib64/libc.so(syscall+28)\n"
1672 "#01 pc 0000000000070cc4 "
1673 "/system/lib64/libc.so(__futex_wait_ex(void volatile*, bool, int, bool, timespec const*)+144)\n"
1674 "#02 pc 00000000000cf228 /system/lib64/libc.so(pthread_cond_wait+64)\n"
1675 "#03 pc 000000000051b55c /system/lib64/libGLES_mali.so\n"
1676 "#04 pc 00000000000cfce0 /system/lib64/libc.so(__pthread_start(void*)+40)\n"
1677 "#05 pc 0000000000072028 /system/lib64/libc.so(__start_thread+68)";
1678 info.sectionMap["TERMINAL_THREAD_STACK"] = binderSatck;
1679 plugin->AddFaultLog(info);
1680 ASSERT_EQ(info.sectionMap["FIRST_FRAME"], "/system/lib64/libGLES_mali.so");
1681 ASSERT_TRUE(info.sectionMap["SECOND_FRAME"].empty());
1682 ASSERT_TRUE(info.sectionMap["LAST_FRAME"].empty());
1683 }
1684
1685 /**
1686 * @tc.name: AppFreezeCrashLogTest003
1687 * @tc.desc: test AddFaultLog, add TERMINAL_THREAD_STACK("\n"), check F1/F2/F3
1688 * @tc.type: FUNC
1689 */
1690 HWTEST_F(FaultloggerUnittest, AppFreezeCrashLogTest003, testing::ext::TestSize.Level3)
1691 {
1692 auto plugin = GetFaultloggerInstance();
1693 FaultLogInfo info;
1694 info.time = 1607161163;
1695 info.id = 20010039;
1696 info.pid = 7497;
1697 info.faultLogType = FaultLogType::APP_FREEZE;
1698 info.module = "com.example.jsinject";
1699 info.logPath = APPFREEZE_FAULT_FILE + "AppFreezeCrashLogTest003/" +
1700 "appfreeze-com.example.jsinject-20010039-19700326211815.tmp";
1701 std::string binderSatck = "#00 pc 000000000006ca3c /system/lib64/libc.so(syscall+28)\\n"
1702 "#01 pc 0000000000070cc4 "
1703 "/system/lib64/libc.so(__futex_wait_ex(void volatile*, bool, int, bool, timespec const*)+144)\\n"
1704 "#02 pc 00000000000cf228 /system/lib64/libc.so(pthread_cond_wait+64)\\n"
1705 "#03 pc 000000000051b55c /system/lib64/libGLES_mali.so\\n"
1706 "#04 pc 00000000000cfce0 /system/lib64/libc.so(__pthread_start(void*)+40)\\n"
1707 "#05 pc 0000000000072028 /system/lib64/libc.so(__start_thread+68)";
1708 info.sectionMap["TERMINAL_THREAD_STACK"] = binderSatck;
1709 plugin->AddFaultLog(info);
1710 ASSERT_EQ(info.sectionMap["FIRST_FRAME"], "/system/lib64/libGLES_mali.so");
1711 ASSERT_TRUE(info.sectionMap["SECOND_FRAME"].empty());
1712 ASSERT_TRUE(info.sectionMap["LAST_FRAME"].empty());
1713 }
1714
1715 /**
1716 * @tc.name: FaultloggerUnittest001
1717 * @tc.desc: test QuerySelfFaultLog and GetMemoryStrByPid
1718 * @tc.type: FUNC
1719 */
1720 HWTEST_F(FaultloggerUnittest, FaultloggerUnittest001, testing::ext::TestSize.Level3)
1721 {
1722 auto plugin = GetFaultloggerInstance();
1723 plugin->hasInit_ = false;
1724 std::unique_ptr<FaultLogQueryResultInner> obj = plugin->QuerySelfFaultLog(1, 1, 1, 1);
1725 ASSERT_EQ(obj, nullptr);
1726
1727 std::string str = plugin->GetMemoryStrByPid(-1);
1728 ASSERT_EQ(str, "");
1729 str = plugin->GetMemoryStrByPid(1);
1730 ASSERT_NE(str, "");
1731 }
1732
1733 /**
1734 * @tc.name: FaultlogDatabaseUnittest001
1735 * @tc.desc: test RunSanitizerd
1736 * @tc.type: FUNC
1737 */
1738 HWTEST_F(FaultloggerUnittest, FaultlogDatabaseUnittest001, testing::ext::TestSize.Level3)
1739 {
1740 FaultLogDatabase *faultLogDb = new FaultLogDatabase(GetHiviewContext().GetSharedWorkLoop());
1741 std::list<FaultLogInfo> queryResult = faultLogDb->GetFaultInfoList("com.example.myapplication", 0, -1, 10);
1742 ASSERT_EQ(queryResult.size(), 0);
1743 queryResult = faultLogDb->GetFaultInfoList("com.example.myapplication", 0, 8, 10);
1744 ASSERT_EQ(queryResult.size(), 0);
1745 queryResult = faultLogDb->GetFaultInfoList("com.example.myapplication", 1, 2, 10);
1746 ASSERT_EQ(queryResult.size(), 0);
1747 queryResult = faultLogDb->GetFaultInfoList("com.example.myapplication", 1, 0, 10);
1748 ASSERT_EQ(queryResult.size(), 0);
1749
1750 FaultLogInfo info;
1751 info.faultLogType = FaultLogType::SYS_FREEZE;
1752 faultLogDb->eventLoop_ = nullptr;
1753 faultLogDb->SaveFaultLogInfo(info);
1754
1755 bool res = faultLogDb->IsFaultExist(1, 1, -1);
1756 ASSERT_FALSE(res);
1757 res = faultLogDb->IsFaultExist(1, 1, 8);
1758 ASSERT_FALSE(res);
1759 }
1760
1761 /**
1762 * @tc.name: FaultlogUtilUnittest001
1763 * @tc.desc: test RunSanitizerd
1764 * @tc.type: FUNC
1765 */
1766 HWTEST_F(FaultloggerUnittest, FaultlogUtilUnittest001, testing::ext::TestSize.Level3)
1767 {
1768 std::string result = GetFaultNameByType(FaultLogType::ADDR_SANITIZER, false);
1769 ASSERT_EQ(result, "ADDR_SANITIZER");
1770
1771 FaultLogInfo info;
1772 info.module = "test/test";
1773 info.faultLogType = FaultLogType::ADDR_SANITIZER;
1774 info.sanitizerType = "TSAN";
1775 std::string str = GetFaultLogName(info);
1776 ASSERT_EQ(str, "tsan-test-0-19700101080000000.log");
1777 info.sanitizerType = "UBSAN";
1778 str = GetFaultLogName(info);
1779 ASSERT_EQ(str, "ubsan-test-0-19700101080000000.log");
1780 info.sanitizerType = "GWP-ASAN";
1781 str = GetFaultLogName(info);
1782 ASSERT_EQ(str, "gwpasan-test-0-19700101080000000.log");
1783 info.sanitizerType = "HWASAN";
1784 str = GetFaultLogName(info);
1785 ASSERT_EQ(str, "hwasan-test-0-19700101080000000.log");
1786 info.sanitizerType = "ASAN";
1787 str = GetFaultLogName(info);
1788 ASSERT_EQ(str, "asan-test-0-19700101080000000.log");
1789 info.sanitizerType = "GWP-ASANS";
1790 str = GetFaultLogName(info);
1791 ASSERT_EQ(str, "sanitizer-test-0-19700101080000000.log");
1792
1793 str = RegulateModuleNameIfNeed("");
1794 ASSERT_EQ(str, "");
1795 }
1796
1797 /**
1798 * @tc.name: FaultloggerServiceOhosUnittest001
1799 * @tc.desc: test RunSanitizerd
1800 * @tc.type: FUNC
1801 */
1802 HWTEST_F(FaultloggerUnittest, FaultloggerServiceOhosUnittest001, testing::ext::TestSize.Level3)
1803 {
1804 FaultloggerServiceOhos faultloggerServiceOhos;
1805 std::vector<std::u16string> args;
1806 args.push_back(u"*m");
1807 int32_t result = faultloggerServiceOhos.Dump(1, args);
1808 ASSERT_EQ(result, -1);
1809
1810 FaultLogInfoOhos info;
1811 faultloggerServiceOhos.AddFaultLog(info);
1812 sptr<IRemoteObject> res = faultloggerServiceOhos.QuerySelfFaultLog(1, 10);
1813 ASSERT_EQ(res, nullptr);
1814 faultloggerServiceOhos.Destroy();
1815 }
1816
1817 /**
1818 * @tc.name: ReadHilogUnittest001
1819 * @tc.desc: Faultlogger::ReadHilog
1820 * @tc.type: FUNC
1821 */
1822 HWTEST_F(FaultloggerUnittest, ReadHilogUnittest001, testing::ext::TestSize.Level3)
1823 {
1824 /**
1825 * @tc.steps: step1. write log to hilog.
1826 */
1827 HIVIEW_LOGI("write log to hilog");
1828
1829 /**
1830 * @tc.steps: step2. Create a pipe.
1831 */
1832 int fds[2] = {-1, -1}; // 2: one read pipe, one write pipe
1833 int ret = pipe(fds);
1834 ASSERT_EQ(ret, 0) << "Failed to create pipe for get log.";
1835
1836 /**
1837 * @tc.steps: step3. ReadHilog.
1838 */
1839 int32_t pid = getpid();
1840 int childPid = fork();
1841 ASSERT_GE(childPid, 0);
1842 if (childPid == 0) {
1843 syscall(SYS_close, fds[0]);
1844 int rc = Faultlogger::DoGetHilogProcess(pid, fds[1]);
1845 syscall(SYS_close, fds[1]);
1846 _exit(rc);
1847 } else {
1848 syscall(SYS_close, fds[1]);
1849 // read log from fds[0]
1850 HIVIEW_LOGI("read hilog start");
1851 std::string log;
1852 Faultlogger::ReadHilog(fds[0], log);
1853 syscall(SYS_close, fds[0]);
1854 ASSERT_TRUE(!log.empty());
1855 }
1856 waitpid(childPid, nullptr, 0);
1857 }
1858
1859 /**
1860 * @tc.name: ReadHilogUnittest002
1861 * @tc.desc: Faultlogger::ReadHilog
1862 * @tc.type: FUNC
1863 */
1864 HWTEST_F(FaultloggerUnittest, ReadHilogUnittest002, testing::ext::TestSize.Level3)
1865 {
1866 /**
1867 * @tc.steps: step1. write log to hilog.
1868 */
1869 HIVIEW_LOGI("write log to hilog");
1870
1871 /**
1872 * @tc.steps: step2. Create a pipe.
1873 */
1874 int fds[2] = {-1, -1}; // 2: one read pipe, one write pipe
1875 int ret = pipe(fds);
1876 ASSERT_EQ(ret, 0) << "Failed to create pipe for get log.";
1877
1878 /**
1879 * @tc.steps: step3. ReadHilog.
1880 */
1881 int32_t pid = getpid();
1882 int childPid = fork();
1883 ASSERT_GE(childPid, 0);
1884 if (childPid == 0) {
1885 syscall(SYS_close, fds[0]);
1886 sleep(7); // Delay for 7 seconds, causing the read end to timeout and exit
1887 int rc = Faultlogger::DoGetHilogProcess(pid, fds[1]);
1888 syscall(SYS_close, fds[1]);
1889 _exit(rc);
1890 } else {
1891 syscall(SYS_close, fds[1]);
1892 // read log from fds[0]
1893 HIVIEW_LOGI("read hilog start");
1894 std::string log;
1895 Faultlogger::ReadHilog(fds[0], log);
1896 syscall(SYS_close, fds[0]);
1897 ASSERT_TRUE(log.empty());
1898 }
1899 waitpid(childPid, nullptr, 0);
1900 }
1901
1902 /**
1903 * @tc.name: ReadHilogUnittest003
1904 * @tc.desc: Faultlogger::ReadHilog
1905 * @tc.type: FUNC
1906 */
1907 HWTEST_F(FaultloggerUnittest, ReadHilogUnittest003, testing::ext::TestSize.Level3)
1908 {
1909 /**
1910 * @tc.steps: step1. write log to hilog.
1911 */
1912 HIVIEW_LOGI("write log to hilog");
1913
1914 /**
1915 * @tc.steps: step2. Create a pipe.
1916 */
1917 int fds[2] = {-1, -1}; // 2: one read pipe, one write pipe
1918 int ret = pipe(fds);
1919 ASSERT_EQ(ret, 0) << "Failed to create pipe for get log.";
1920
1921 /**
1922 * @tc.steps: step3. ReadHilog.
1923 */
1924 int32_t pid = getpid();
1925 int childPid = fork();
1926 ASSERT_GE(childPid, 0);
1927 if (childPid == 0) {
1928 syscall(SYS_close, fds[0]);
1929 syscall(SYS_close, fds[1]);
1930 _exit(0);
1931 } else {
1932 syscall(SYS_close, fds[1]);
1933 // read log from fds[0]
1934 HIVIEW_LOGI("read hilog start");
1935 std::string log;
1936 Faultlogger::ReadHilog(fds[0], log);
1937 syscall(SYS_close, fds[0]);
1938 ASSERT_TRUE(log.empty());
1939 }
1940 waitpid(childPid, nullptr, 0);
1941 }
1942 } // namespace HiviewDFX
1943 } // namespace OHOS
1944