1 /*
2 * Copyright (c) 2021-2025 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 <gtest/gtest.h>
17 #include <memory>
18 #include <string>
19
20 #include "dfx_elf_parser.h"
21 #include "dfx_ptrace.h"
22 #include "dfx_regs.h"
23 #include "dfx_regs_get.h"
24 #include "dfx_buffer_writer.h"
25 #include "dfx_dump_request.h"
26 #include "dfx_thread.h"
27 #include "dump_utils.h"
28 #include <pthread.h>
29 #include "process_dumper.h"
30 #include "dfx_util.h"
31 #include "dfx_test_util.h"
32
33 using namespace OHOS::HiviewDFX;
34 using namespace testing::ext;
35 using namespace std;
36
37 namespace OHOS {
38 namespace HiviewDFX {
39 class ProcessDumpTest : public testing::Test {
40 public:
SetUpTestCase(void)41 static void SetUpTestCase(void) {}
TearDownTestCase(void)42 static void TearDownTestCase(void) {}
SetUp()43 void SetUp() {}
TearDown()44 void TearDown() {}
45 };
46 } // namespace HiviewDFX
47 } // namespace OHOS
48
49 namespace {
SleepThread(void * argv)50 void *SleepThread(void *argv)
51 {
52 int threadID = *(int*)argv;
53 printf("create MultiThread %d", threadID);
54
55 const int sleepTime = 10;
56 sleep(sleepTime);
57
58 return nullptr;
59 }
60
61 /**
62 * @tc.name: DfxProcessTest003
63 * @tc.desc: test init other threads
64 * @tc.type: FUNC
65 */
66 HWTEST_F (ProcessDumpTest, DfxProcessTest003, TestSize.Level0)
67 {
68 GTEST_LOG_(INFO) << "DfxProcessTest003: start.";
69 DfxProcess process;
70 process.InitProcessInfo(getpid(), getpid(), getuid(), "");
71 pthread_t childThread;
72 int threadID[1] = {1};
73 pthread_create(&childThread, NULL, SleepThread, &threadID[0]);
74 pthread_detach(childThread);
75 auto ret = process.InitOtherThreads(gettid());
76 EXPECT_EQ(true, ret) << "DfxProcessTest003 Failed";
77 auto threads = process.GetOtherThreads();
78 EXPECT_GT(threads.size(), 0) << "DfxProcessTest003 Failed";
79 process.ClearOtherThreads();
80 threads = process.GetOtherThreads();
81 EXPECT_EQ(threads.size(), 0) << "DfxProcessTest003 Failed";
82 GTEST_LOG_(INFO) << "DfxProcessTest003: end.";
83 }
84
85 /**
86 * @tc.name: DfxProcessTest004
87 * @tc.desc: test Attach Detach
88 * @tc.type: FUNC
89 */
90 HWTEST_F (ProcessDumpTest, DfxProcessTest004, TestSize.Level2)
91 {
92 GTEST_LOG_(INFO) << "DfxProcessTest004: start.";
93 DfxProcess process;
94 process.InitProcessInfo(getpid(), getpid(), getuid(), "");
95 auto ret = process.InitOtherThreads(gettid());
96 EXPECT_EQ(true, ret) << "DfxProcessTest004 Failed";
97 process.Attach();
98 process.Detach();
99 GTEST_LOG_(INFO) << "DfxProcessTest004: end.";
100 }
101
102 /**
103 * @tc.name: DfxProcessTest005
104 * @tc.desc: test DfxProcess ChangeTid
105 * @tc.type: FUNC
106 */
107 HWTEST_F (ProcessDumpTest, DfxProcessTest005, TestSize.Level2)
108 {
109 GTEST_LOG_(INFO) << "DfxProcessTest005: start.";
110 pid_t pid = getpid();
111 DfxProcess process1;
112 process1.InitProcessInfo(pid, pid, getuid(), "");
113 pid_t ret = process1.ChangeTid(pid, false);
114 process1.Attach();
115 process1.Detach();
116 ASSERT_EQ(ret, pid);
117 pthread_t tid;
118 int threadID[1] = {1};
119 pthread_create(&tid, NULL, SleepThread, &threadID[0]);
120 pthread_detach(tid);
121 DfxProcess process2;
122 process2.InitProcessInfo(pid, pid, getuid(), "");
123 ret = process2.ChangeTid(pid, false);
124 process2.Attach();
125 process2.Detach();
126 ASSERT_EQ(ret, pid);
127 GTEST_LOG_(INFO) << "DfxProcessTest005: end.";
128 }
129
130 /**
131 * @tc.name: DfxProcessTest006
132 * @tc.desc: test DfxProcess ChangeTid
133 * @tc.type: FUNC
134 */
135 HWTEST_F (ProcessDumpTest, DfxProcessTest006, TestSize.Level2)
136 {
137 GTEST_LOG_(INFO) << "DfxProcessTest006: start.";
138 pid_t pid = getpid();
139 DfxProcess process;
140 process.InitProcessInfo(pid, pid, getuid(), "");
141 pid_t id = process.ChangeTid(pid, false);
142 process.GetKeyThread() = DfxThread::Create(pid, pid, pid);
143 process.Attach(true);
144 DfxPtrace::Detach(pid);
145 ASSERT_TRUE(id != 0);
146 GTEST_LOG_(INFO) << "DfxProcessTest006: end.";
147 }
148
149 /**
150 * @tc.name: DfxProcessTest007
151 * @tc.desc: test DfxProcess ChangeTid
152 * @tc.type: FUNC
153 */
154 HWTEST_F (ProcessDumpTest, DfxProcessTest007, TestSize.Level2)
155 {
156 GTEST_LOG_(INFO) << "DfxProcessTest007: start.";
157 pid_t curPid = getpid();
158 pid_t pid = fork();
159 if (pid == 0) {
160 sleep(1);
161 _exit(0);
162 }
163 int status = 0;
164 waitpid(pid, &status, WNOHANG);
165 DfxProcess process;
166 process.InitProcessInfo(curPid, pid, getuid(), "");
167 pid_t id = process.ChangeTid(pid, false);
168 ProcessDumpRequest request = {
169 .type = ProcessDumpType::DUMP_TYPE_DUMP_CATCH,
170 .tid = pid,
171 .pid = pid,
172 .nsPid = curPid,
173 };
174 process.InitKeyThread(request);
175 id = process.ChangeTid(pid, false);
176 ASSERT_NE(id, 0);
177 GTEST_LOG_(INFO) << "DfxProcessTest007: end.";
178 }
179
180 /**
181 * @tc.name: DfxThreadTest002
182 * @tc.desc: test DfxThread GetThreadRegs
183 * @tc.type: FUNC
184 */
185 HWTEST_F (ProcessDumpTest, DfxThreadTest002, TestSize.Level2)
186 {
187 GTEST_LOG_(INFO) << "DfxThreadTest002: start.";
188 int32_t pid = 243, tid = 243;
189 DfxThread thread(pid, tid, tid);
190 std::shared_ptr<DfxRegs> inputrefs;
191 thread.SetThreadRegs(inputrefs);
192 std::shared_ptr<DfxRegs> outputrefs = thread.GetThreadRegs();
193 EXPECT_EQ(true, inputrefs == outputrefs) << "DfxThreadTest002 Failed";
194 GTEST_LOG_(INFO) << "DfxThreadTest002: end.";
195 }
196 }
197