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 <cstring>
17 #include <dlfcn.h>
18 #include <fcntl.h>
19 #include <gtest/gtest.h>
20 #include <cinttypes>
21 #include <cstdio>
22 #include <ctime>
23 #include <unistd.h>
24
25 #include "hidump_plugin.h"
26 #include "plugin_module_api.h"
27
28 using namespace testing::ext;
29
30 namespace {
31 const std::string DEFAULT_RECORD_FILE("/data/local/tmp/");
32 const int DEFAULT_WAIT = 10;
33 constexpr int BUF_MAX_LEN = 8;
34
35 class HidumpPluginUnittest : public ::testing::Test {
36 public:
SetUpTestCase()37 static void SetUpTestCase() {};
TearDownTestCase()38 static void TearDownTestCase() {};
39
SetUp()40 void SetUp() {}
TearDown()41 void TearDown() {}
42 };
43
WriteFunc(WriterStruct * writer,const void * data,size_t size)44 long WriteFunc(WriterStruct* writer, const void* data, size_t size)
45 {
46 if (writer == nullptr || data == nullptr || size <= 0) {
47 return -1;
48 }
49
50 return 0;
51 }
52
FlushFunc(WriterStruct * writer)53 bool FlushFunc(WriterStruct* writer)
54 {
55 if (writer == nullptr) {
56 return false;
57 }
58 return true;
59 }
60
PluginStart(HidumpPlugin & plugin,HidumpConfig & config)61 bool PluginStart(HidumpPlugin& plugin, HidumpConfig& config)
62 {
63 // serialize
64 int size = config.ByteSizeLong();
65 std::vector<uint8_t> configData(size);
66 int ret = config.SerializeToArray(configData.data(), configData.size());
67 CHECK_TRUE(ret > 0, false, "HidumpPluginUnittest: SerializeToArray fail!!!");
68 PROFILER_LOG_INFO(LOG_CORE, "HidumpPluginUnittest: SerializeToArray success");
69
70 // start
71 ret = plugin.Start(configData.data(), configData.size());
72 CHECK_TRUE(ret == 0, false, "HidumpPluginUnittest: start plugin fail!!!");
73 PROFILER_LOG_INFO(LOG_CORE, "HidumpPluginUnittest: Start success");
74
75 return true;
76 }
77
78 /**
79 * @tc.name: hidump plugin
80 * @tc.desc: Test framework
81 * @tc.type: FUNC
82 */
83 HWTEST_F(HidumpPluginUnittest, TestFramework, TestSize.Level1)
84 {
85 std::string path = std::string("libhidumpplugin.z.so");
86 void* handle = dlopen(path.c_str(), RTLD_LAZY);
87 EXPECT_NE(handle, nullptr);
88 PluginModuleStruct* plugin = reinterpret_cast<PluginModuleStruct*>(dlsym(handle, "g_pluginModule"));
89 EXPECT_NE(plugin, nullptr);
90 EXPECT_STREQ(plugin->name, "hidump-plugin");
91
92 // set config
93 HidumpConfig config;
94 config.set_report_fps(true);
95 int size = config.ByteSizeLong();
96 ASSERT_GT(size, 0);
97 std::vector<uint8_t> configData(size);
98 ASSERT_GT(config.SerializeToArray(configData.data(), configData.size()), 0);
99
100 // test framework process
101 WriterStruct writer = {WriteFunc, FlushFunc};
102 std::vector<uint8_t> dataBuffer(plugin->resultBufferSizeHint);
103 EXPECT_EQ(plugin->callbacks->onRegisterWriterStruct(&writer), 0);
104 EXPECT_EQ(plugin->callbacks->onPluginSessionStart(configData.data(), configData.size()), 0);
105 EXPECT_EQ(plugin->callbacks->onPluginSessionStop(), 0);
106 }
107
108 /**
109 * @tc.name: hidump plugin
110 * @tc.desc: Test if invalid cmd causes an exception
111 * expect:"inaccessible or not found"
112 * @tc.type: FUNC
113 */
114 HWTEST_F(HidumpPluginUnittest, TestInvalidCmd1, TestSize.Level1)
115 {
116 HidumpConfig config;
117 HidumpPlugin plugin;
118 WriterStruct writer = {WriteFunc, FlushFunc};
119
120 config.set_report_fps(true);
121 plugin.SetConfig(config);
122
123 const char *cmd = "";
124 plugin.SetTestCmd(cmd);
125 plugin.SetWriter(&writer);
126 EXPECT_STREQ(plugin.GetTestCmd(), cmd);
127 EXPECT_TRUE(PluginStart(plugin, config));
128 EXPECT_EQ(plugin.Stop(), 0);
129 }
130
131 /**
132 * @tc.name: hidump plugin
133 * @tc.desc: Test if invalid cmd causes an exception
134 * expect:"HidumpPlugin: fps command not output error!"
135 * @tc.type: FUNC
136 */
137 HWTEST_F(HidumpPluginUnittest, TestInvalidCmd2, TestSize.Level1)
138 {
139 HidumpConfig config;
140 HidumpPlugin plugin;
141 WriterStruct writer = {WriteFunc, FlushFunc};
142
143 config.set_report_fps(true);
144 plugin.SetConfig(config);
145
146 const char *cmd = "SP_daemon -profilerfps 0";
147 plugin.SetTestCmd(cmd);
148 plugin.SetWriter(&writer);
149 EXPECT_STREQ(plugin.GetTestCmd(), cmd);
150 EXPECT_TRUE(PluginStart(plugin, config));
151 EXPECT_EQ(plugin.Stop(), 0);
152 }
153
154 /**
155 * @tc.name: hidump plugin
156 * @tc.desc: Test Default Cmd
157 * @tc.type: FUNC
158 */
159 HWTEST_F(HidumpPluginUnittest, TestDefaultCmd, TestSize.Level1)
160 {
161 HidumpConfig config;
162 HidumpPlugin plugin;
163 WriterStruct writer = {WriteFunc, FlushFunc};
164
165 config.set_report_fps(true);
166 plugin.SetConfig(config);
167
168 plugin.SetWriter(&writer);
169 EXPECT_TRUE(PluginStart(plugin, config));
170 EXPECT_EQ(plugin.Stop(), 0);
171 }
172
173 /**
174 * @tc.name: hidump plugin
175 * @tc.desc: Test Default Cmd and verify result
176 * @tc.type: FUNC
177 */
178 HWTEST_F(HidumpPluginUnittest, TestCmdAndVerifyResult, TestSize.Level1)
179 {
180 HidumpConfig config;
181 HidumpPlugin plugin;
182 WriterStruct writer = {WriteFunc, FlushFunc};
183
184 config.set_report_fps(true);
185 plugin.SetConfig(config);
186
187 plugin.SetWriter(&writer);
188 EXPECT_TRUE(PluginStart(plugin, config));
189 sleep(DEFAULT_WAIT);
190 EXPECT_EQ(plugin.Stop(), 0);
191 }
192
193 /**
194 * @tc.name: hidump plugin
195 * @tc.desc: Test CustomPopen whether non-blocking
196 * @tc.type: FUNC
197 */
198 HWTEST_F(HidumpPluginUnittest, TestCustomPopenR, TestSize.Level1)
199 {
200 FILE *fp = nullptr;
201 HidumpPlugin plugin;
202
203 fp = plugin.CustomPopen("", "r");
204 EXPECT_NE(fp, nullptr);
205
206 EXPECT_NE(plugin.CustomPclose(fp), -1);
207 }
208
RecordFileExist(std::string & file)209 bool RecordFileExist(std::string& file)
210 {
211 if (access(DEFAULT_RECORD_FILE.c_str(), F_OK) != 0) {
212 return false;
213 }
214
215 std::string cmd = "cat " + file;
216 std::unique_ptr<FILE, int (*)(FILE*)> fp(popen(cmd.c_str(), "r"), pclose);
217 if (!fp) {
218 PROFILER_LOG_ERROR(LOG_CORE, "%s:: popen error", __func__);
219 return false;
220 }
221
222 char buff[BUF_MAX_LEN] = {0};
223 char* pRet = fgets(buff, BUF_MAX_LEN - 1, fp.get());
224 if (pRet == nullptr) {
225 PROFILER_LOG_ERROR(LOG_CORE, "%s: fgets Failed, errno(%d)", __func__, errno);
226 return false;
227 }
228 buff[BUF_MAX_LEN - 1] = '\0';
229 if (!strncmp(pRet, "123", strlen("123"))) {
230 return true;
231 }
232 return false;
233 }
234
235 /**
236 * @tc.name: hidump plugin
237 * @tc.desc: Test CustomPopen whether non-blocking
238 * @tc.type: FUNC
239 */
240 HWTEST_F(HidumpPluginUnittest, TestCustomPopenW, TestSize.Level1)
241 {
242 FILE *fp = nullptr;
243 HidumpPlugin plugin;
244 std::string fileName = "/data/local/tmp/hidumpTest.txt";
245 std::string cmd = "echo \"123\" > " + fileName;
246
247 fp = plugin.CustomPopen(cmd.c_str(), "w");
248 EXPECT_NE(fp, nullptr);
249 fflush(fp);
250 sleep(1);
251 EXPECT_NE(plugin.CustomPclose(fp), -1);
252 ASSERT_FALSE(RecordFileExist(fileName));
253
254 std::string rmCmd = "rm -rf " + fileName;
255 system(rmCmd.c_str());
256 }
257
258 /**
259 * @tc.name: hidump plugin
260 * @tc.desc: Test CustomPopen whether nullptr cmd
261 * @tc.type: FUNC
262 */
263 HWTEST_F(HidumpPluginUnittest, TestCustomPopenCmdNull, TestSize.Level1)
264 {
265 FILE *fp = nullptr;
266 HidumpPlugin plugin;
267
268 fp = plugin.CustomPopen(nullptr, "w");
269 ASSERT_EQ(fp, nullptr);
270 }
271
272 /**
273 * @tc.name: hidump plugin
274 * @tc.desc: Test CustomPopen whether nullptr type
275 * @tc.type: FUNC
276 */
277 HWTEST_F(HidumpPluginUnittest, TestCustomPopenTypeNull, TestSize.Level1)
278 {
279 FILE *fp = nullptr;
280 HidumpPlugin plugin;
281 std::string fileName = "/data/local/tmp/hidumpTest.txt";
282 std::string cmd = "echo \"123\" > " + fileName;
283
284 fp = plugin.CustomPopen(cmd.c_str(), nullptr);
285 ASSERT_EQ(fp, nullptr);
286 }
287
288 /**
289 * @tc.name: hidump plugin
290 * @tc.desc: Test CustomPopen whether nullptr
291 * @tc.type: FUNC
292 */
293 HWTEST_F(HidumpPluginUnittest, TestCustomPopenNull, TestSize.Level1)
294 {
295 FILE *fp = nullptr;
296 HidumpPlugin plugin;
297
298 fp = plugin.CustomPopen(nullptr, nullptr);
299 ASSERT_EQ(fp, nullptr);
300 }
301
302 /**
303 * @tc.name: hidump plugin
304 * @tc.desc: start fail test
305 * @tc.type: FUNC
306 */
307 HWTEST_F(HidumpPluginUnittest, TestStartFail, TestSize.Level1)
308 {
309 HidumpConfig config;
310 HidumpPlugin plugin;
311 WriterStruct writer = {WriteFunc, FlushFunc};
312
313 // set config
314 config.set_report_fps(true);
315
316 // test plugin process
317 plugin.SetWriter(&writer);
318 plugin.SetConfig(config);
319
320 // serialize
321 int size = config.ByteSizeLong();
322 ASSERT_GT(size, 0);
323 std::vector<uint8_t> configData(size);
324 ASSERT_GT(config.SerializeToArray(configData.data(), configData.size()), 0);
325
326 // start
327 EXPECT_NE(plugin.Start(configData.data(), size - 1), 0);
328 }
329 } // namespace