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 <iomanip>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/time.h>
24 #include <sys/types.h>
25 #include <time.h>
26 #include <unistd.h>
27 #include <vector>
28 
29 #include "logging.h"
30 #include "memory_plugin_config.pb.h"
31 #include "memory_plugin_result.pb.h"
32 #include "plugin_module_api.h"
33 
34 using namespace testing::ext;
35 
36 #if defined(__i386__) || defined(__x86_64__)
37 const std::string LIB_PATH = const_cast<char*>("./hos/out/hos-arm/clang_x64/devtools/devtools/libmemdataplugin.z.so");
38 #else
39 const std::string LIB_PATH = const_cast<char*>("/system/lib/libmemdataplugin.z.so");
40 #endif
41 
42 namespace {
43 enum NumType {
44     BIT_WIDTH = 35,
45     MS_S = 1000000,
46 };
47 
48 class PluginModuleApiTest : public ::testing::Test {
49 protected:
SetUpTestCase()50     static void SetUpTestCase() {}
TearDownTestCase()51     static void TearDownTestCase() {}
52 
53     void SetUp() override {}
54     void TearDown() override {}
55 
MatchTail(const std::string& name, const char* str)56     bool MatchTail(const std::string& name, const char* str)
57     {
58         int index = name.size() - strlen(str);
59         if (index < 0) {
60             return false;
61         }
62         return strncmp(name.c_str() + index, str, strlen(str)) == 0;
63     }
64 
MemoryPluginTest(MemoryConfig& protoConfig, const std::string libPath)65     bool MemoryPluginTest(MemoryConfig& protoConfig, const std::string libPath)
66     {
67         MemoryData memoryData;
68         PluginModuleStruct* memplugin;
69         void* handle;
70         int cnt = 1;
71         uint8_t* dataBuffer;
72         clock_t clockstart, clockend;
73         struct timeval start, end;
74         int timeuse;
75 
76         if (!MatchTail(libPath, ".so")) {
77             printf("libPath=%s\r\n", libPath.c_str());
78             return false;
79         }
80 
81         handle = dlopen(libPath.c_str(), RTLD_LAZY);
82         if (handle == nullptr) {
83             HILOG_DEBUG(LOG_CORE, "test:dlopen err:%s.", dlerror());
84             return false;
85         }
86 
87         memplugin = (PluginModuleStruct*)dlsym(handle, "g_pluginModule");
88         dataBuffer = (uint8_t*)malloc(memplugin->resultBufferSizeHint);
89 
90         int configlength = protoConfig.ByteSizeLong();
91         std::vector<uint8_t> config(configlength);
92         protoConfig.SerializeToArray(config.data(), config.size());
93 
94         if (memplugin->callbacks->onPluginSessionStart(config.data(), config.size()) < 0) {
95             HILOG_DEBUG(LOG_CORE, "start failed");
96             dlclose(handle);
97             free(dataBuffer);
98             return false;
99         }
100 
101         clockstart = clock();
102         gettimeofday(&start, nullptr);
103 
104         while (cnt--) {
105             int len = memplugin->callbacks->onPluginReportResult(dataBuffer, memplugin->resultBufferSizeHint);
106             if (len > 0) {
107                 memoryData.ParseFromArray(dataBuffer, len);
108             }
109         }
110 
111         gettimeofday(&end, nullptr);
112         clockend = clock();
113         timeuse = MS_S * (end.tv_sec - start.tv_sec) + end.tv_usec - start.tv_usec;
114         HILOG_DEBUG(LOG_CORE, "clock time=%.3fs, timeofday=%.3fs", (double)(clockend - clockstart) / CLOCKS_PER_SEC,
115               (double)timeuse / MS_S);
116 
117         memplugin->callbacks->onPluginSessionStop();
118 
119         memplugin->callbacks->onRegisterWriterStruct(nullptr);
120 
121         dlclose(handle);
122         free(dataBuffer);
123         return true;
124     }
125 };
126 
HWTEST_F(PluginModuleApiTest, ProtoConfigNullAndInvalidSo, TestSize.Level1)127 HWTEST_F(PluginModuleApiTest, ProtoConfigNullAndInvalidSo, TestSize.Level1)
128 {
129     MemoryConfig protoConfig;
130     EXPECT_FALSE(PluginModuleApiTest::MemoryPluginTest(protoConfig, "1111"));
131 }
132 
HWTEST_F(PluginModuleApiTest, ProtoConfigNullAndEffectiveSo, TestSize.Level1)133 HWTEST_F(PluginModuleApiTest, ProtoConfigNullAndEffectiveSo, TestSize.Level1)
134 {
135     MemoryConfig protoConfig;
136     EXPECT_TRUE(PluginModuleApiTest::MemoryPluginTest(protoConfig, LIB_PATH));
137 }
138 
HWTEST_F(PluginModuleApiTest, ProtoConfigMemAndInvalidSo, TestSize.Level1)139 HWTEST_F(PluginModuleApiTest, ProtoConfigMemAndInvalidSo, TestSize.Level1)
140 {
141     MemoryConfig protoConfig;
142     protoConfig.set_report_process_mem_info(true);
143     EXPECT_FALSE(PluginModuleApiTest::MemoryPluginTest(protoConfig, "1111"));
144 }
145 
HWTEST_F(PluginModuleApiTest, ProtoConfigMemAndEffectiveSo, TestSize.Level1)146 HWTEST_F(PluginModuleApiTest, ProtoConfigMemAndEffectiveSo, TestSize.Level1)
147 {
148     MemoryConfig protoConfig;
149     protoConfig.set_report_process_mem_info(true);
150     EXPECT_TRUE(PluginModuleApiTest::MemoryPluginTest(protoConfig, LIB_PATH));
151 }
152 
HWTEST_F(PluginModuleApiTest, ProtoConfigPidAndInvalidSo, TestSize.Level1)153 HWTEST_F(PluginModuleApiTest, ProtoConfigPidAndInvalidSo, TestSize.Level1)
154 {
155     MemoryConfig protoConfig;
156     protoConfig.set_report_app_mem_info(true);
157     protoConfig.add_pid(1);
158     EXPECT_FALSE(PluginModuleApiTest::MemoryPluginTest(protoConfig, "1111"));
159 }
160 
HWTEST_F(PluginModuleApiTest, ProtoConfigPidAndEffectiveSo, TestSize.Level1)161 HWTEST_F(PluginModuleApiTest, ProtoConfigPidAndEffectiveSo, TestSize.Level1)
162 {
163     MemoryConfig protoConfig;
164     protoConfig.set_report_app_mem_info(true);
165     protoConfig.add_pid(1);
166     EXPECT_TRUE(PluginModuleApiTest::MemoryPluginTest(protoConfig, LIB_PATH));
167 }
168 
HWTEST_F(PluginModuleApiTest, MemoryPluginTreeAndInvalidSo, TestSize.Level1)169 HWTEST_F(PluginModuleApiTest, MemoryPluginTreeAndInvalidSo, TestSize.Level1)
170 {
171     MemoryConfig protoConfig;
172     protoConfig.set_report_process_tree(true);
173     EXPECT_FALSE(PluginModuleApiTest::MemoryPluginTest(protoConfig, "1111"));
174 }
175 
HWTEST_F(PluginModuleApiTest, MemoryPluginTreeAndEffectiveSo, TestSize.Level1)176 HWTEST_F(PluginModuleApiTest, MemoryPluginTreeAndEffectiveSo, TestSize.Level1)
177 {
178     MemoryConfig protoConfig;
179     protoConfig.set_report_process_tree(true);
180     EXPECT_TRUE(PluginModuleApiTest::MemoryPluginTest(protoConfig, LIB_PATH));
181 }
182 
HWTEST_F(PluginModuleApiTest, ApiCallInvalidSoAndInvalidStruct, TestSize.Level1)183 HWTEST_F(PluginModuleApiTest, ApiCallInvalidSoAndInvalidStruct, TestSize.Level1)
184 {
185     PluginModuleStruct memplugin;
186     ASSERT_EQ(memplugin.callbacks->onPluginSessionStart(nullptr, 0), 0);
187     ASSERT_EQ(memplugin.callbacks->onPluginReportResult(nullptr, 0), 0);
188     ASSERT_EQ(memplugin.callbacks->onPluginSessionStop(), 0);
189     ASSERT_EQ(memplugin.callbacks->onRegisterWriterStruct(nullptr), 0);
190 }
191 
HWTEST_F(PluginModuleApiTest, ApiCallEffectiveSoAndInvalidStruct, TestSize.Level1)192 HWTEST_F(PluginModuleApiTest, ApiCallEffectiveSoAndInvalidStruct, TestSize.Level1)
193 {
194     PluginModuleStruct* memplugin;
195     void* handle = dlopen(LIB_PATH.c_str(), RTLD_LAZY);
196     if (handle == nullptr) {
197         HILOG_DEBUG(LOG_CORE, "test:dlopen err:%s.", dlerror());
198     }
199     memplugin = (PluginModuleStruct*)dlsym(handle, "g_pluginModule");
200     ASSERT_EQ(memplugin->callbacks->onPluginSessionStart(nullptr, 0), 0);
201     ASSERT_EQ(memplugin->callbacks->onPluginReportResult(nullptr, 0), 0);
202     ASSERT_EQ(memplugin->callbacks->onPluginSessionStop(), 0);
203     ASSERT_EQ(memplugin->callbacks->onRegisterWriterStruct(nullptr), 0);
204 }
205 
HWTEST_F(PluginModuleApiTest, ApiCallInvalidSoAndEffectiveStruct, TestSize.Level1)206 HWTEST_F(PluginModuleApiTest, ApiCallInvalidSoAndEffectiveStruct, TestSize.Level1)
207 {
208     PluginModuleStruct memplugin;
209     WriterStruct writer;
210 
211     ASSERT_EQ(memplugin.callbacks->onPluginSessionStart(nullptr, 0), 0);
212     ASSERT_EQ(memplugin.callbacks->onPluginSessionStop(), 0);
213     ASSERT_EQ(memplugin.callbacks->onRegisterWriterStruct(&writer), 0);
214 }
215 
HWTEST_F(PluginModuleApiTest, ApiCallEffectiveSoAndEffectiveStruct, TestSize.Level1)216 HWTEST_F(PluginModuleApiTest, ApiCallEffectiveSoAndEffectiveStruct, TestSize.Level1)
217 {
218     PluginModuleStruct* memplugin;
219     WriterStruct writer;
220 
221     void* handle = dlopen(LIB_PATH.c_str(), RTLD_LAZY);
222     if (handle == nullptr) {
223         HILOG_DEBUG(LOG_CORE, "test:dlopen err:%s.", dlerror());
224     }
225     memplugin = (PluginModuleStruct*)dlsym(handle, "g_pluginModule");
226     ASSERT_EQ(memplugin->callbacks->onPluginSessionStart(nullptr, 0), 0);
227     ASSERT_EQ(memplugin->callbacks->onPluginSessionStop(), 0);
228     ASSERT_EQ(memplugin->callbacks->onRegisterWriterStruct(&writer), 0);
229 }
230 } // namespace
231 
232