• 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 <hwext/gtest-ext.h>
17 #include <hwext/gtest-tag.h>
18 #include <dlfcn.h>
19 
20 #include "diskio_data_plugin.h"
21 #include "plugin_module_api.h"
22 
23 using namespace testing::ext;
24 
25 namespace {
26 const std::string DEFAULT_TEST_PATH = "/data/local/tmp/resources";
27 const std::string SO_PATH = "/system/lib/libdiskiodataplugin.z.so";
28 const std::string DEFAULT_BIN_PATH("/data/local/tmp/diskiodataplugintest");
29 constexpr uint32_t BUF_SIZE = 4 * 1024 * 1024;
30 constexpr int WRITE_KB = 1000;
31 
32 std::string g_path;
33 std::string g_testPath;
34 
35 struct TestVmstat {
36     int64_t pgpgin;
37     int64_t pgpgout;
38 };
39 
40 TestVmstat g_vmStat = {2072559, 27543064};
41 
42 class DiskioDataPluginTest : public ::testing::Test {
43 public:
SetUpTestCase()44     static void SetUpTestCase() {}
45 
TearDownTestCase()46     static void TearDownTestCase()
47     {
48         if (access(g_testPath.c_str(), F_OK) == 0) {
49             std::string str = "rm -rf " + g_testPath;
50             system(str.c_str());
51         }
52     }
53 };
54 
Getexepath()55 string Getexepath()
56 {
57     char buf[PATH_MAX] = "";
58     std::string path = "/proc/self/exe";
59     size_t rslt = readlink(path.c_str(), buf, sizeof(buf));
60     if (rslt < 0 || (rslt >= sizeof(buf))) {
61         return "";
62     }
63     buf[rslt] = '\0';
64     for (int i = rslt; i >= 0; i--) {
65         if (buf[i] == '/') {
66             buf[i + 1] = '\0';
67             break;
68         }
69     }
70     return buf;
71 }
72 
GetFullPath(std::string path)73 std::string GetFullPath(std::string path)
74 {
75     if (path.size() > 0 && path[0] != '/') {
76         return Getexepath() + path;
77     }
78     return path;
79 }
80 
PluginDiskioInfoStub(DiskioDataPlugin & diskioPlugin,DiskioData & diskioData,bool unusualBuff)81 bool PluginDiskioInfoStub(DiskioDataPlugin& diskioPlugin, DiskioData& diskioData, bool unusualBuff)
82 {
83     DiskioConfig protoConfig;
84     std::vector<uint8_t> configData(protoConfig.ByteSizeLong());
85     int ret = protoConfig.SerializeToArray(configData.data(), configData.size());
86     if (ret < 0) {
87         return false;
88     }
89 
90     // start
91     ret = diskioPlugin.Start(configData.data(), configData.size());
92     if (ret < 0) {
93         return false;
94     }
95 
96     // report
97     std::vector<uint8_t> bufferData(BUF_SIZE);
98     if (unusualBuff) { // buffer异常,调整缓冲区长度为1,测试异常情况
99         bufferData.resize(1, 0);
100     }
101 
102     ret = diskioPlugin.Report(bufferData.data(), bufferData.size());
103     if (ret > 0) {
104         diskioData.ParseFromArray(bufferData.data(), ret);
105         return true;
106     }
107     return false;
108 }
109 
110 /**
111  * @tc.name: diskio plugin
112  * @tc.desc: Test whether the path exists.
113  * @tc.type: FUNC
114  */
115 HWTEST_F(DiskioDataPluginTest, TestPath, TestSize.Level1)
116 {
117     g_path = GetFullPath(DEFAULT_TEST_PATH);
118     g_testPath = g_path;
119     EXPECT_NE("", g_path);
120     g_path += "/proc/vmstat";
121 }
122 
123 /**
124  * @tc.name: diskio plugin
125  * @tc.desc: diskio information test for specific path.
126  * @tc.type: FUNC
127  */
128 HWTEST_F(DiskioDataPluginTest, TestPlugin, TestSize.Level1)
129 {
130     DiskioDataPlugin diskioPlugin;
131     DiskioData diskioData;
132     diskioPlugin.SetPath(g_path);
133 
134     EXPECT_TRUE(PluginDiskioInfoStub(diskioPlugin, diskioData, false));
135     EXPECT_EQ(diskioData.prev_rd_sectors_kb(), 0);
136     EXPECT_EQ(diskioData.prev_wr_sectors_kb(), 0);
137     EXPECT_EQ(diskioData.rd_sectors_kb(), g_vmStat.pgpgin);
138     EXPECT_EQ(diskioData.wr_sectors_kb(), g_vmStat.pgpgout);
139 
140     EXPECT_EQ(diskioPlugin.Stop(), 0);
141 
142     // 缓冲区异常
143     EXPECT_FALSE(PluginDiskioInfoStub(diskioPlugin, diskioData, true));
144     EXPECT_EQ(diskioPlugin.Stop(), 0);
145 }
146 
147 /**
148  * @tc.name: diskio plugin
149  * @tc.desc: diskio information test for unusual path.
150  * @tc.type: FUNC
151  */
152 HWTEST_F(DiskioDataPluginTest, TestPluginBoundary, TestSize.Level1)
153 {
154     DiskioDataPlugin diskioPlugin;
155     DiskioData diskioData;
156     diskioPlugin.SetPath("123");
157     EXPECT_FALSE(PluginDiskioInfoStub(diskioPlugin, diskioData, false));
158     diskioPlugin.Stop();
159 }
160 
161 /**
162  * @tc.name: diskio plugin
163  * @tc.desc: diskio plugin registration test.
164  * @tc.type: FUNC
165  */
166 HWTEST_F(DiskioDataPluginTest, TestPluginRegister, TestSize.Level1)
167 {
168     void* handle = dlopen(SO_PATH.c_str(), RTLD_LAZY);
169     ASSERT_NE(handle, nullptr);
170     PluginModuleStruct* diskioPlugin = (PluginModuleStruct*)dlsym(handle, "g_pluginModule");
171     ASSERT_NE(diskioPlugin, nullptr);
172     EXPECT_STREQ(diskioPlugin->name, "diskio-plugin");
173     EXPECT_EQ(diskioPlugin->resultBufferSizeHint, BUF_SIZE);
174 
175     // Serialize config
176     DiskioConfig protoConfig;
177     int configLength = protoConfig.ByteSizeLong();
178     ASSERT_EQ(configLength, 0);
179     std::vector<uint8_t> configBuffer(configLength);
180     EXPECT_TRUE(protoConfig.SerializeToArray(configBuffer.data(), configLength));
181 
182     // run plugin
183     std::vector<uint8_t> dataBuffer(diskioPlugin->resultBufferSizeHint);
184     EXPECT_EQ(diskioPlugin->callbacks->onPluginSessionStart(configBuffer.data(), configLength), RET_SUCC);
185     ASSERT_GT(diskioPlugin->callbacks->onPluginReportResult(dataBuffer.data(), diskioPlugin->resultBufferSizeHint), 0);
186     EXPECT_EQ(diskioPlugin->callbacks->onPluginSessionStop(), RET_SUCC);
187 
188     // 反序列化失败导致的start失败
189     configLength++;
190     std::vector<uint8_t> configBuffer2(configLength);
191     EXPECT_TRUE(protoConfig.SerializeToArray(configBuffer2.data(), configLength));
192     EXPECT_EQ(diskioPlugin->callbacks->onPluginSessionStart(configBuffer2.data(), configLength+1), RET_FAIL);
193 }
194 
ExecuteBin(const std::string & bin,const std::vector<std::string> & args)195 bool ExecuteBin(const std::string& bin, const std::vector<std::string>& args)
196 {
197     std::vector<char*> argv;
198     for (size_t i = 0; i < args.size(); i++) {
199         argv.push_back(const_cast<char*>(args[i].c_str()));
200     }
201     argv.push_back(nullptr); // last item in argv must be NULL
202 
203     int retval = execvp(bin.c_str(), argv.data());
204     CHECK_TRUE(retval != -1, false, "execv %s failed, %d!", bin.c_str(), errno);
205     _exit(EXIT_FAILURE);
206     abort(); // never should be here.
207     return true;
208 }
209 
210 /**
211  * @tc.name: diskio plugin
212  * @tc.desc: test ParseDiskioInfo for system file
213  * @tc.type: FUNC
214  */
215 HWTEST_F(DiskioDataPluginTest, TestSystemFile, TestSize.Level1)
216 {
217     DiskioDataPlugin plugin1, plugin2;
218     DiskioData diskioData1, diskioData2;
219 
220     std::string cmd = "chmod 777 " + DEFAULT_BIN_PATH;
221     system(cmd.c_str());
222 
223     EXPECT_TRUE(PluginDiskioInfoStub(plugin1, diskioData1, false));
224     pid_t pid = fork();
225     if (pid == 0) {
226         // set 1, write data to disk
227         std::vector<std::string> argv = {"childpidtest", "1"};
228         ASSERT_TRUE(ExecuteBin(DEFAULT_BIN_PATH, argv));
229     }
230     sleep(1); // 睡眠1s,确保已写入磁盘1000kb的数据
231     EXPECT_TRUE(PluginDiskioInfoStub(plugin2, diskioData2, false));
232     EXPECT_LE(diskioData1.wr_sectors_kb() + WRITE_KB, diskioData2.wr_sectors_kb());
233 
234     while (waitpid(-1, NULL, WNOHANG) == 0) {
235         kill(pid, SIGKILL);
236     }
237 
238     plugin1.Stop();
239     plugin2.Stop();
240 }
241 } // namespace
242