1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
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 <fcntl.h>
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <vector>
22
23 #include "plugin_manager.h"
24 #include "plugin_watcher.h"
25
26 #include "logging.h"
27
28 using namespace testing::ext;
29
30 namespace {
31 constexpr int DEAFULT_FILE_MODE = 0777;
32
33 #if defined(__i386__) || defined(__x86_64__)
34 const std::string DEFAULT_TEST_PATH = "./";
35 #else
36 const std::string DEFAULT_TEST_PATH_1 = "/data/local/tmp/watchertest/1/";
37 const std::string DEFAULT_TEST_PATH_2 = "/data/local/tmp/watchertest/2/";
38 const std::string DEFAULT_TEST_PATH_3 = "/data/local/tmp/watchertest/3/";
39 const std::string NO_EXIST_TEST_PATH = "/data/local/tmp/noexist/";
40 #endif
41
42 class PluginWatchTest : public ::testing::Test {
43 protected:
44 static constexpr int TEMP_DELAY = 10 * 1000;
SetUpTestCase()45 static void SetUpTestCase() {}
TearDownTestCase()46 static void TearDownTestCase() {}
47
48 void SetUp() override
49 {
50 std::string cmd = "mkdir -p " + DEFAULT_TEST_PATH_1;
51 system(cmd.c_str());
52 cmd = "mkdir -p " + DEFAULT_TEST_PATH_2;
53 system(cmd.c_str());
54 cmd = "mkdir -p " + DEFAULT_TEST_PATH_3;
55 system(cmd.c_str());
56 sort(expectFileList.begin(), expectFileList.end());
57 }
58
59 void TearDown() override
60 {
61 cmpFileList.clear();
62 }
63
OnPluginAddedStub(const std::string& path)64 void OnPluginAddedStub(const std::string& path)
65 {
66 cmpFileList.push_back(path);
67 sort(cmpFileList.begin(), cmpFileList.end());
68 }
69
OnPluginRemovedStub(const std::string& path)70 void OnPluginRemovedStub(const std::string& path)
71 {
72 for (auto iter = cmpFileList.cbegin(); iter != cmpFileList.cend(); iter++) {
73 if (*iter == path) {
74 cmpFileList.erase(iter);
75 break;
76 }
77 }
78 }
79
CreateFile(std::string dirPath) const80 void CreateFile(std::string dirPath) const
81 {
82 for (auto it : createFileList) {
83 int fd = creat((dirPath + it).c_str(), DEAFULT_FILE_MODE);
84 if (fd > 0) {
85 close(fd);
86 }
87 }
88 }
89
AddFile(std::string dirPath) const90 void AddFile(std::string dirPath) const
91 {
92 for (auto it : addFileList) {
93 int fd = creat((dirPath + it).c_str(), DEAFULT_FILE_MODE);
94 if (fd < 0) {
95 return;
96 }
97 write(fd, "testcase", 1);
98 close(fd);
99 }
100 }
101
DeleteFile(std::string dirPath) const102 void DeleteFile(std::string dirPath) const
103 {
104 for (auto it : createFileList) {
105 if (remove((dirPath + it).c_str()) != 0) {
106 return;
107 }
108 }
109 for (auto it : addFileList) {
110 if (remove((dirPath + it).c_str()) != 0) {
111 return;
112 }
113 }
114 }
115
CheckFileList(std::string dirPath) const116 bool CheckFileList(std::string dirPath) const
117 {
118 if (cmpFileList.size() != expectFileList.size()) {
119 return false;
120 }
121
122 for (size_t i = 0; i < cmpFileList.size(); i++) {
123 if (cmpFileList.at(i) != (dirPath + expectFileList.at(i))) {
124 return false;
125 }
126 }
127
128 return true;
129 }
130
131 private:
132 std::vector<std::string> cmpFileList;
133
134 const std::vector<std::string> createFileList = {
135 "lib_6.so", "lib_5.so", "lib_8.so", "lib_4.so", "test1.txt"
136 };
137
138 const std::vector<std::string> addFileList = {
139 "libadd_6.so", "libadd_5.so", "libadd_8.so", "libadd_4.so", "test2.txt"
140 };
141
142 std::vector<std::string> expectFileList = {
143 "libadd_6.so", "libadd_5.so", "libadd_8.so", "libadd_4.so",
144 "lib_6.so", "lib_5.so", "lib_8.so", "lib_4.so"
145 };
146 };
147
148 class MockPluginWatcher : public PluginWatcher {
149 public:
MockPluginWatcher(const PluginManagerPtr& pluginManager)150 explicit MockPluginWatcher(const PluginManagerPtr& pluginManager) : PluginWatcher(pluginManager) {}
151 ~MockPluginWatcher() = default;
152 MOCK_METHOD1(OnPluginAdded, void(const std::string&));
153 MOCK_METHOD1(OnPluginRemoved, void(const std::string&));
154 };
155
156 /**
157 * @tc.name: plugin
158 * @tc.desc: Monitor single plugin dir.
159 * @tc.type: FUNC
160 */
HWTEST_F(PluginWatchTest, SingleWatchDirTest, TestSize.Level1)161 HWTEST_F(PluginWatchTest, SingleWatchDirTest, TestSize.Level1)
162 {
163 auto pluginManage = std::make_shared<PluginManager>();
164 MockPluginWatcher watcher(pluginManage);
165
166 EXPECT_CALL(watcher, OnPluginAdded(testing::_)).WillRepeatedly(
167 testing::Invoke(this, &PluginWatchTest::OnPluginAddedStub));
168 EXPECT_CALL(watcher, OnPluginRemoved(testing::_)).WillRepeatedly(
169 testing::Invoke(this, &PluginWatchTest::OnPluginRemovedStub));
170 CreateFile(DEFAULT_TEST_PATH_1);
171
172 EXPECT_TRUE(watcher.ScanPlugins(DEFAULT_TEST_PATH_1));
173 EXPECT_TRUE(watcher.WatchPlugins(DEFAULT_TEST_PATH_1));
174 usleep(TEMP_DELAY);
175 AddFile(DEFAULT_TEST_PATH_1);
176 usleep(TEMP_DELAY);
177 EXPECT_EQ(CheckFileList(DEFAULT_TEST_PATH_1), true);
178 DeleteFile(DEFAULT_TEST_PATH_1);
179 usleep(TEMP_DELAY);
180 EXPECT_EQ(cmpFileList.size(), 0);
181 }
182
183 /**
184 * @tc.name: plugin
185 * @tc.desc: Monitor multi plugin dir.
186 * @tc.type: FUNC
187 */
HWTEST_F(PluginWatchTest, MultiWatchDirTest, TestSize.Level1)188 HWTEST_F(PluginWatchTest, MultiWatchDirTest, TestSize.Level1)
189 {
190 auto pluginManage = std::make_shared<PluginManager>();
191 MockPluginWatcher watcher(pluginManage);
192
193 EXPECT_CALL(watcher, OnPluginAdded(testing::_)).WillRepeatedly(
194 testing::Invoke(this, &PluginWatchTest::OnPluginAddedStub));
195 EXPECT_CALL(watcher, OnPluginRemoved(testing::_)).WillRepeatedly(
196 testing::Invoke(this, &PluginWatchTest::OnPluginRemovedStub));
197 CreateFile(DEFAULT_TEST_PATH_1);
198 EXPECT_TRUE(watcher.ScanPlugins(DEFAULT_TEST_PATH_1));
199 EXPECT_TRUE(watcher.WatchPlugins(DEFAULT_TEST_PATH_1));
200 usleep(TEMP_DELAY);
201 AddFile(DEFAULT_TEST_PATH_1);
202 usleep(TEMP_DELAY);
203 EXPECT_EQ(CheckFileList(DEFAULT_TEST_PATH_1), true);
204 DeleteFile(DEFAULT_TEST_PATH_1);
205 usleep(TEMP_DELAY);
206 EXPECT_EQ(cmpFileList.size(), 0);
207
208 CreateFile(DEFAULT_TEST_PATH_2);
209 EXPECT_TRUE(watcher.ScanPlugins(DEFAULT_TEST_PATH_2));
210 EXPECT_TRUE(watcher.WatchPlugins(DEFAULT_TEST_PATH_2));
211 usleep(TEMP_DELAY);
212 AddFile(DEFAULT_TEST_PATH_2);
213 usleep(TEMP_DELAY);
214 EXPECT_EQ(CheckFileList(DEFAULT_TEST_PATH_2), true);
215 DeleteFile(DEFAULT_TEST_PATH_2);
216 usleep(TEMP_DELAY);
217 EXPECT_EQ(cmpFileList.size(), 0);
218
219 CreateFile(DEFAULT_TEST_PATH_3);
220 EXPECT_TRUE(watcher.ScanPlugins(DEFAULT_TEST_PATH_3));
221 EXPECT_TRUE(watcher.WatchPlugins(DEFAULT_TEST_PATH_3));
222 usleep(TEMP_DELAY);
223 AddFile(DEFAULT_TEST_PATH_3);
224 usleep(TEMP_DELAY);
225 EXPECT_EQ(CheckFileList(DEFAULT_TEST_PATH_3), true);
226 DeleteFile(DEFAULT_TEST_PATH_3);
227 usleep(TEMP_DELAY);
228 EXPECT_EQ(cmpFileList.size(), 0);
229 }
230
231 /**
232 * @tc.name: plugin
233 * @tc.desc: Exception test.
234 * @tc.type: FUNC
235 */
HWTEST_F(PluginWatchTest, ExceptionTest, TestSize.Level1)236 HWTEST_F(PluginWatchTest, ExceptionTest, TestSize.Level1)
237 {
238 auto pluginManage = std::make_shared<PluginManager>();
239 MockPluginWatcher watcher(pluginManage);
240 EXPECT_FALSE(watcher.ScanPlugins(NO_EXIST_TEST_PATH));
241 EXPECT_FALSE(watcher.WatchPlugins(NO_EXIST_TEST_PATH));
242 }
243 } // namespace
244