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#ifdef HISYSEVENT_ENABLE
21#include "hisysevent_manager.h"
22#include "rustpanic_listener.h"
23
24using namespace testing;
25using namespace testing::ext;
26
27namespace OHOS {
28namespace HiviewDFX {
29namespace {
30static std::shared_ptr<RustPanicListener> panicListener = nullptr;
31}
32class PanicHandlerTest : public testing::Test {
33public:
34    static void SetUpTestCase();
35    static void TearDownTestCase();
36    void SetUp();
37    void TearDown();
38};
39
40void PanicHandlerTest::SetUpTestCase()
41{}
42
43void PanicHandlerTest::TearDownTestCase()
44{}
45
46void PanicHandlerTest::SetUp()
47{
48    chmod("/data/rustpanic_maker", 0755); // 0755 : -rwxr-xr-x
49}
50
51void PanicHandlerTest::TearDown()
52{
53    panicListener = nullptr;
54}
55
56static 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
71static 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 */
86HWTEST_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 */
105HWTEST_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
119#endif