1 /*
2  * Copyright (c) 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 
16 #include <cstring>
17 #include <gtest/gtest.h>
18 #include <unistd.h>
19 #include <vector>
20 
21 #include "hisysevent_manager.h"
22 #include "rustpanic_listener.h"
23 
24 using namespace testing;
25 using namespace testing::ext;
26 
27 namespace OHOS {
28 namespace HiviewDFX {
29 namespace {
30 static std::shared_ptr<RustPanicListener> panicListener = nullptr;
31 }
32 class PanicHandlerTest : public testing::Test {
33 public:
34     static void SetUpTestCase();
35     static void TearDownTestCase();
36     void SetUp();
37     void TearDown();
38 };
39 
SetUpTestCase()40 void PanicHandlerTest::SetUpTestCase()
41 {}
42 
TearDownTestCase()43 void PanicHandlerTest::TearDownTestCase()
44 {}
45 
SetUp()46 void PanicHandlerTest::SetUp()
47 {
48     chmod("/data/rustpanic_maker", 0755); // 0755 : -rwxr-xr-x
49 }
50 
TearDown()51 void PanicHandlerTest::TearDown()
52 {
53     panicListener = nullptr;
54 }
55 
ForkAndTriggerRustPanic(bool ismain)56 static void ForkAndTriggerRustPanic(bool ismain)
57 {
58     pid_t pid = fork();
59     if (pid < 0) {
60         GTEST_LOG_(ERROR) << "ForkAndTriggerRustPanic: Failed to fork panic process.";
61         return;
62     } else if (pid == 0) {
63         if (ismain) {
64             execl("/data/rustpanic_maker", "rustpanic_maker", "main", nullptr);
65         } else {
66             execl("/data/rustpanic_maker", "rustpanic_maker", "child", nullptr);
67         }
68     }
69 }
70 
ListenAndCheckHiSysevent()71 static void ListenAndCheckHiSysevent()
72 {
73     panicListener = std::make_shared<RustPanicListener>();
74     ListenerRule tagRule("RELIABILITY", "RUST_PANIC", RuleType::WHOLE_WORD);
75     std::vector<ListenerRule> sysRules;
76     sysRules.push_back(tagRule);
77     HiSysEventManager::AddListener(panicListener, sysRules);
78 }
79 
80 /**
81  * @tc.name: PanicHandlerTest001
82  * @tc.desc: test panic in main thread
83  * @tc.type: FUNC
84  * @tc.require: issueI6HM7C
85  */
86 HWTEST_F(PanicHandlerTest, PanicHandlerTest001, TestSize.Level2)
87 {
88     GTEST_LOG_(INFO) << "PanicHandlerTest001: start.";
89     ListenAndCheckHiSysevent();
90     panicListener->SetKeyWord("panic in main thread");
91     ForkAndTriggerRustPanic(true);
92     if (panicListener != nullptr) {
93         GTEST_LOG_(INFO) << "PanicHandlerTest001: ready to check hisysevent reason keyword.";
94         ASSERT_TRUE(panicListener->CheckKeywordInReasons());
95     }
96     GTEST_LOG_(INFO) << "PanicHandlerTest001: end.";
97 }
98 
99 /**
100  * @tc.name: PanicHandlerTest002
101  * @tc.desc: test panic in child thread
102  * @tc.type: FUNC
103  * @tc.require: issueI6HM7C
104  */
105 HWTEST_F(PanicHandlerTest, PanicHandlerTest002, TestSize.Level2)
106 {
107     GTEST_LOG_(INFO) << "PanicHandlerTest002: start.";
108     ListenAndCheckHiSysevent();
109     panicListener->SetKeyWord("panic in child thread");
110     ForkAndTriggerRustPanic(false);
111     if (panicListener != nullptr) {
112         GTEST_LOG_(INFO) << "PanicHandlerTest002: ready to check hisysevent reason keyword.";
113         ASSERT_TRUE(panicListener->CheckKeywordInReasons());
114     }
115     GTEST_LOG_(INFO) << "PanicHandlerTest002: end.";
116 }
117 } // namespace HiviewDFX
118 } // namespace OHOS