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