• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
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 "command_poller.h"
18 #include "hook_manager.h"
19 #include "hook_service.h"
20 #include "hook_socket_client.h"
21 #include "parameters.h"
22 #include "socket_context.h"
23 
24 using namespace testing::ext;
25 using namespace OHOS::Developtools::NativeDaemon;
26 namespace {
27 const std::string OUTPUT_PATH = "/data/local/tmp/hiprofiler_data.htrace";
28 const int SMB_PAGES = 16384;
29 class HookManagerTest : public ::testing::Test {
30 public:
SetUpTestCase()31     static void SetUpTestCase()
32     {
33         OHOS::system::SetParameter("hiviewdfx.hiprofiler.profilerd.start", "1");
34 #ifdef COVERAGE_TEST
35         const int coverageSleepTime = 5; // sleep 5s
36         sleep(coverageSleepTime);
37 #else
38         sleep(1); // 睡眠1s确保hiprofilerd进程启动
39 #endif
40     }
TearDownTestCase()41     static void TearDownTestCase()
42     {
43         OHOS::system::SetParameter("hiviewdfx.hiprofiler.profilerd.start", "0");
44     }
45 };
46 
CreateCommand(const std::string & outputFile,const int32_t time,const std::string & processName)47 std::string CreateCommand(const std::string& outputFile, const int32_t time, const std::string& processName)
48 {
49     std::ostringstream cmdStream;
50     cmdStream << "hiprofiler_cmd \\\n"
51               << "-c - \\\n"
52               << "-o " << outputFile << " \\\n"
53               << "-t " << time << " \\\n"
54               << "-s \\\n"
55               << "-k \\\n"
56               << "<<CONFIG\n"
57               << "request_id: 1\n"
58               << "session_config {\n"
59               << "  buffers {\n"
60               << "    pages: 14848" << "\n"
61               << "  }\n"
62               << "}\n"
63               << "plugin_configs {\n"
64               << "  plugin_name: \"nativehook\"\n"
65               << "  config_data {\n"
66               << "process_name: \"" << processName << "\"\n"
67               << "smb_pages: " << SMB_PAGES << "\n"
68               << "dump_nmd: true\n"
69               << "  }\n"
70               << "}\n"
71               << "CONFIG\n";
72     return cmdStream.str();
73 }
74 
RunCommand(const std::string & cmd,std::string & content)75 bool RunCommand(const std::string& cmd, std::string& content)
76 {
77     std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
78     CHECK_TRUE(pipe, false, "RunCommand: create popen FAILED!");
79     static constexpr int buffSize = 1024;
80     std::array<char, buffSize> buffer;
81     while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
82         content += buffer.data();
83     }
84     return true;
85 }
86 
87 /*
88  * @tc.name: RegisterPlugin
89  * @tc.desc: test HookManager::RegisterAgentPlugin with normal case.
90  * @tc.type: FUNC
91  */
92 HWTEST_F(HookManagerTest, RegisterPlugin, TestSize.Level1)
93 {
94     std::shared_ptr<HookManager> hookManager = std::make_shared<HookManager>();
95     ASSERT_TRUE(hookManager != nullptr);
96     std::shared_ptr<CommandPoller> commandPoller = std::make_shared<CommandPoller>(hookManager);
97     ASSERT_TRUE(commandPoller != nullptr);
98     EXPECT_TRUE(commandPoller->OnConnect());
99     hookManager->SetCommandPoller(commandPoller);
100     ASSERT_TRUE(hookManager->RegisterAgentPlugin("nativehook"));
101     ASSERT_TRUE(hookManager->UnregisterAgentPlugin("nativehook"));
102 }
103 
104 /*
105  * @tc.name: LoadPlugin
106  * @tc.desc: test HookManager::LoadPlugin with normal case.
107  * @tc.type: FUNC
108  */
109 HWTEST_F(HookManagerTest, LoadPlugin, TestSize.Level1)
110 {
111     std::shared_ptr<HookManager> hookManager = std::make_shared<HookManager>();
112     ASSERT_TRUE(hookManager != nullptr);
113     std::shared_ptr<CommandPoller> commandPoller = std::make_shared<CommandPoller>(hookManager);
114     ASSERT_TRUE(commandPoller != nullptr);
115     EXPECT_TRUE(commandPoller->OnConnect());
116     hookManager->SetCommandPoller(commandPoller);
117     ASSERT_TRUE(hookManager->RegisterAgentPlugin("nativehook"));
118     ASSERT_TRUE(hookManager->LoadPlugin("nativehook"));
119     ASSERT_TRUE(hookManager->UnloadPlugin("nativehook"));
120     ASSERT_TRUE(hookManager->UnregisterAgentPlugin("nativehook"));
121 }
122 
123 /*
124  * @tc.name: UnloadPlugin
125  * @tc.desc: test HookManager::UnloadPlugin with normal case.
126  * @tc.type: FUNC
127  */
128 HWTEST_F(HookManagerTest, UnloadPlugin, TestSize.Level1)
129 {
130     std::shared_ptr<HookManager> hookManager = std::make_shared<HookManager>();
131     ASSERT_TRUE(hookManager != nullptr);
132     std::shared_ptr<CommandPoller> commandPoller = std::make_shared<CommandPoller>(hookManager);
133     ASSERT_TRUE(commandPoller != nullptr);
134     EXPECT_TRUE(commandPoller->OnConnect());
135     hookManager->SetCommandPoller(commandPoller);
136     ASSERT_TRUE(hookManager->RegisterAgentPlugin("nativehook"));
137     ASSERT_TRUE(hookManager->LoadPlugin("nativehook"));
138     ASSERT_TRUE(hookManager->UnloadPlugin(commandPoller->GetRequestId()));
139     ASSERT_TRUE(hookManager->UnregisterAgentPlugin("nativehook"));
140 }
141 
142 /*
143  * @tc.name: PluginSession
144  * @tc.desc: test HookManager process with normal case.
145  * @tc.type: FUNC
146  */
147 HWTEST_F(HookManagerTest, PluginSession, TestSize.Level1)
148 {
149     std::shared_ptr<HookManager> hookManager = std::make_shared<HookManager>();
150     ASSERT_TRUE(hookManager != nullptr);
151     std::shared_ptr<CommandPoller> commandPoller = std::make_shared<CommandPoller>(hookManager);
152     ASSERT_TRUE(commandPoller != nullptr);
153     EXPECT_TRUE(commandPoller->OnConnect());
154     hookManager->SetCommandPoller(commandPoller);
155 
156     std::vector<uint32_t> pluginIds(1);
157     ProfilerPluginConfig config;
158     config.set_name("nativehook");
159     config.set_plugin_sha256("");
160     config.set_sample_interval(20);
161 
162     PluginResult result;
163     std::vector<ProfilerPluginConfig> configVec;
164     configVec.push_back(config);
165 
166     EXPECT_FALSE(hookManager->CreatePluginSession(configVec));
167     EXPECT_FALSE(hookManager->StartPluginSession(pluginIds, configVec, result));
168     EXPECT_TRUE(hookManager->CreateWriter("name", 0, 0, 0));
169     EXPECT_TRUE(hookManager->ResetWriter(0));
170     EXPECT_FALSE(hookManager->StopPluginSession(pluginIds));
171     EXPECT_TRUE(hookManager->DestroyPluginSession(pluginIds));
172 }
173 
174 /*
175  * @tc.name: CheckProcess
176  * @tc.desc: test CheckProcess with false case.
177  * @tc.type: FUNC
178  */
179 HWTEST_F(HookManagerTest, CheckProcess, TestSize.Level1)
180 {
181     HookManager hookManager;
182     NativeHookConfig nativeConfig;
183     nativeConfig.set_process_name("HookManagerTest");
184     hookManager.SetHookConfig(nativeConfig);
185     EXPECT_TRUE(hookManager.CheckProcess());
186 
187     nativeConfig.set_startup_mode(true);
188     hookManager.SetHookConfig(nativeConfig);
189     EXPECT_TRUE(hookManager.CheckProcess());
190     hookManager.ResetStartupParam();
191 
192     // native_daemon_ut as a testing process
193     nativeConfig.set_startup_mode(false);
194     nativeConfig.set_process_name("native_daemon_ut");
195     hookManager.SetHookConfig(nativeConfig);
196     EXPECT_TRUE(hookManager.CheckProcess());
197     EXPECT_TRUE(hookManager.CheckProcessName());
198 }
199 
200 /*
201  * @tc.name: CheckNmdInfo
202  * @tc.desc: test CheckNmdInfoe when process is exit.
203  * @tc.type: FUNC
204  */
205 #ifdef __aarch64__
206 HWTEST_F(HookManagerTest, CheckNmdInfo, TestSize.Level1)
207 {
208     std::string cmd = CreateCommand(OUTPUT_PATH, 1, "hiview");
209     std::string ret;
210     EXPECT_TRUE(RunCommand(cmd, ret));
211     EXPECT_TRUE(ret.find("FAIL") == std::string::npos);
212     std::string filePath = "/data/local/tmp/nmd_hiview.txt";
213     EXPECT_EQ(access(filePath.c_str(), F_OK), 0);
214 
215     std::ifstream infile;
216     infile.open(filePath, std::ios::in);
217     EXPECT_TRUE(infile.is_open());
218     std::string buf;
219     bool nmdResult = false;
220     while (getline(infile, buf)) {
221         if (buf.find("jemalloc statistics") != std::string::npos) {
222             nmdResult = true;
223             break;
224         }
225     }
226     EXPECT_TRUE(nmdResult);
227 }
228 #endif
229 
230 /*
231  * @tc.name: CheckNmdInfoe002
232  * @tc.desc: test CheckNmdInfoe002 when process is not exit.
233  * @tc.type: FUNC
234  */
235 HWTEST_F(HookManagerTest, CheckNmdInfo002, TestSize.Level1)
236 {
237     std::string cmd = CreateCommand(OUTPUT_PATH, 1, "test_profiler");
238     std::string ret;
239     EXPECT_TRUE(RunCommand(cmd, ret));
240     EXPECT_TRUE(ret.find("FAIL") == std::string::npos);
241     std::string filePath = "/data/local/tmp/test_profiler.txt";
242     EXPECT_EQ(access(filePath.c_str(), F_OK), -1);
243 }
244 } // namespace