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
20 #include "network_plugin.h"
21 #include "plugin_module_api.h"
22
23 using namespace testing::ext;
24
25 namespace {
26 #if defined(__LP64__)
27 const std::string DEFAULT_SO_PATH("/system/lib64/");
28 #else
29 const std::string DEFAULT_SO_PATH("/system/lib/");
30 #endif
31 const std::string DEFAULT_TEST_PATH("/data/local/tmp/");
32 const std::string DEFAULT_NET_PATH("/proc/net/xt_qtaguid/stats");
33 constexpr uint32_t BUF_SIZE = 4 * 1024 * 1024;
34
35 std::string g_path;
36
37 struct NetDetails {
38 uint64_t tx;
39 uint64_t rx;
40 std::string type;
41 };
42
43 struct TestElement {
44 int32_t pid;
45 int32_t uid;
46 uint64_t tx;
47 uint64_t rx;
48 std::vector<NetDetails> details;
49 };
50
51 TestElement g_expectBegin = {9553, 10194, 0, 0};
52 TestElement g_expectEnd = {9553, 10194, 27085, 751549, {{27085, 751549, std::string("wlan0")}}};
53
54 std::string GetFullPath(std::string path);
55
56 class NetworkPluginTest : public ::testing::Test {
57 public:
58 static void SetUpTestCase();
59
TearDownTestCase()60 static void TearDownTestCase()
61 {
62 if (access(g_path.c_str(), F_OK) == 0) {
63 std::string str = "rm -rf " + GetFullPath(DEFAULT_TEST_PATH) + "utresources";
64 system(str.c_str());
65 }
66 }
SetUp()67 void SetUp() {}
TearDown()68 void TearDown() {}
69 };
70
Getexepath()71 string Getexepath()
72 {
73 char buf[PATH_MAX] = "";
74 std::string path = "/proc/self/exe";
75 size_t rslt = readlink(path.c_str(), buf, sizeof(buf));
76 if (rslt < 0 || (rslt >= sizeof(buf))) {
77 return "";
78 }
79 buf[rslt] = '\0';
80 for (int i = rslt; i >= 0; i--) {
81 if (buf[i] == '/') {
82 buf[i + 1] = '\0';
83 break;
84 }
85 }
86 return buf;
87 }
88
SetConfig(std::vector<int> pidList,NetworkConfig & config)89 bool SetConfig(std::vector<int> pidList, NetworkConfig& config)
90 {
91 CHECK_TRUE(pidList.size() > 0, false, "ut: %s failed!\n", __func__);
92
93 for (size_t i = 0; i < pidList.size(); i++) {
94 config.add_pid(pidList.at(i));
95 }
96 return true;
97 }
98
PluginStub(NetworkPlugin & plugin,NetworkDatas & networkData,NetworkConfig & config)99 bool PluginStub(NetworkPlugin& plugin, NetworkDatas& networkData, NetworkConfig& config)
100 {
101 // serialize
102 int configSize = config.ByteSizeLong();
103 std::vector<uint8_t> configData(configSize);
104 int ret = config.SerializeToArray(configData.data(), configData.size());
105
106 // start
107 ret = plugin.Start(configData.data(), configSize);
108 CHECK_TRUE(ret == 0, false, "ut: start failed!\n");
109
110 // report
111 std::vector<uint8_t> bufferData(BUF_SIZE);
112 ret = plugin.Report(bufferData.data(), bufferData.size());
113 if (ret > 0) {
114 networkData.ParseFromArray(bufferData.data(), ret);
115 return true;
116 }
117
118 return false;
119 }
120
GetFullPath(std::string path)121 std::string GetFullPath(std::string path)
122 {
123 if (path.size() > 0 && path[0] != '/') {
124 return Getexepath() + path;
125 }
126 return path;
127 }
128
SetUpTestCase()129 void NetworkPluginTest::SetUpTestCase()
130 {
131 g_path = GetFullPath(DEFAULT_TEST_PATH);
132 EXPECT_NE("", g_path);
133 g_path += "utresources";
134 }
135
136 /**
137 * @tc.name: network plugin
138 * @tc.desc: Test whether the utresource path exists.
139 * @tc.type: FUNC
140 */
141 HWTEST_F(NetworkPluginTest, Testpath, TestSize.Level1)
142 {
143 EXPECT_NE(g_path, "");
144 }
145
146 /**
147 * @tc.name: network plugin
148 * @tc.desc: No network data for specific pid.
149 * @tc.type: FUNC
150 */
151 HWTEST_F(NetworkPluginTest, TestNetworkDataNull, TestSize.Level1)
152 {
153 NetworkPlugin plugin;
154 NetworkDatas networkData;
155 plugin.setPathForTest(g_path + std::string("/begin"));
156
157 std::vector<int> pidList = {g_expectBegin.pid};
158 NetworkConfig config;
159 EXPECT_TRUE(SetConfig(pidList, config));
160 EXPECT_TRUE(PluginStub(plugin, networkData, config));
161
162 for (uint32_t i = 0; i < pidList.size(); ++i) {
163 EXPECT_EQ(g_expectBegin.uid, plugin.GetUid(pidList[i]));
164 EXPECT_EQ(g_expectBegin.rx, networkData.mutable_networkinfo(i)->rx_bytes());
165 EXPECT_EQ(g_expectBegin.tx, networkData.mutable_networkinfo(i)->tx_bytes());
166 int index = networkData.mutable_networkinfo(i)->details_size();
167 EXPECT_EQ(index, 0);
168 }
169
170 // stop
171 plugin.Stop();
172 }
173
174 /**
175 * @tc.name: network plugin
176 * @tc.desc: get network data for specific pid.
177 * @tc.type: FUNC
178 */
179 HWTEST_F(NetworkPluginTest, TestGetNetworkData, TestSize.Level1)
180 {
181 NetworkPlugin plugin;
182 NetworkDatas networkData;
183 plugin.setPathForTest(g_path + std::string("/end"));
184
185 std::vector<int> pidList = {g_expectEnd.pid};
186 NetworkConfig config;
187 EXPECT_TRUE(SetConfig(pidList, config));
188 EXPECT_TRUE(PluginStub(plugin, networkData, config));
189
190 for (uint32_t i = 0; i < pidList.size(); ++i) {
191 EXPECT_EQ(g_expectEnd.uid, plugin.GetUid(pidList[i]));
192 EXPECT_EQ(g_expectEnd.rx, networkData.mutable_networkinfo(i)->rx_bytes());
193 EXPECT_EQ(g_expectEnd.tx, networkData.mutable_networkinfo(i)->tx_bytes());
194 int index = networkData.mutable_networkinfo(i)->details_size();
195 EXPECT_EQ(index, 1);
196 for (int j = 0; j < index; ++j) {
197 EXPECT_EQ(g_expectEnd.details[j].tx, networkData.mutable_networkinfo(i)->mutable_details(j)->tx_bytes());
198 EXPECT_EQ(g_expectEnd.details[j].rx, networkData.mutable_networkinfo(i)->mutable_details(j)->rx_bytes());
199 EXPECT_EQ(g_expectEnd.details[j].type, networkData.mutable_networkinfo(i)->mutable_details(j)->type());
200 }
201 }
202
203 // stop
204 plugin.Stop();
205 }
206
207 /**
208 * @tc.name: network plugin
209 * @tc.desc: test the ParseFromArray fail of plugin start
210 * @tc.type: FUNC
211 */
212 HWTEST_F(NetworkPluginTest, TestParseFromArrayOfPluginStart, TestSize.Level1)
213 {
214 NetworkPlugin plugin;
215 NetworkConfig config;
216 int32_t pid = 1;
217
218 // set config
219 config.add_pid(pid);
220
221 // serialize
222 int size = config.ByteSizeLong();
223 ASSERT_GT(size, 0);
224 std::vector<uint8_t> configData(size);
225 ASSERT_GT(config.SerializeToArray(configData.data(), configData.size()), 0);
226
227 // start
228 EXPECT_NE(plugin.Start(configData.data(), size - 1), 0);
229 }
230
WriteFunc(WriterStruct * writer,const void * data,size_t size)231 long WriteFunc(WriterStruct* writer, const void* data, size_t size)
232 {
233 if (writer == nullptr || data == nullptr || size <= 0) {
234 return -1;
235 }
236 return 0;
237 }
238
FlushFunc(WriterStruct * writer)239 bool FlushFunc(WriterStruct* writer)
240 {
241 if (writer == nullptr) {
242 return false;
243 }
244 return true;
245 }
246
247 /**
248 * @tc.name: network plugin
249 * @tc.desc: test register
250 * @tc.type: FUNC
251 */
252 HWTEST_F(NetworkPluginTest, TestRegister, TestSize.Level1)
253 {
254 std::string path = DEFAULT_SO_PATH + std::string("libnetworkplugin.z.so");
255 void* handle = dlopen(path.c_str(), RTLD_LAZY);
256 EXPECT_NE(handle, nullptr);
257 PluginModuleStruct* plugin = reinterpret_cast<PluginModuleStruct*>(dlsym(handle, "g_pluginModule"));
258 EXPECT_NE(plugin, nullptr);
259 EXPECT_STREQ(plugin->name, "network-plugin");
260
261 // set config
262 NetworkConfig config;
263 int32_t pid = 1;
264 config.add_pid(pid);
265 int size = config.ByteSizeLong();
266 ASSERT_GT(size, 0);
267 std::vector<uint8_t> configData(size);
268 ASSERT_GT(config.SerializeToArray(configData.data(), configData.size()), 0);
269
270 // test framework process
271 WriterStruct writer = {WriteFunc, FlushFunc};
272 std::vector<uint8_t> dataBuffer(plugin->resultBufferSizeHint);
273 EXPECT_EQ(plugin->callbacks->onRegisterWriterStruct(&writer), 0);
274 }
275
276 /**
277 * @tc.name: network plugin
278 * @tc.desc: Framework test
279 * @tc.type: FUNC
280 */
281 HWTEST_F(NetworkPluginTest, TestFramework, TestSize.Level1)
282 {
283 std::string path = DEFAULT_SO_PATH + std::string("libnetworkplugin.z.so");
284 void* handle = dlopen(path.c_str(), RTLD_LAZY);
285 EXPECT_NE(handle, nullptr);
286 PluginModuleStruct* plugin = reinterpret_cast<PluginModuleStruct*>(dlsym(handle, "g_pluginModule"));
287 EXPECT_NE(plugin, nullptr);
288 EXPECT_STREQ(plugin->name, "network-plugin");
289
290 // set config
291 NetworkConfig config;
292 int32_t pid = 1;
293 config.add_pid(pid);
294 int size = config.ByteSizeLong();
295 ASSERT_GT(size, 0);
296 std::vector<uint8_t> configData(size);
297 ASSERT_GT(config.SerializeToArray(configData.data(), configData.size()), 0);
298
299 // test framework process
300 std::vector<uint8_t> dataBuffer(plugin->resultBufferSizeHint);
301 EXPECT_EQ(plugin->callbacks->onPluginSessionStart(configData.data(), configData.size()), 0);
302 if (access(DEFAULT_NET_PATH.c_str(), F_OK) != 0) {
303 EXPECT_LT(plugin->callbacks->onPluginReportResult(dataBuffer.data(), dataBuffer.size()), 0);
304 } else {
305 EXPECT_EQ(plugin->callbacks->onPluginReportResult(dataBuffer.data(), dataBuffer.size()), 0);
306 }
307 EXPECT_EQ(plugin->callbacks->onPluginSessionStop(), 0);
308 }
309 } // namespace
310