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