• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <dlfcn.h>
17 #include <hwext/gtest-ext.h>
18 #include <hwext/gtest-tag.h>
19 #include <sys/types.h>
20 
21 #include "memory_data_plugin.h"
22 #include "plugin_module_api.h"
23 
24 using namespace testing::ext;
25 
26 namespace {
27 const std::string DEFAULT_TEST_PATH("/data/local/tmp/");
28 #if defined(__LP64__)
29 const std::string DEFAULT_SO_PATH("/system/lib64/");
30 #else
31 const std::string DEFAULT_SO_PATH("/system/lib/");
32 #endif
33 const std::string DEFAULT_BIN_PATH("/data/local/tmp/memorytest");
34 constexpr uint32_t BUF_SIZE = 4 * 1024 * 1024;
35 const int US_PER_S = 1000000;
36 
37 std::string g_path;
38 
39 struct TestElement {
40     int32_t pid;
41     std::string name;
42     // data from /proc/$pid/stat
43     uint64_t vm_size_kb;
44     uint64_t vm_rss_kb;
45     uint64_t rss_anon_kb;
46     uint64_t rss_file_kb;
47     uint64_t rss_shmem_kb;
48     uint64_t vm_swap_kb;
49     uint64_t vm_locked_kb;
50     uint64_t vm_hwm_kb;
51     int64_t oom_score_adj;
52 
53     uint64_t java_heap;
54     uint64_t native_heap;
55     uint64_t code;
56     uint64_t stack;
57     uint64_t graphics;
58     uint64_t private_other;
59 };
60 
61 TestElement g_pidtarget[] = {
62     {1, "systemd", 226208, 9388, 2984, 6404, 0, 0, 0, 9616, -1, 3036, 4256, 288, 748, 0, 1388},
63     {2, "kthreadd", 0, 0, 0, 0, 0, 0, 0, 0, -100, 3036, 4260, 336, 760, 0, 4204},
64     {11, "rcu_sched", 0, 0, 0, 0, 0, 0, 0, 0, 0, 3036, 4272, 400, 772, 0, 7160},
65 };
66 
67 unsigned long g_meminfo[] = {
68     16168696, 1168452, 12363564, 2726188, 7370484, 29260,    8450388,  4807668,
69     2535372,  658832,  4148836,  132,     0,       63999996, 62211580, 0
70 };
71 
72 unsigned long g_vmeminfo[] = {
73     112823, 0,      587,    1848,   101,   9074,  8426,   18314,
74     0,     2416,  2348,  9073,   1876,  26863, 1,      0
75 };
76 
77 std::string GetFullPath(std::string path);
78 
79 class MemoryDataPluginTest : public ::testing::Test {
80 public:
81     static void SetUpTestCase();
82 
TearDownTestCase()83     static void TearDownTestCase() {}
SetUp()84     void SetUp() {}
TearDown()85     void TearDown() {}
86 };
87 
Getexepath()88 string Getexepath()
89 {
90     char buf[PATH_MAX] = "";
91     std::string path = "/proc/self/exe";
92     size_t rslt = readlink(path.c_str(), buf, sizeof(buf));
93     if (rslt < 0 || (rslt >= sizeof(buf))) {
94         return "";
95     }
96     buf[rslt] = '\0';
97     for (int i = rslt; i >= 0; i--) {
98         if (buf[i] == '/') {
99             buf[i + 1] = '\0';
100             break;
101         }
102     }
103     return buf;
104 }
105 
SetPluginProcessConfig(std::vector<int> processList,MemoryConfig & protoConfig)106 void SetPluginProcessConfig(std::vector<int> processList, MemoryConfig& protoConfig)
107 {
108     if (processList.size() != 0) {
109         // 具体进程
110         protoConfig.set_report_process_mem_info(true);
111         protoConfig.set_report_app_mem_info(true);
112         for (size_t i = 0; i < processList.size(); i++) {
113             protoConfig.add_pid(processList.at(i));
114         }
115     } else {
116         // 进程树
117         protoConfig.set_report_process_tree(true);
118     }
119 }
120 
SetPluginSysMemConfig(MemoryConfig & protoConfig)121 void SetPluginSysMemConfig(MemoryConfig &protoConfig)
122 {
123     protoConfig.set_report_sysmem_mem_info(true);
124 
125     protoConfig.add_sys_meminfo_counters(SysMeminfoType::PMEM_MEM_TOTAL);
126     protoConfig.add_sys_meminfo_counters(SysMeminfoType::PMEM_MEM_FREE);
127     protoConfig.add_sys_meminfo_counters(SysMeminfoType::PMEM_MEM_AVAILABLE);
128     protoConfig.add_sys_meminfo_counters(SysMeminfoType::PMEM_BUFFERS);
129     protoConfig.add_sys_meminfo_counters(SysMeminfoType::PMEM_CACHED);
130     protoConfig.add_sys_meminfo_counters(SysMeminfoType::PMEM_SWAP_CACHED);
131     protoConfig.add_sys_meminfo_counters(SysMeminfoType::PMEM_ACTIVE);
132     protoConfig.add_sys_meminfo_counters(SysMeminfoType::PMEM_INACTIVE);
133 
134     protoConfig.add_sys_meminfo_counters(SysMeminfoType::PMEM_ACTIVE_ANON);
135     protoConfig.add_sys_meminfo_counters(SysMeminfoType::PMEM_INACTIVE_ANON);
136     protoConfig.add_sys_meminfo_counters(SysMeminfoType::PMEM_INACTIVE_FILE);
137     protoConfig.add_sys_meminfo_counters(SysMeminfoType::PMEM_UNEVICTABLE);
138     protoConfig.add_sys_meminfo_counters(SysMeminfoType::PMEM_MLOCKED);
139     protoConfig.add_sys_meminfo_counters(SysMeminfoType::PMEM_SWAP_TOTAL);
140     protoConfig.add_sys_meminfo_counters(SysMeminfoType::PMEM_SWAP_FREE);
141     protoConfig.add_sys_meminfo_counters(SysMeminfoType::PMEM_DIRTY);
142 
143     protoConfig.set_report_sysmem_vmem_info(true);
144 
145     protoConfig.add_sys_vmeminfo_counters(SysVMeminfoType::VMEMINFO_NR_FREE_PAGES);
146     protoConfig.add_sys_vmeminfo_counters(SysVMeminfoType::VMEMINFO_NR_INACTIVE_ANON);
147     protoConfig.add_sys_vmeminfo_counters(SysVMeminfoType::VMEMINFO_NR_ACTIVE_ANON);
148     protoConfig.add_sys_vmeminfo_counters(SysVMeminfoType::VMEMINFO_NR_INACTIVE_FILE);
149 
150     protoConfig.add_sys_vmeminfo_counters(SysVMeminfoType::VMEMINFO_NR_ACTIVE_FILE);
151     protoConfig.add_sys_vmeminfo_counters(SysVMeminfoType::VMEMINFO_NR_UNEVICTABLE);
152     protoConfig.add_sys_vmeminfo_counters(SysVMeminfoType::VMEMINFO_NR_MLOCK);
153     protoConfig.add_sys_vmeminfo_counters(SysVMeminfoType::VMEMINFO_NR_ANON_PAGES);
154 
155     protoConfig.add_sys_vmeminfo_counters(SysVMeminfoType::VMEMINFO_NR_MAPPED);
156     protoConfig.add_sys_vmeminfo_counters(SysVMeminfoType::VMEMINFO_NR_FILE_PAGES);
157     protoConfig.add_sys_vmeminfo_counters(SysVMeminfoType::VMEMINFO_NR_DIRTY);
158     protoConfig.add_sys_vmeminfo_counters(SysVMeminfoType::VMEMINFO_NR_SLAB_RECLAIMABLE);
159 
160     protoConfig.add_sys_vmeminfo_counters(SysVMeminfoType::VMEMINFO_NR_SLAB_UNRECLAIMABLE);
161     protoConfig.add_sys_vmeminfo_counters(SysVMeminfoType::VMEMINFO_NR_PAGE_TABLE_PAGES);
162     protoConfig.add_sys_vmeminfo_counters(SysVMeminfoType::VMEMINFO_NR_KERNEL_STACK);
163     protoConfig.add_sys_vmeminfo_counters(SysVMeminfoType::VMEMINFO_NR_UNSTABLE);
164 }
165 
SetPluginMemoryServiceConfig(MemoryConfig & protoConfig)166 void SetPluginMemoryServiceConfig(MemoryConfig& protoConfig)
167 {
168     protoConfig.set_report_process_mem_info(true);
169     protoConfig.set_report_app_mem_info(true);
170     protoConfig.add_pid(1);
171     protoConfig.set_report_app_mem_by_memory_service(true);
172 }
173 
PluginStub(MemoryDataPlugin & memoryPlugin,MemoryConfig & protoConfig,MemoryData & memoryData)174 bool PluginStub(MemoryDataPlugin& memoryPlugin, MemoryConfig& protoConfig, MemoryData& memoryData)
175 {
176     // serialize
177     int configSize = protoConfig.ByteSizeLong();
178     std::vector<uint8_t> configData(configSize);
179     int ret = protoConfig.SerializeToArray(configData.data(), configData.size());
180     CHECK_TRUE(ret > 0, false, "PluginStub::SerializeToArray fail!!!");
181 
182     // start
183     ret = memoryPlugin.Start(configData.data(), configData.size());
184     CHECK_TRUE(ret == 0, false, "PluginStub::start plugin fail!!!");
185 
186     // report
187     std::vector<uint8_t> bufferData(BUF_SIZE);
188     ret = memoryPlugin.Report(bufferData.data(), bufferData.size());
189     if (ret >= 0) {
190         memoryData.ParseFromArray(bufferData.data(), ret);
191         return true;
192     }
193 
194     return false;
195 }
196 
GetFullPath(std::string path)197 std::string GetFullPath(std::string path)
198 {
199     if (path.size() > 0 && path[0] != '/') {
200         return Getexepath() + path;
201     }
202     return path;
203 }
204 
SetUpTestCase()205 void MemoryDataPluginTest::SetUpTestCase()
206 {
207     g_path = GetFullPath(DEFAULT_TEST_PATH);
208     EXPECT_NE("", g_path);
209     g_path += "utresources/proc";
210 }
211 
212 /**
213  * @tc.name: memory plugin
214  * @tc.desc: Test whether the path exists.
215  * @tc.type: FUNC
216  */
217 HWTEST_F(MemoryDataPluginTest, TestUtpath, TestSize.Level1)
218 {
219     EXPECT_NE(g_path, "");
220 }
221 
222 /**
223  * @tc.name: memory plugin
224  * @tc.desc: Pid list test in a specific directory.
225  * @tc.type: FUNC
226  */
227 HWTEST_F(MemoryDataPluginTest, Testpidlist, TestSize.Level1)
228 {
229     MemoryDataPlugin* memoryPlugin = new MemoryDataPlugin();
230     const std::vector<int> expectPidList = {1, 2, 11};
231 
232     DIR* dir = memoryPlugin->OpenDestDir(g_path.c_str());
233     EXPECT_NE(nullptr, dir);
234 
235     std::vector<int> cmpPidList;
236     while (int32_t pid = memoryPlugin->GetValidPid(dir)) {
237         cmpPidList.push_back(pid);
238     }
239     sort(cmpPidList.begin(), cmpPidList.end());
240     closedir(dir);
241     EXPECT_EQ(cmpPidList, expectPidList);
242     delete memoryPlugin;
243 }
244 
245 /**
246  * @tc.name: memory plugin
247  * @tc.desc: Mem information test for specific pid.
248  * @tc.type: FUNC
249  */
250 HWTEST_F(MemoryDataPluginTest, Testpluginformeminfo, TestSize.Level1)
251 {
252     MemoryDataPlugin memoryPlugin;
253     MemoryData memoryData;
254     MemoryConfig protoConfig;
255 
256     memoryPlugin.SetPath(const_cast<char*>(g_path.c_str()));
257     SetPluginSysMemConfig(protoConfig);
258     EXPECT_TRUE(PluginStub(memoryPlugin, protoConfig, memoryData));
259 
260     EXPECT_EQ(16, memoryData.meminfo().size());
261     int index = memoryData.meminfo_size();
262     for (int i = 0; i < index; ++i) {
263         EXPECT_EQ(g_meminfo[i], memoryData.meminfo(i).value());
264     }
265 
266     EXPECT_EQ(16, memoryData.vmeminfo().size());
267     index = memoryData.vmeminfo_size();
268     for (int i = 0; i < index; ++i) {
269         EXPECT_EQ(g_vmeminfo[i], memoryData.vmeminfo(i).value());
270     }
271     memoryPlugin.Stop();
272 }
273 
274 /**
275  * @tc.name: memory plugin
276  * @tc.desc: pid list information test for process tree.
277  * @tc.type: FUNC
278  */
279 HWTEST_F(MemoryDataPluginTest, Testpluginforlist, TestSize.Level1)
280 {
281     MemoryDataPlugin memoryPlugin;
282     MemoryData memoryData;
283     MemoryConfig protoConfig;
284 
285     std::vector<int> cmpPidList;
286     EXPECT_EQ((size_t)0, cmpPidList.size());
287 
288     memoryPlugin.SetPath(const_cast<char*>(g_path.c_str()));
289 
290     SetPluginProcessConfig(cmpPidList, protoConfig);
291     EXPECT_TRUE(PluginStub(memoryPlugin, protoConfig, memoryData));
292 
293     int index = memoryData.processesinfo_size();
294     EXPECT_EQ(3, index);
295     for (int i = 0; i < index; ++i) {
296         ProcessMemoryInfo it = memoryData.processesinfo(i);
297         EXPECT_EQ(g_pidtarget[i].pid, it.pid());
298         EXPECT_EQ(g_pidtarget[i].name, it.name());
299         EXPECT_EQ(g_pidtarget[i].vm_size_kb, it.vm_size_kb());
300         EXPECT_EQ(g_pidtarget[i].vm_rss_kb, it.vm_rss_kb());
301         EXPECT_EQ(g_pidtarget[i].rss_anon_kb, it.rss_anon_kb());
302         EXPECT_EQ(g_pidtarget[i].rss_file_kb, it.rss_file_kb());
303         EXPECT_EQ(g_pidtarget[i].rss_shmem_kb, it.rss_shmem_kb());
304         EXPECT_EQ(g_pidtarget[i].vm_locked_kb, it.vm_locked_kb());
305         EXPECT_EQ(g_pidtarget[i].vm_hwm_kb, it.vm_hwm_kb());
306 
307         EXPECT_EQ(g_pidtarget[i].oom_score_adj, it.oom_score_adj());
308 
309         EXPECT_FALSE(it.has_memsummary());
310     }
311 
312     memoryPlugin.Stop();
313 }
314 
315 /**
316  * @tc.name: memory plugin
317  * @tc.desc: pid list information test for specific pid.
318  * @tc.type: FUNC
319  */
320 HWTEST_F(MemoryDataPluginTest, Testpluginforsinglepid, TestSize.Level1)
321 {
322     MemoryDataPlugin memoryPlugin;
323     MemoryData memoryData;
324     MemoryConfig protoConfig;
325 
326     std::vector<int> pid = {5};
327     TestElement singlepid = {};
328 
329     memoryPlugin.SetPath(const_cast<char*>(g_path.c_str()));
330 
331     SetPluginProcessConfig(pid, protoConfig);
332     EXPECT_TRUE(PluginStub(memoryPlugin, protoConfig, memoryData));
333 
334     int index = memoryData.processesinfo_size();
335     EXPECT_EQ(1, index);
336 
337     ProcessMemoryInfo it = memoryData.processesinfo(0);
338     EXPECT_EQ(singlepid.pid, it.pid());
339     EXPECT_EQ(singlepid.name, it.name());
340     EXPECT_EQ(singlepid.vm_size_kb, it.vm_size_kb());
341     EXPECT_EQ(singlepid.vm_rss_kb, it.vm_rss_kb());
342     EXPECT_EQ(singlepid.rss_anon_kb, it.rss_anon_kb());
343     EXPECT_EQ(singlepid.rss_file_kb, it.rss_file_kb());
344     EXPECT_EQ(singlepid.rss_shmem_kb, it.rss_shmem_kb());
345     EXPECT_EQ(singlepid.vm_locked_kb, it.vm_locked_kb());
346     EXPECT_EQ(singlepid.vm_hwm_kb, it.vm_hwm_kb());
347 
348     EXPECT_EQ(singlepid.oom_score_adj, it.oom_score_adj());
349 
350     EXPECT_TRUE(it.has_memsummary());
351     AppSummary app = it.memsummary();
352     EXPECT_EQ(singlepid.java_heap, app.java_heap());
353     EXPECT_EQ(singlepid.native_heap, app.native_heap());
354     EXPECT_EQ(singlepid.code, app.code());
355     EXPECT_EQ(singlepid.stack, app.stack());
356     EXPECT_EQ(singlepid.graphics, app.graphics());
357     EXPECT_EQ(singlepid.private_other, app.private_other());
358 
359     memoryPlugin.Stop();
360 }
361 
362 /**
363  * @tc.name: memory plugin
364  * @tc.desc: pid list information test for specific pids.
365  * @tc.type: FUNC
366  */
367 HWTEST_F(MemoryDataPluginTest, Testpluginforpids, TestSize.Level1)
368 {
369     MemoryDataPlugin memoryPlugin;
370     MemoryData memoryData;
371     MemoryConfig protoConfig;
372 
373     std::vector<int> cmpPidList = {1, 2, 11};
374     EXPECT_NE((size_t)0, cmpPidList.size());
375 
376     memoryPlugin.SetPath(const_cast<char*>(g_path.c_str()));
377 
378     SetPluginProcessConfig(cmpPidList, protoConfig);
379     EXPECT_TRUE(PluginStub(memoryPlugin, protoConfig, memoryData));
380 
381     int index = memoryData.processesinfo_size();
382     EXPECT_EQ(3, index);
383     for (int i = 0; i < index; ++i) {
384         ProcessMemoryInfo it = memoryData.processesinfo(i);
385         EXPECT_EQ(g_pidtarget[i].pid, it.pid());
386         EXPECT_EQ(g_pidtarget[i].name, it.name());
387         EXPECT_EQ(g_pidtarget[i].vm_size_kb, it.vm_size_kb());
388         EXPECT_EQ(g_pidtarget[i].vm_rss_kb, it.vm_rss_kb());
389         EXPECT_EQ(g_pidtarget[i].rss_anon_kb, it.rss_anon_kb());
390         EXPECT_EQ(g_pidtarget[i].rss_file_kb, it.rss_file_kb());
391         EXPECT_EQ(g_pidtarget[i].rss_shmem_kb, it.rss_shmem_kb());
392         EXPECT_EQ(g_pidtarget[i].vm_locked_kb, it.vm_locked_kb());
393         EXPECT_EQ(g_pidtarget[i].vm_hwm_kb, it.vm_hwm_kb());
394 
395         EXPECT_EQ(g_pidtarget[i].oom_score_adj, it.oom_score_adj());
396 
397         if (i == 0) {
398             EXPECT_TRUE(it.has_memsummary());
399         }
400     }
401 
402     memoryPlugin.Stop();
403 }
404 
405 /**
406  * @tc.name: memory plugin
407  * @tc.desc: Smaps stats info test for specific pids.
408  * @tc.type: FUNC
409  */
410 HWTEST_F(MemoryDataPluginTest, TestSmapsStatsInfo, TestSize.Level1)
411 {
412     const std::vector<int> expectPidList = {1, 2, 11};
413 
414     SmapsStats smap(std::string(g_path + "/"));
415     for (size_t i = 0; i < expectPidList.size(); i++) {
416         ProcessMemoryInfo processMemoryInfo;
417         EXPECT_TRUE(smap.ParseMaps(expectPidList[i], processMemoryInfo, true, false));
418         EXPECT_EQ(g_pidtarget[i].java_heap, (uint64_t)(smap.GetProcessJavaHeap()));
419         EXPECT_EQ(g_pidtarget[i].native_heap, (uint64_t)(smap.GetProcessNativeHeap()));
420         EXPECT_EQ(g_pidtarget[i].code, (uint64_t)(smap.GetProcessCode()));
421         EXPECT_EQ(g_pidtarget[i].stack, (uint64_t)(smap.GetProcessStack()));
422         EXPECT_EQ(g_pidtarget[i].graphics, (uint64_t)(smap.GetProcessGraphics()));
423         EXPECT_EQ(g_pidtarget[i].private_other, (uint64_t)(smap.GetProcessPrivateOther()));
424     }
425 }
426 
427 /**
428  * @tc.name: memory plugin
429  * @tc.desc: Vmstat info test for specific pids.
430  * @tc.type: FUNC
431  */
432 HWTEST_F(MemoryDataPluginTest, TestpluginWriteVmstat, TestSize.Level1)
433 {
434     MemoryDataPlugin memoryPlugin;
435     MemoryData memoryData;
436     MemoryConfig protoConfig;
437 
438     protoConfig.set_report_sysmem_vmem_info(true);
439     EXPECT_TRUE(PluginStub(memoryPlugin, protoConfig, memoryData));
440 
441     memoryPlugin.Stop();
442 }
443 
444 /**
445  * @tc.name: memory plugin
446  * @tc.desc: Get information through MemoryService.
447  * @tc.type: FUNC
448  */
449 HWTEST_F(MemoryDataPluginTest, TestpluginMemoryService, TestSize.Level1)
450 {
451     MemoryDataPlugin memoryPlugin;
452     MemoryData memoryData;
453     MemoryConfig protoConfig;
454 
455     SetPluginMemoryServiceConfig(protoConfig);
456     EXPECT_TRUE(PluginStub(memoryPlugin, protoConfig, memoryData));
457     std::string line = "01234567890";
458     memoryPlugin.ParseNumber(line);
459 
460     ProcessMemoryInfo it = memoryData.processesinfo(0);
461     EXPECT_FALSE(it.has_memsummary());
462     AppSummary app = it.memsummary();
463     EXPECT_EQ((uint64_t)0, app.java_heap());
464     EXPECT_EQ((uint64_t)0, app.native_heap());
465     EXPECT_EQ((uint64_t)0, app.code());
466     EXPECT_EQ((uint64_t)0, app.stack());
467     EXPECT_EQ((uint64_t)0, app.graphics());
468     EXPECT_EQ((uint64_t)0, app.private_other());
469 
470     memoryPlugin.Stop();
471 }
472 
WriteFunc(WriterStruct * writer,const void * data,size_t size)473 long WriteFunc(WriterStruct* writer, const void* data, size_t size)
474 {
475     if (writer == nullptr || data == nullptr || size <= 0) {
476         return -1;
477     }
478     return 0;
479 }
480 
FlushFunc(WriterStruct * writer)481 bool FlushFunc(WriterStruct* writer)
482 {
483     if (writer == nullptr) {
484         return false;
485     }
486     return true;
487 }
488 
489 /**
490  * @tc.name: mem plugin
491  * @tc.desc: test register
492  * @tc.type: FUNC
493  */
494 HWTEST_F(MemoryDataPluginTest, TestRegister, TestSize.Level1)
495 {
496     std::string path = DEFAULT_SO_PATH + std::string("libmemdataplugin.z.so");
497     void* handle = dlopen(path.c_str(), RTLD_LAZY);
498     EXPECT_NE(handle, nullptr);
499     PluginModuleStruct* plugin = reinterpret_cast<PluginModuleStruct*>(dlsym(handle, "g_pluginModule"));
500     EXPECT_NE(plugin, nullptr);
501     EXPECT_STREQ(plugin->name, "memory-plugin");
502 
503     // set config
504     MemoryConfig config;
505     config.set_report_process_mem_info(true);
506     int size = config.ByteSizeLong();
507     ASSERT_GT(size, 0);
508     std::vector<uint8_t> configData(size);
509     ASSERT_GT(config.SerializeToArray(configData.data(), configData.size()), 0);
510 
511     // test framework process
512     WriterStruct writer = {WriteFunc, FlushFunc};
513     std::vector<uint8_t> dataBuffer(plugin->resultBufferSizeHint);
514     EXPECT_EQ(plugin->callbacks->onRegisterWriterStruct(&writer), 0);
515 }
516 
517 /**
518  * @tc.name: mem plugin
519  * @tc.desc: start fail test
520  * @tc.type: FUNC
521  */
522 HWTEST_F(MemoryDataPluginTest, TestStartFail, TestSize.Level1)
523 {
524     MemoryConfig config;
525     MemoryDataPlugin plugin;
526 
527     // set config
528     config.set_report_process_mem_info(true);
529 
530     // serialize
531     int size = config.ByteSizeLong();
532     ASSERT_GT(size, 0);
533     std::vector<uint8_t> configData(size);
534     ASSERT_GT(config.SerializeToArray(configData.data(), configData.size()), 0);
535 
536     // start
537     EXPECT_NE(plugin.Start(configData.data(), size - 1), 0);
538 }
539 
540 /**
541  * @tc.name: mem plugin
542  * @tc.desc: Framework test
543  * @tc.type: FUNC
544  */
545 HWTEST_F(MemoryDataPluginTest, TestFramework, TestSize.Level1)
546 {
547     std::string path = DEFAULT_SO_PATH + std::string("libmemdataplugin.z.so");
548     void* handle = dlopen(path.c_str(), RTLD_LAZY);
549     EXPECT_NE(handle, nullptr);
550     PluginModuleStruct* plugin = reinterpret_cast<PluginModuleStruct*>(dlsym(handle, "g_pluginModule"));
551     EXPECT_NE(plugin, nullptr);
552     EXPECT_STREQ(plugin->name, "memory-plugin");
553 
554     // set config
555     MemoryConfig config;
556     config.set_report_process_mem_info(true);
557     int size = config.ByteSizeLong();
558     ASSERT_GT(size, 0);
559     std::vector<uint8_t> configData(size);
560     ASSERT_GT(config.SerializeToArray(configData.data(), configData.size()), 0);
561 
562     // test framework process
563     std::vector<uint8_t> dataBuffer(plugin->resultBufferSizeHint);
564     EXPECT_EQ(plugin->callbacks->onPluginSessionStart(configData.data(), configData.size()), 0);
565     EXPECT_EQ(plugin->callbacks->onPluginReportResult(dataBuffer.data(), dataBuffer.size()), 0);
566     EXPECT_EQ(plugin->callbacks->onPluginSessionStop(), 0);
567 }
568 
OutputData(uint8_t * data,uint32_t size)569 void OutputData(uint8_t* data, uint32_t size)
570 {
571     MemoryData memoryData;
572     int ret = memoryData.ParseFromArray(data, size);
573     if (ret <= 0) {
574         HILOG_ERROR(LOG_CORE, "MemoryDataPluginTest, %s:parseFromArray failed!", __func__);
575         return;
576     }
577 
578     return;
579 }
580 
581 /**
582  * @tc.name: mem plugin
583  * @tc.desc: ProcessTree test
584  * @tc.type: FUNC
585  */
586 HWTEST_F(MemoryDataPluginTest, TestProcessTreeRunTime, TestSize.Level1)
587 {
588     std::string path = DEFAULT_SO_PATH + std::string("libmemdataplugin.z.so");
589     void* handle = dlopen(path.c_str(), RTLD_LAZY);
590     EXPECT_NE(handle, nullptr);
591     PluginModuleStruct* plugin = reinterpret_cast<PluginModuleStruct*>(dlsym(handle, "g_pluginModule"));
592     EXPECT_NE(plugin, nullptr);
593     EXPECT_STREQ(plugin->name, "memory-plugin");
594 
595     // set config
596     MemoryConfig config;
597     config.set_report_process_tree(true);
598     int size = config.ByteSizeLong();
599     ASSERT_GT(size, 0);
600     std::vector<uint8_t> configData(size);
601     ASSERT_GT(config.SerializeToArray(configData.data(), configData.size()), 0);
602 
603     // test framework process
604     int testCount = 10;
605     struct timeval start, end;
606     std::vector<uint8_t> dataBuffer(plugin->resultBufferSizeHint);
607     EXPECT_EQ(plugin->callbacks->onPluginSessionStart(configData.data(), configData.size()), 0);
608     clock_t clockstart = clock();
609     gettimeofday(&start, nullptr);
610     while (testCount--) {
611         int ret = plugin->callbacks->onPluginReportResult(dataBuffer.data(), dataBuffer.size());
612         ASSERT_GT(ret, 0);
613         OutputData(dataBuffer.data(), (uint32_t)ret);
614     }
615     gettimeofday(&end, nullptr);
616     clock_t clockend = clock();
617     int timeuse = US_PER_S * (end.tv_sec - start.tv_sec) + end.tv_usec - start.tv_usec;
618     HILOG_INFO(LOG_CORE, "clock time=%.3fs, timeofday=%.3fs", (double)(clockend - clockstart) / CLOCKS_PER_SEC,
619         (double)timeuse / US_PER_S);
620     EXPECT_EQ(plugin->callbacks->onPluginSessionStop(), 0);
621 }
622 
623 namespace {
624 const char* DUMP_FORMAT = R"(Applications Memory Usage (in Kilobytes):
625 Uptime: 559174 Realtime: 559174
626 App Summary
627 Pss(KB)
628 ------
629 Java Heap:  0
630 Native Heap:    2932
631 Code:   640
632 Stack:  60
633 Graphics:   0
634 Private Other:  1056
635 System: 1092
636 TOTAL:  5780      TOTAL SWAP (KB):        0)";
637 }
638 
639 /**
640  * @tc.name: mem plugin
641  * @tc.desc: test ParseMemInfo
642  * @tc.type: FUNC
643  */
644 HWTEST_F(MemoryDataPluginTest, TestParseMemInfo, TestSize.Level1)
645 {
646     MemoryDataPlugin plugin;
647     ProcessMemoryInfo memoryInfo;
648     uint64_t javaHeap = 0;
649     uint64_t nativeHeap = 2932;
650     uint64_t code = 640;
651     uint64_t stack = 60;
652     uint64_t graphics = 0;
653     uint64_t other = 1056;
654     uint64_t system = 1092;
655 
656     ASSERT_TRUE(plugin.ParseMemInfo(DUMP_FORMAT, &memoryInfo));
657     // test result
658     EXPECT_EQ(memoryInfo.mutable_memsummary()->java_heap(), javaHeap);
659     EXPECT_EQ(memoryInfo.mutable_memsummary()->native_heap(), nativeHeap);
660     EXPECT_EQ(memoryInfo.mutable_memsummary()->code(), code);
661     EXPECT_EQ(memoryInfo.mutable_memsummary()->stack(), stack);
662     EXPECT_EQ(memoryInfo.mutable_memsummary()->graphics(), graphics);
663     EXPECT_EQ(memoryInfo.mutable_memsummary()->private_other(), other);
664     EXPECT_EQ(memoryInfo.mutable_memsummary()->system(), system);
665 }
666 
ExecuteBin(const std::string & bin,const std::vector<std::string> & args)667 bool ExecuteBin(const std::string& bin, const std::vector<std::string>& args)
668 {
669     std::vector<char*> argv;
670     for (size_t i = 0; i < args.size(); i++) {
671         argv.push_back(const_cast<char*>(args[i].c_str()));
672     }
673     argv.push_back(nullptr); // last item in argv must be NULL
674 
675     int retval = execvp(bin.c_str(), argv.data());
676     CHECK_TRUE(retval != -1, false, "execv %s failed, %d!", bin.c_str(), errno);
677     _exit(EXIT_FAILURE);
678     abort(); // never should be here.
679     return true;
680 }
681 
682 /**
683  * @tc.name: mem plugin
684  * @tc.desc: test ParseMemInfo
685  * @tc.type: FUNC
686  */
687 HWTEST_F(MemoryDataPluginTest, TestPid, TestSize.Level1)
688 {
689     MemoryDataPlugin plugin;
690     MemoryData memoryData;
691     MemoryConfig config;
692 
693     std::string cmd = "chmod 777 " + DEFAULT_BIN_PATH;
694     system(cmd.c_str());
695     pid_t pid1 = fork();
696     if (pid1 == 0) {
697         std::vector<std::string> argv = {"childpidtest1", "10"};
698         ASSERT_TRUE(ExecuteBin(DEFAULT_BIN_PATH, argv));
699     }
700     pid_t pid2 = fork();
701     if (pid2 == 0) {
702         std::vector<std::string> argv = {"childpidtest2", "1"};
703         ASSERT_TRUE(ExecuteBin(DEFAULT_BIN_PATH, argv));
704     }
705     sleep(1);
706 
707     // set config
708     config.set_report_process_mem_info(true);
709     config.set_report_app_mem_info(true);
710     config.add_pid(pid1);
711     config.add_pid(pid2);
712     // check result
713     EXPECT_TRUE(PluginStub(plugin, config, memoryData));
714     EXPECT_GT(memoryData.processesinfo(0).vm_size_kb(), memoryData.processesinfo(1).vm_size_kb());
715 
716     while (waitpid(-1, nullptr, WNOHANG) == 0) {
717         kill(pid1, SIGKILL);
718         kill(pid2, SIGKILL);
719     }
720     plugin.Stop();
721 }
722 } // namespace
723