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 28using namespace testing::ext; 29 30namespace { 31constexpr int DEAFULT_FILE_MODE = 0777; 32 33#if defined(__i386__) || defined(__x86_64__) 34const std::string DEFAULT_TEST_PATH = "./"; 35#else 36const std::string DEFAULT_TEST_PATH_1 = "/data/local/tmp/watchertest/1/"; 37const std::string DEFAULT_TEST_PATH_2 = "/data/local/tmp/watchertest/2/"; 38const std::string DEFAULT_TEST_PATH_3 = "/data/local/tmp/watchertest/3/"; 39const std::string NO_EXIST_TEST_PATH = "/data/local/tmp/noexist/"; 40#endif 41 42class PluginWatchTest : public ::testing::Test { 43protected: 44 static constexpr int TEMP_DELAY = 10 * 1000; 45 static void SetUpTestCase() {} 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 64 void OnPluginAddedStub(const std::string& path) 65 { 66 cmpFileList.push_back(path); 67 sort(cmpFileList.begin(), cmpFileList.end()); 68 } 69 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 80 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 90 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 102 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 116 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 131private: 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 148class MockPluginWatcher : public PluginWatcher { 149public: 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 */ 161HWTEST_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 */ 188HWTEST_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 */ 236HWTEST_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