From: Sangwan Kwon Date: Fri, 8 Nov 2019 06:20:40 +0000 (+0900) Subject: Reorganize directory structure X-Git-Tag: submit/tizen/20200810.073515~163 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1426e7d6fce82138635eb9b0ab2f0edb57186f46;p=platform%2Fcore%2Fsecurity%2Fvist.git Reorganize directory structure Signed-off-by: Sangwan Kwon --- diff --git a/plugins/bluetooth/bluetooth.cpp b/plugins/bluetooth/bluetooth.cpp index 0caa39e..32da9bb 100644 --- a/plugins/bluetooth/bluetooth.cpp +++ b/plugins/bluetooth/bluetooth.cpp @@ -18,8 +18,8 @@ #include #include -#include -#include +#include +#include #include diff --git a/plugins/wifi/wifi.cpp b/plugins/wifi/wifi.cpp index 95ca32e..5dff58f 100644 --- a/plugins/wifi/wifi.cpp +++ b/plugins/wifi/wifi.cpp @@ -17,8 +17,8 @@ #include #include -#include -#include +#include +#include #include diff --git a/src/vist/CMakeLists.txt b/src/vist/CMakeLists.txt index fb12f6f..26157a9 100644 --- a/src/vist/CMakeLists.txt +++ b/src/vist/CMakeLists.txt @@ -31,6 +31,7 @@ ADD_DEFINITIONS(-DDB_PATH="${DB_INSTALL_DIR}/.vist.db" ADD_SUBDIRECTORY(client) ADD_SUBDIRECTORY(notification) ADD_SUBDIRECTORY(policy) +ADD_SUBDIRECTORY(sdk) ADD_SUBDIRECTORY(service) ADD_LIBRARY(${TARGET_VIST_LIB} STATIC ${${TARGET_VIST_LIB}_SRCS}) diff --git a/src/vist/policy/CMakeLists.txt b/src/vist/policy/CMakeLists.txt index fc29790..5387a8e 100644 --- a/src/vist/policy/CMakeLists.txt +++ b/src/vist/policy/CMakeLists.txt @@ -17,19 +17,16 @@ SET(${TARGET_VIST_POLICY_LIB}_SRCS "") PKG_CHECK_MODULES(VIST_POLICY_DEPS REQUIRED klay dlog) -INCLUDE_DIRECTORIES(SYSTEM . common ${VIST_POLICY_DEPS_INCLUDE_DIRS}) +INCLUDE_DIRECTORIES(SYSTEM . ${VIST_POLICY_DEPS_INCLUDE_DIRS}) -ADD_VIST_POLICY_LIBRARY(vist_policy_core core/api.cpp - core/policy-manager.cpp - core/policy-loader.cpp - core/policy-storage.cpp) +ADD_VIST_POLICY_LIBRARY(vist_policy_core api.cpp + policy-manager.cpp + policy-loader.cpp + policy-storage.cpp) -FILE(GLOB POLICY_CORE_TESTS "core/tests/*.cpp") +FILE(GLOB POLICY_CORE_TESTS "tests/*.cpp") ADD_VIST_TEST(${POLICY_CORE_TESTS}) -FILE(GLOB POLICY_SDK_TESTS "sdk/tests/*.cpp") -ADD_VIST_TEST(${POLICY_SDK_TESTS}) - ADD_LIBRARY(${TARGET_VIST_POLICY_LIB} STATIC ${${TARGET_VIST_POLICY_LIB}_SRCS}) TARGET_LINK_LIBRARIES(${TARGET_VIST_POLICY_LIB} ${VIST_POLICY_DEPS_LIBRARIES} pthread diff --git a/src/vist/policy/api.cpp b/src/vist/policy/api.cpp new file mode 100644 index 0000000..0a38eb5 --- /dev/null +++ b/src/vist/policy/api.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include + +#include "policy-manager.hpp" + +namespace vist { +namespace policy { + +PolicyValue API::Get(const std::string& policy) +{ + return PolicyManager::Instance().get(policy); +} + +std::unordered_map API::GetAll() +{ + return PolicyManager::Instance().getAll(); +} + +void API::Admin::Set(const std::string& policy, const PolicyValue& value) +{ + // TODO(Sangwan): Get admin name from peer PID + PolicyManager::Instance().set(policy, value, "admin"); +} + +void API::Admin::Enroll(const std::string& admin) +{ + PolicyManager::Instance().enroll(admin); +} + +void API::Admin::Disenroll(const std::string& admin) +{ + PolicyManager::Instance().disenroll(admin); +} + +std::vector API::Admin::GetAll() +{ + return PolicyManager::Instance().getAdmins(); +} + +} // namespace policy +} // namespace vist diff --git a/src/vist/policy/api.hpp b/src/vist/policy/api.hpp index bd8aa91..6c15af8 100644 --- a/src/vist/policy/api.hpp +++ b/src/vist/policy/api.hpp @@ -16,7 +16,7 @@ #pragma once -#include +#include #include #include diff --git a/src/vist/policy/core/api.cpp b/src/vist/policy/core/api.cpp deleted file mode 100644 index 0a38eb5..0000000 --- a/src/vist/policy/core/api.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -#include - -#include "policy-manager.hpp" - -namespace vist { -namespace policy { - -PolicyValue API::Get(const std::string& policy) -{ - return PolicyManager::Instance().get(policy); -} - -std::unordered_map API::GetAll() -{ - return PolicyManager::Instance().getAll(); -} - -void API::Admin::Set(const std::string& policy, const PolicyValue& value) -{ - // TODO(Sangwan): Get admin name from peer PID - PolicyManager::Instance().set(policy, value, "admin"); -} - -void API::Admin::Enroll(const std::string& admin) -{ - PolicyManager::Instance().enroll(admin); -} - -void API::Admin::Disenroll(const std::string& admin) -{ - PolicyManager::Instance().disenroll(admin); -} - -std::vector API::Admin::GetAll() -{ - return PolicyManager::Instance().getAdmins(); -} - -} // namespace policy -} // namespace vist diff --git a/src/vist/policy/core/db-schema.hpp b/src/vist/policy/core/db-schema.hpp deleted file mode 100644 index 2bdf75b..0000000 --- a/src/vist/policy/core/db-schema.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -#pragma once - -#include - -namespace vist { -namespace policy { -namespace schema { - -struct Admin { - std::string name; -}; - -struct PolicyActivated { - std::string admin; - std::string policy; - int value = -1; -}; - -struct PolicyDefinition { - std::string name; - int ivalue = -1; -}; - -} // namespace schema -} // namespace policy -} // namespace vist diff --git a/src/vist/policy/core/policy-loader.cpp b/src/vist/policy/core/policy-loader.cpp deleted file mode 100644 index 28c3b41..0000000 --- a/src/vist/policy/core/policy-loader.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -#include "policy-loader.hpp" - -namespace vist { -namespace policy { - -PolicyProvider* PolicyLoader::load(const std::string& path) -{ - PluginLoader loader(path); - PolicyProvider::FactoryType factory = nullptr; - loader.load(PolicyProvider::getFactoryName(), factory); - if (factory == nullptr) - std::runtime_error("Failed to load symbol. " + PolicyProvider::getFactoryName()); - - auto provider = (*factory)(); - if (provider == nullptr) - std::runtime_error("Failed to make provider. " + PolicyProvider::getFactoryName()); - - return provider; -} - -PluginLoader::PluginLoader(const std::string& path, int flag) - : handle(::dlopen(path.c_str(), flag), [](void*)->int{return 0;}) -// Cleaning object after dlclose() makes SEGFAULT. -// TODO: Sync dynamic loading's life-cycle with program.(PluginManager) -// : handle(::dlopen(path.c_str(), flag), ::dlclose) -{ - if (handle == nullptr) - throw std::invalid_argument("Failed to open: " + path); -} - -} // namespace policy -} // namespace vist diff --git a/src/vist/policy/core/policy-loader.hpp b/src/vist/policy/core/policy-loader.hpp deleted file mode 100644 index b463fd6..0000000 --- a/src/vist/policy/core/policy-loader.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -#pragma once - -#include - -#include -#include -#include - -#include - -namespace vist { -namespace policy { - -struct PolicyLoader final { - static PolicyProvider* load(const std::string& path); -}; - -class PluginLoader final { -public: - explicit PluginLoader(const std::string& path, int flag = RTLD_LAZY); - - template - void load(const std::string& name, T& symbol); - -private: - using Handle = std::unique_ptr; - Handle handle; -}; - -template -void PluginLoader::load(const std::string& name, T& symbol) -{ - symbol = reinterpret_cast(::dlsym(handle.get(), name.c_str())); - if (symbol == nullptr) - throw std::runtime_error("Failed to load: " + name); -} - -} // namespace policy -} // namespace vist diff --git a/src/vist/policy/core/policy-manager.cpp b/src/vist/policy/core/policy-manager.cpp deleted file mode 100644 index f1bd3e5..0000000 --- a/src/vist/policy/core/policy-manager.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -#include "policy-manager.hpp" -#include "policy-loader.hpp" - -#include - -#include - -namespace vist { -namespace policy { - -PolicyManager::PolicyManager() : storage(DB_PATH) -{ - loadProviders(PLUGIN_INSTALL_DIR); - int cnt = loadPolicies(); - INFO(VIST) << std::to_string(cnt) << "-policies loaded"; -} - -std::pair PolicyManager::loadProviders(const std::string& path) -{ - INFO(VIST) << "Load policies from :" << path; - klay::File dir(path); - if (!dir.exists() || !dir.isDirectory()) - throw std::invalid_argument("Plugin directory is wrong.: " + path); - - int passed = 0, failed = 0; - klay::DirectoryIterator end; - for (klay::DirectoryIterator iter(path); iter != end; ++iter) { - if (!iter->isFile()) - continue; - - try { - auto provider = PolicyLoader::load(iter->getPath()); - DEBUG(VIST) << "Loaded provider: " << provider->getName(); - - bool exist = false; - for (const auto& p : this->providers) { - if (p->getName() == provider->getName()) { - exist = true; - break; - } - } - - if (!exist) - this->providers.emplace_back(std::move(provider)); - } catch (const std::exception& e) { - ++failed; - ERROR(VIST) << "Failed to load: " << iter->getPath() << e.what(); - continue; - } - - ++passed; - } - - INFO(VIST) << "Loaded result >> passed: " << passed << ", failed: " << failed; - return std::make_pair(passed, failed); -} - -int PolicyManager::loadPolicies() -{ - bool changed = false; - - /// Make policy-provider map for performance - for (const auto& provider : providers) { - for (const auto& pair : provider->policies) { - policies[pair.first] = provider->getName(); - - /// Check the policy is defined on policy-storage - if (!storage.exists(pair.first)) { - INFO(VIST) << "Define policy: " << pair.first; - storage.define(pair.first, pair.second->getInitial().value); - changed = true; - } - } - } - - if (changed) - storage.syncPolicyDefinition(); - - return policies.size(); -} - -void PolicyManager::enroll(const std::string& admin) -{ - this->storage.enroll(admin); -} - -void PolicyManager::disenroll(const std::string& admin) -{ - this->storage.disenroll(admin); -} - -void PolicyManager::set(const std::string& policy, - const PolicyValue& value, - const std::string& admin) -{ - if (this->policies.find(policy) == this->policies.end()) - std::runtime_error("Not exist policy: " + policy); - - storage.update(admin, policy, value); - - for (auto& p : providers) { - if (p->getName() != this->policies[policy]) - continue; - - if (p->policies.find(policy) != p->policies.end()) { - p->policies[policy]->set(value); - return; - } - } -} - -PolicyValue PolicyManager::get(const std::string& policy) -{ - return storage.strictest(policy); -} - -std::unordered_map PolicyManager::getAll() -{ - return storage.strictest(); -} - -std::vector PolicyManager::getAdmins() -{ - return storage.getAdmins(); -} - -} // namespace policy -} // namespace vist diff --git a/src/vist/policy/core/policy-manager.hpp b/src/vist/policy/core/policy-manager.hpp deleted file mode 100644 index bdc364b..0000000 --- a/src/vist/policy/core/policy-manager.hpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -#pragma once - -#include -#include - -#include "policy-storage.hpp" - -#include -#include -#include -#include -#include - -#include - -namespace vist { -namespace policy { - -class PolicyManager final { -public: - PolicyManager(const PolicyManager&) = delete; - PolicyManager& operator=(const PolicyManager&) = delete; - - PolicyManager(PolicyManager&&) = delete; - PolicyManager& operator=(PolicyManager&&) = delete; - - static PolicyManager& Instance() - { - static PolicyManager manager; - return manager; - } - - void enroll(const std::string& admin); - void disenroll(const std::string& admin); - - void set(const std::string& policy, - const PolicyValue& value, - const std::string& admin); - PolicyValue get(const std::string& policy); - std::unordered_map getAll(); - - std::vector getAdmins(); - -private: - explicit PolicyManager(); - ~PolicyManager() = default; - - std::pair loadProviders(const std::string& path); - int loadPolicies(); - - PolicyStorage storage; - std::vector> providers; - - /// Policy-Provider - std::unordered_map policies; - - FRIEND_TEST(PolicyCoreTests, policy_loader); -}; - -} // namespace policy -} // namespace vist diff --git a/src/vist/policy/core/policy-storage.cpp b/src/vist/policy/core/policy-storage.cpp deleted file mode 100644 index 6cc3798..0000000 --- a/src/vist/policy/core/policy-storage.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -#include "policy-storage.hpp" - -#include -#include - -#include -#include -#include - -#include -#include - -using namespace vist::tsqb; -using namespace vist::policy::schema; - -namespace { - -auto adminTable = make_table("ADMIN", make_column("name", &Admin::name)); - -auto polActivatedTable = make_table("POLICY_ACTIVATED", - make_column("admin", &PolicyActivated::admin), - make_column("policy", &PolicyActivated::policy), - make_column("value", &PolicyActivated::value)); - -auto polDefinitionTable = make_table("POLICY_DEFINITION", - make_column("name", &PolicyDefinition::name), - make_column("ivalue", &PolicyDefinition::ivalue)); - -const std::string SCRIPT_BASE = SCRIPT_INSTALL_DIR; -const std::string SCRIPT_CREATE_SCHEMA = "create-schema"; - -} // anonymous namespace - -namespace vist { -namespace policy { - -PolicyStorage::PolicyStorage(const std::string& path) : - database(std::make_shared(path, - database::Connection::ReadWrite | - database::Connection::Create)) -{ - database->exec("PRAGMA foreign_keys = ON;"); - database->exec(getScript(SCRIPT_CREATE_SCHEMA)); - - sync(); -} - -void PolicyStorage::sync() -{ - DEBUG(VIST) << "Sync policy storage to cache object."; - syncAdmin(); - syncPolicyActivated(); - syncPolicyDefinition(); -} - -void PolicyStorage::syncPolicyDefinition() -{ - this->definitions.clear(); - std::string query = polDefinitionTable.selectAll(); - database::Statement stmt(*database, query); - - while (stmt.step()) { - PolicyDefinition pd; - pd.name = std::string(stmt.getColumn(0)); - pd.ivalue = stmt.getColumn(1); - DEBUG(VIST) << "Defined policy:" << pd.name; - this->definitions.emplace(pd.name, std::move(pd)); - } - - DEBUG(VIST) << definitions.size() << "- policies synced."; -} - -void PolicyStorage::syncAdmin() -{ - this->admins.clear(); - std::string query = adminTable.selectAll(); - database::Statement stmt(*database, query); - - while (stmt.step()) - this->admins.emplace_back(std::string(stmt.getColumn(0))); - - DEBUG(VIST) << admins.size() << "-admins synced."; -} - -void PolicyStorage::syncPolicyActivated() -{ - this->activatedPolicies.clear(); - std::string query = polActivatedTable.selectAll(); - database::Statement stmt(*database, query); - - while (stmt.step()) { - PolicyActivated pa; - pa.admin = std::string(stmt.getColumn(0)); - pa.policy = std::string(stmt.getColumn(1)); - pa.value = stmt.getColumn(2); - this->activatedPolicies.emplace(pa.policy, std::move(pa)); - } - - DEBUG(VIST) << activatedPolicies.size() << "- activated-policies synced."; -} - -std::string PolicyStorage::getScript(const std::string& name) -{ - std::string path = SCRIPT_BASE + "/" + name + ".sql"; - std::ifstream is(path); - if (is.fail()) - throw std::invalid_argument("Failed to open script: " + path); - - std::istreambuf_iterator begin(is), end; - auto content = std::string(begin, end); - if (content.empty()) - throw std::runtime_error("Failed to read script: " + path); - - return content; -} - -void PolicyStorage::define(const std::string& policy, int ivalue) -{ - if (definitions.find(policy) != definitions.end()) { - INFO(VIST) << "Policy is already defined: " << policy; - return; - } - - PolicyDefinition pd; - pd.name = policy; - pd.ivalue = ivalue; - - std::string query = polDefinitionTable.insert(&PolicyDefinition::name, - &PolicyDefinition::ivalue); - database::Statement stmt(*database, query); - stmt.bind(1, pd.name); - stmt.bind(2, pd.ivalue); - if (!stmt.exec()) - throw std::runtime_error("Failed to define policy: " + pd.name); -} - -void PolicyStorage::enroll(const std::string& name) -{ - INFO(VIST) << "Enroll admin: " << name; - if (std::find(admins.begin(), admins.end(), name) != admins.end()) { - ERROR(VIST) << "Admin is aleady enrolled.: " << name; - return; - } - - std::string query = adminTable.insert(&Admin::name); - DEBUG(VIST) << "Enroll admin query statement: " << query; - database::Statement stmt(*database, query); - stmt.bind(1, name); - if (!stmt.exec()) - throw std::runtime_error("Failed to enroll admin: " + name); - - admins.push_back(name); - /// PolicyActivated is triggered by enrolling admin. - syncPolicyActivated(); - - int count = activatedPolicies.size() / admins.size(); - INFO(VIST) << "Admin[" << name << "] manages " - << std::to_string(count) << "-policies."; -} - -void PolicyStorage::disenroll(const std::string& name) -{ - INFO(VIST) << "Disenroll admin: " << name; - auto iter = std::find(admins.begin(), admins.end(), name); - if (iter == admins.end()) { - ERROR(VIST) << "Not exist admin: " << name; - return; - } else { - admins.erase(iter); - } - - std::string query = adminTable.remove().where(expr(&Admin::name) == name); - database::Statement stmt(*database, query); - stmt.bind(1, name); - if (!stmt.exec()) - throw std::runtime_error("Failed to disenroll admin: " + name); -} - -void PolicyStorage::update(const std::string& admin, - const std::string& policy, - const PolicyValue& value) -{ - DEBUG(VIST) << "Policy-update is called by admin: " << admin - << ", about: " << policy << ", value: " << std::to_string(value); - - if (std::find(admins.begin(), admins.end(), admin) == admins.end()) - throw std::runtime_error("Not exist admin: " + admin); - - if (definitions.find(policy) == definitions.end()) - throw std::runtime_error("Not exist policy: " + policy); - - int policyValue = value; - std::string query = polActivatedTable.update(&PolicyActivated::value) - .where(expr(&PolicyActivated::admin) == admin && - expr(&PolicyActivated::policy) == policy); - database::Statement stmt(*database, query); - stmt.bind(1, policyValue); - stmt.bind(2, admin); - stmt.bind(3, policy); - if (!stmt.exec()) - throw runtime::Exception("Failed to update policy:" + policy); - - syncPolicyActivated(); -} - -PolicyValue PolicyStorage::strictest(const std::string& policy) -{ - if (definitions.find(policy) == definitions.end()) - throw std::runtime_error("Not exist policy: " + policy); - - // There is no enrolled admins. - if (activatedPolicies.size() == 0) - return PolicyValue(definitions[policy].ivalue); - - std::shared_ptr strictestPtr = nullptr; - auto range = activatedPolicies.equal_range(policy); - for (auto iter = range.first; iter != range.second; iter++) { - int value = iter->second.value; - if (strictestPtr == nullptr) - strictestPtr = std::make_shared(value); - else - strictestPtr->value = (*strictestPtr < value) ? strictestPtr->value : value; - - DEBUG(VIST) << "The strictest of policy[" << policy - << "] : " + std::to_string(strictestPtr->value); - } - - if (strictestPtr == nullptr) - throw std::runtime_error("Not exist managed policy: " + policy); - - return std::move(*strictestPtr); -} - -std::unordered_map PolicyStorage::strictest() -{ - std::unordered_map policies; - for (const auto& pair : definitions) { - std::string name = pair.first; - auto value = this->strictest(name); - - policies.emplace(std::move(name), std::move(value)); - } - - return policies; -} - -const std::vector& PolicyStorage::getAdmins() const noexcept -{ - return admins; -} - -} // namespace policy -} // namespace vist diff --git a/src/vist/policy/core/policy-storage.hpp b/src/vist/policy/core/policy-storage.hpp deleted file mode 100644 index cec538d..0000000 --- a/src/vist/policy/core/policy-storage.hpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * ttp://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -#pragma once - -#include - -#include "db-schema.hpp" - -#include -#include -#include - -#include - -namespace vist { -namespace policy { - -using namespace schema; - -class PolicyStorage final { -public: - explicit PolicyStorage(const std::string& path); - - /// TODO(Sangwan): Consider to support lazy sync - void sync(); - - void syncAdmin(); - void syncPolicyActivated(); - void syncPolicyDefinition(); - - inline bool exists(const std::string& policy) const noexcept - { - return definitions.find(policy) != definitions.end(); - } - - inline bool isActivated() const noexcept - { - return admins.size() > 0 && activatedPolicies.size() > 0; - } - - void enroll(const std::string& admin); - void disenroll(const std::string& admin); - - void define(const std::string& policy, int ivalue); - void update(const std::string& admin, - const std::string& policy, - const PolicyValue& value); - - PolicyValue strictest(const std::string& policy); - /// Return all strictest policy values - std::unordered_map strictest(); - - const std::vector& getAdmins() const noexcept; - -private: - std::string getScript(const std::string& name); - - std::shared_ptr database; - - /// DB Cache objects - /// TODO(Sangwan): add locking mechanism - std::vector admins; - std::unordered_map activatedPolicies; - std::unordered_map definitions; -}; - -} // namespace policy -} // namespace vist diff --git a/src/vist/policy/core/tests/core.cpp b/src/vist/policy/core/tests/core.cpp deleted file mode 100644 index 2cf5bb8..0000000 --- a/src/vist/policy/core/tests/core.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -#include - -#include - -namespace vist { -namespace policy { - -class PolicyCoreTests : public testing::Test {}; - -TEST_F(PolicyCoreTests, policy_loader) { - auto& manager = PolicyManager::Instance(); - - EXPECT_TRUE(manager.providers.size() > 0); - EXPECT_TRUE(manager.policies.size() > 0); -} - -TEST_F(PolicyCoreTests, policy_set_get) { - auto& manager = PolicyManager::Instance(); - manager.enroll("testAdmin"); - manager.set("bluetooth", PolicyValue(5), "testAdmin"); - - auto policy = manager.get("bluetooth"); - EXPECT_EQ(policy.value, 5); - - manager.enroll("testAdmin1"); - manager.set("bluetooth", PolicyValue(10), "testAdmin1"); - - /// Manager should return the strongest policy. - policy = manager.get("bluetooth"); - EXPECT_EQ(policy.value, 5); - - manager.disenroll("testAdmin"); - manager.disenroll("testAdmin1"); -} - -} // namespace policy -} // namespace vist diff --git a/src/vist/policy/core/tests/storage.cpp b/src/vist/policy/core/tests/storage.cpp deleted file mode 100644 index 369fb00..0000000 --- a/src/vist/policy/core/tests/storage.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -#include - -#include - -#include - -using namespace vist::policy; - -class PolicyStorageTests : public testing::Test { -public: - void SetUp() override - { - this->storage = std::make_shared(DB_PATH); - } - - std::shared_ptr getStorage() - { - return this->storage; - } - -private: - std::shared_ptr storage = nullptr; -}; - -TEST_F(PolicyStorageTests, initialize) -{ - bool isRaised = false; - - try { - // DB is maden at run-time - PolicyStorage storage("/tmp/dummy"); - } catch (const std::exception&) { - isRaised = true; - } - - EXPECT_FALSE(isRaised); -} - -TEST_F(PolicyStorageTests, enrollment) -{ - auto storage = getStorage(); - EXPECT_FALSE(storage->isActivated()); - - storage->enroll("testAdmin0"); - storage->enroll("testAdmin1"); - EXPECT_TRUE(storage->isActivated()); - - storage->disenroll("testAdmin0"); - EXPECT_TRUE(storage->isActivated()); - - storage->disenroll("testAdmin1"); - EXPECT_FALSE(storage->isActivated()); -} - -TEST_F(PolicyStorageTests, update) -{ - auto storage = getStorage(); - storage->enroll("testAdmin"); - - bool isRaised = false; - try { - storage->update("fakeAdmin", "bluetooth", PolicyValue(0)); - } catch (const std::exception&) { - isRaised = true; - } - - isRaised = false; - try { - storage->update("testAdmin", "bluetooth", PolicyValue(0)); - } catch (const std::exception&) { - isRaised = true; - } - EXPECT_FALSE(isRaised); - - isRaised = false; - try { - storage->update("testAdmin", "FakePolicy", PolicyValue(0)); - } catch (const std::exception&) { - isRaised = true; - } - EXPECT_TRUE(isRaised); - - storage->disenroll("testAdmin"); -} - -TEST_F(PolicyStorageTests, strictest) -{ - auto storage = getStorage(); - storage->enroll("testAdmin0"); - storage->enroll("testAdmin1"); - - storage->update("testAdmin0", "bluetooth", PolicyValue(3)); - storage->update("testAdmin1", "bluetooth", PolicyValue(6)); - - bool isRaised = false; - try { - auto value = storage->strictest("FakePolicy"); - } catch (const std::exception&) { - isRaised = true; - } - EXPECT_TRUE(isRaised); - - auto policy = storage->strictest("bluetooth"); - EXPECT_EQ(policy.value, 3); - - storage->disenroll("testAdmin0"); - storage->disenroll("testAdmin1"); -} - -TEST_F(PolicyStorageTests, strictest_all) -{ - auto storage = getStorage(); - storage->enroll("testAdmin"); - - auto policies = storage->strictest(); - EXPECT_TRUE(policies.size() > 0); - - storage->disenroll("testAdmin"); -} - -TEST_F(PolicyStorageTests, admin_list) -{ - auto storage = getStorage(); - - auto admins = storage->getAdmins(); - EXPECT_EQ(admins.size(), 0); - - storage->enroll("testAdmin1"); - admins = storage->getAdmins(); - EXPECT_EQ(admins.size(), 1); - - storage->enroll("testAdmin2"); - admins = storage->getAdmins(); - EXPECT_EQ(admins.size(), 2); - - storage->disenroll("testAdmin2"); - admins = storage->getAdmins(); - EXPECT_EQ(admins.size(), 1); - - storage->disenroll("testAdmin1"); - admins = storage->getAdmins(); - EXPECT_EQ(admins.size(), 0); -} diff --git a/src/vist/policy/db-schema.hpp b/src/vist/policy/db-schema.hpp new file mode 100644 index 0000000..2bdf75b --- /dev/null +++ b/src/vist/policy/db-schema.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#pragma once + +#include + +namespace vist { +namespace policy { +namespace schema { + +struct Admin { + std::string name; +}; + +struct PolicyActivated { + std::string admin; + std::string policy; + int value = -1; +}; + +struct PolicyDefinition { + std::string name; + int ivalue = -1; +}; + +} // namespace schema +} // namespace policy +} // namespace vist diff --git a/src/vist/policy/policy-loader.cpp b/src/vist/policy/policy-loader.cpp new file mode 100644 index 0000000..28c3b41 --- /dev/null +++ b/src/vist/policy/policy-loader.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include "policy-loader.hpp" + +namespace vist { +namespace policy { + +PolicyProvider* PolicyLoader::load(const std::string& path) +{ + PluginLoader loader(path); + PolicyProvider::FactoryType factory = nullptr; + loader.load(PolicyProvider::getFactoryName(), factory); + if (factory == nullptr) + std::runtime_error("Failed to load symbol. " + PolicyProvider::getFactoryName()); + + auto provider = (*factory)(); + if (provider == nullptr) + std::runtime_error("Failed to make provider. " + PolicyProvider::getFactoryName()); + + return provider; +} + +PluginLoader::PluginLoader(const std::string& path, int flag) + : handle(::dlopen(path.c_str(), flag), [](void*)->int{return 0;}) +// Cleaning object after dlclose() makes SEGFAULT. +// TODO: Sync dynamic loading's life-cycle with program.(PluginManager) +// : handle(::dlopen(path.c_str(), flag), ::dlclose) +{ + if (handle == nullptr) + throw std::invalid_argument("Failed to open: " + path); +} + +} // namespace policy +} // namespace vist diff --git a/src/vist/policy/policy-loader.hpp b/src/vist/policy/policy-loader.hpp new file mode 100644 index 0000000..7221223 --- /dev/null +++ b/src/vist/policy/policy-loader.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#pragma once + +#include + +#include +#include +#include + +#include + +namespace vist { +namespace policy { + +struct PolicyLoader final { + static PolicyProvider* load(const std::string& path); +}; + +class PluginLoader final { +public: + explicit PluginLoader(const std::string& path, int flag = RTLD_LAZY); + + template + void load(const std::string& name, T& symbol); + +private: + using Handle = std::unique_ptr; + Handle handle; +}; + +template +void PluginLoader::load(const std::string& name, T& symbol) +{ + symbol = reinterpret_cast(::dlsym(handle.get(), name.c_str())); + if (symbol == nullptr) + throw std::runtime_error("Failed to load: " + name); +} + +} // namespace policy +} // namespace vist diff --git a/src/vist/policy/policy-manager.cpp b/src/vist/policy/policy-manager.cpp new file mode 100644 index 0000000..f1bd3e5 --- /dev/null +++ b/src/vist/policy/policy-manager.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include "policy-manager.hpp" +#include "policy-loader.hpp" + +#include + +#include + +namespace vist { +namespace policy { + +PolicyManager::PolicyManager() : storage(DB_PATH) +{ + loadProviders(PLUGIN_INSTALL_DIR); + int cnt = loadPolicies(); + INFO(VIST) << std::to_string(cnt) << "-policies loaded"; +} + +std::pair PolicyManager::loadProviders(const std::string& path) +{ + INFO(VIST) << "Load policies from :" << path; + klay::File dir(path); + if (!dir.exists() || !dir.isDirectory()) + throw std::invalid_argument("Plugin directory is wrong.: " + path); + + int passed = 0, failed = 0; + klay::DirectoryIterator end; + for (klay::DirectoryIterator iter(path); iter != end; ++iter) { + if (!iter->isFile()) + continue; + + try { + auto provider = PolicyLoader::load(iter->getPath()); + DEBUG(VIST) << "Loaded provider: " << provider->getName(); + + bool exist = false; + for (const auto& p : this->providers) { + if (p->getName() == provider->getName()) { + exist = true; + break; + } + } + + if (!exist) + this->providers.emplace_back(std::move(provider)); + } catch (const std::exception& e) { + ++failed; + ERROR(VIST) << "Failed to load: " << iter->getPath() << e.what(); + continue; + } + + ++passed; + } + + INFO(VIST) << "Loaded result >> passed: " << passed << ", failed: " << failed; + return std::make_pair(passed, failed); +} + +int PolicyManager::loadPolicies() +{ + bool changed = false; + + /// Make policy-provider map for performance + for (const auto& provider : providers) { + for (const auto& pair : provider->policies) { + policies[pair.first] = provider->getName(); + + /// Check the policy is defined on policy-storage + if (!storage.exists(pair.first)) { + INFO(VIST) << "Define policy: " << pair.first; + storage.define(pair.first, pair.second->getInitial().value); + changed = true; + } + } + } + + if (changed) + storage.syncPolicyDefinition(); + + return policies.size(); +} + +void PolicyManager::enroll(const std::string& admin) +{ + this->storage.enroll(admin); +} + +void PolicyManager::disenroll(const std::string& admin) +{ + this->storage.disenroll(admin); +} + +void PolicyManager::set(const std::string& policy, + const PolicyValue& value, + const std::string& admin) +{ + if (this->policies.find(policy) == this->policies.end()) + std::runtime_error("Not exist policy: " + policy); + + storage.update(admin, policy, value); + + for (auto& p : providers) { + if (p->getName() != this->policies[policy]) + continue; + + if (p->policies.find(policy) != p->policies.end()) { + p->policies[policy]->set(value); + return; + } + } +} + +PolicyValue PolicyManager::get(const std::string& policy) +{ + return storage.strictest(policy); +} + +std::unordered_map PolicyManager::getAll() +{ + return storage.strictest(); +} + +std::vector PolicyManager::getAdmins() +{ + return storage.getAdmins(); +} + +} // namespace policy +} // namespace vist diff --git a/src/vist/policy/policy-manager.hpp b/src/vist/policy/policy-manager.hpp new file mode 100644 index 0000000..7523976 --- /dev/null +++ b/src/vist/policy/policy-manager.hpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#pragma once + +#include +#include + +#include "policy-storage.hpp" + +#include +#include +#include +#include +#include + +#include + +namespace vist { +namespace policy { + +class PolicyManager final { +public: + PolicyManager(const PolicyManager&) = delete; + PolicyManager& operator=(const PolicyManager&) = delete; + + PolicyManager(PolicyManager&&) = delete; + PolicyManager& operator=(PolicyManager&&) = delete; + + static PolicyManager& Instance() + { + static PolicyManager manager; + return manager; + } + + void enroll(const std::string& admin); + void disenroll(const std::string& admin); + + void set(const std::string& policy, + const PolicyValue& value, + const std::string& admin); + PolicyValue get(const std::string& policy); + std::unordered_map getAll(); + + std::vector getAdmins(); + +private: + explicit PolicyManager(); + ~PolicyManager() = default; + + std::pair loadProviders(const std::string& path); + int loadPolicies(); + + PolicyStorage storage; + std::vector> providers; + + /// Policy-Provider + std::unordered_map policies; + + FRIEND_TEST(PolicyCoreTests, policy_loader); +}; + +} // namespace policy +} // namespace vist diff --git a/src/vist/policy/policy-storage.cpp b/src/vist/policy/policy-storage.cpp new file mode 100644 index 0000000..6cc3798 --- /dev/null +++ b/src/vist/policy/policy-storage.cpp @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include "policy-storage.hpp" + +#include +#include + +#include +#include +#include + +#include +#include + +using namespace vist::tsqb; +using namespace vist::policy::schema; + +namespace { + +auto adminTable = make_table("ADMIN", make_column("name", &Admin::name)); + +auto polActivatedTable = make_table("POLICY_ACTIVATED", + make_column("admin", &PolicyActivated::admin), + make_column("policy", &PolicyActivated::policy), + make_column("value", &PolicyActivated::value)); + +auto polDefinitionTable = make_table("POLICY_DEFINITION", + make_column("name", &PolicyDefinition::name), + make_column("ivalue", &PolicyDefinition::ivalue)); + +const std::string SCRIPT_BASE = SCRIPT_INSTALL_DIR; +const std::string SCRIPT_CREATE_SCHEMA = "create-schema"; + +} // anonymous namespace + +namespace vist { +namespace policy { + +PolicyStorage::PolicyStorage(const std::string& path) : + database(std::make_shared(path, + database::Connection::ReadWrite | + database::Connection::Create)) +{ + database->exec("PRAGMA foreign_keys = ON;"); + database->exec(getScript(SCRIPT_CREATE_SCHEMA)); + + sync(); +} + +void PolicyStorage::sync() +{ + DEBUG(VIST) << "Sync policy storage to cache object."; + syncAdmin(); + syncPolicyActivated(); + syncPolicyDefinition(); +} + +void PolicyStorage::syncPolicyDefinition() +{ + this->definitions.clear(); + std::string query = polDefinitionTable.selectAll(); + database::Statement stmt(*database, query); + + while (stmt.step()) { + PolicyDefinition pd; + pd.name = std::string(stmt.getColumn(0)); + pd.ivalue = stmt.getColumn(1); + DEBUG(VIST) << "Defined policy:" << pd.name; + this->definitions.emplace(pd.name, std::move(pd)); + } + + DEBUG(VIST) << definitions.size() << "- policies synced."; +} + +void PolicyStorage::syncAdmin() +{ + this->admins.clear(); + std::string query = adminTable.selectAll(); + database::Statement stmt(*database, query); + + while (stmt.step()) + this->admins.emplace_back(std::string(stmt.getColumn(0))); + + DEBUG(VIST) << admins.size() << "-admins synced."; +} + +void PolicyStorage::syncPolicyActivated() +{ + this->activatedPolicies.clear(); + std::string query = polActivatedTable.selectAll(); + database::Statement stmt(*database, query); + + while (stmt.step()) { + PolicyActivated pa; + pa.admin = std::string(stmt.getColumn(0)); + pa.policy = std::string(stmt.getColumn(1)); + pa.value = stmt.getColumn(2); + this->activatedPolicies.emplace(pa.policy, std::move(pa)); + } + + DEBUG(VIST) << activatedPolicies.size() << "- activated-policies synced."; +} + +std::string PolicyStorage::getScript(const std::string& name) +{ + std::string path = SCRIPT_BASE + "/" + name + ".sql"; + std::ifstream is(path); + if (is.fail()) + throw std::invalid_argument("Failed to open script: " + path); + + std::istreambuf_iterator begin(is), end; + auto content = std::string(begin, end); + if (content.empty()) + throw std::runtime_error("Failed to read script: " + path); + + return content; +} + +void PolicyStorage::define(const std::string& policy, int ivalue) +{ + if (definitions.find(policy) != definitions.end()) { + INFO(VIST) << "Policy is already defined: " << policy; + return; + } + + PolicyDefinition pd; + pd.name = policy; + pd.ivalue = ivalue; + + std::string query = polDefinitionTable.insert(&PolicyDefinition::name, + &PolicyDefinition::ivalue); + database::Statement stmt(*database, query); + stmt.bind(1, pd.name); + stmt.bind(2, pd.ivalue); + if (!stmt.exec()) + throw std::runtime_error("Failed to define policy: " + pd.name); +} + +void PolicyStorage::enroll(const std::string& name) +{ + INFO(VIST) << "Enroll admin: " << name; + if (std::find(admins.begin(), admins.end(), name) != admins.end()) { + ERROR(VIST) << "Admin is aleady enrolled.: " << name; + return; + } + + std::string query = adminTable.insert(&Admin::name); + DEBUG(VIST) << "Enroll admin query statement: " << query; + database::Statement stmt(*database, query); + stmt.bind(1, name); + if (!stmt.exec()) + throw std::runtime_error("Failed to enroll admin: " + name); + + admins.push_back(name); + /// PolicyActivated is triggered by enrolling admin. + syncPolicyActivated(); + + int count = activatedPolicies.size() / admins.size(); + INFO(VIST) << "Admin[" << name << "] manages " + << std::to_string(count) << "-policies."; +} + +void PolicyStorage::disenroll(const std::string& name) +{ + INFO(VIST) << "Disenroll admin: " << name; + auto iter = std::find(admins.begin(), admins.end(), name); + if (iter == admins.end()) { + ERROR(VIST) << "Not exist admin: " << name; + return; + } else { + admins.erase(iter); + } + + std::string query = adminTable.remove().where(expr(&Admin::name) == name); + database::Statement stmt(*database, query); + stmt.bind(1, name); + if (!stmt.exec()) + throw std::runtime_error("Failed to disenroll admin: " + name); +} + +void PolicyStorage::update(const std::string& admin, + const std::string& policy, + const PolicyValue& value) +{ + DEBUG(VIST) << "Policy-update is called by admin: " << admin + << ", about: " << policy << ", value: " << std::to_string(value); + + if (std::find(admins.begin(), admins.end(), admin) == admins.end()) + throw std::runtime_error("Not exist admin: " + admin); + + if (definitions.find(policy) == definitions.end()) + throw std::runtime_error("Not exist policy: " + policy); + + int policyValue = value; + std::string query = polActivatedTable.update(&PolicyActivated::value) + .where(expr(&PolicyActivated::admin) == admin && + expr(&PolicyActivated::policy) == policy); + database::Statement stmt(*database, query); + stmt.bind(1, policyValue); + stmt.bind(2, admin); + stmt.bind(3, policy); + if (!stmt.exec()) + throw runtime::Exception("Failed to update policy:" + policy); + + syncPolicyActivated(); +} + +PolicyValue PolicyStorage::strictest(const std::string& policy) +{ + if (definitions.find(policy) == definitions.end()) + throw std::runtime_error("Not exist policy: " + policy); + + // There is no enrolled admins. + if (activatedPolicies.size() == 0) + return PolicyValue(definitions[policy].ivalue); + + std::shared_ptr strictestPtr = nullptr; + auto range = activatedPolicies.equal_range(policy); + for (auto iter = range.first; iter != range.second; iter++) { + int value = iter->second.value; + if (strictestPtr == nullptr) + strictestPtr = std::make_shared(value); + else + strictestPtr->value = (*strictestPtr < value) ? strictestPtr->value : value; + + DEBUG(VIST) << "The strictest of policy[" << policy + << "] : " + std::to_string(strictestPtr->value); + } + + if (strictestPtr == nullptr) + throw std::runtime_error("Not exist managed policy: " + policy); + + return std::move(*strictestPtr); +} + +std::unordered_map PolicyStorage::strictest() +{ + std::unordered_map policies; + for (const auto& pair : definitions) { + std::string name = pair.first; + auto value = this->strictest(name); + + policies.emplace(std::move(name), std::move(value)); + } + + return policies; +} + +const std::vector& PolicyStorage::getAdmins() const noexcept +{ + return admins; +} + +} // namespace policy +} // namespace vist diff --git a/src/vist/policy/policy-storage.hpp b/src/vist/policy/policy-storage.hpp new file mode 100644 index 0000000..4ef524d --- /dev/null +++ b/src/vist/policy/policy-storage.hpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * ttp://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#pragma once + +#include + +#include "db-schema.hpp" + +#include +#include +#include + +#include + +namespace vist { +namespace policy { + +using namespace schema; + +class PolicyStorage final { +public: + explicit PolicyStorage(const std::string& path); + + /// TODO(Sangwan): Consider to support lazy sync + void sync(); + + void syncAdmin(); + void syncPolicyActivated(); + void syncPolicyDefinition(); + + inline bool exists(const std::string& policy) const noexcept + { + return definitions.find(policy) != definitions.end(); + } + + inline bool isActivated() const noexcept + { + return admins.size() > 0 && activatedPolicies.size() > 0; + } + + void enroll(const std::string& admin); + void disenroll(const std::string& admin); + + void define(const std::string& policy, int ivalue); + void update(const std::string& admin, + const std::string& policy, + const PolicyValue& value); + + PolicyValue strictest(const std::string& policy); + /// Return all strictest policy values + std::unordered_map strictest(); + + const std::vector& getAdmins() const noexcept; + +private: + std::string getScript(const std::string& name); + + std::shared_ptr database; + + /// DB Cache objects + /// TODO(Sangwan): add locking mechanism + std::vector admins; + std::unordered_map activatedPolicies; + std::unordered_map definitions; +}; + +} // namespace policy +} // namespace vist diff --git a/src/vist/policy/sdk/policy-model.hpp b/src/vist/policy/sdk/policy-model.hpp deleted file mode 100644 index 64580fc..0000000 --- a/src/vist/policy/sdk/policy-model.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -#pragma once - -#include - -#include -#include - -namespace vist { -namespace policy { - -class PolicyModel { -public: - explicit PolicyModel(std::string name, PolicyValue initial) noexcept : - name(std::move(name)), initial(std::move(initial)) {} - virtual ~PolicyModel() = default; - - PolicyModel(const PolicyModel&) = delete; - PolicyModel& operator=(const PolicyModel&) = delete; - - PolicyModel(PolicyModel&&) = default; - PolicyModel& operator=(PolicyModel&&) = default; - - inline void set(const PolicyValue& value) - { - auto rollback = current; - current = value; - ready = true; - - try { - this->onChanged(value); - } catch (const std::exception& e) { - current = rollback; - ready = false; - std::rethrow_exception(std::current_exception()); - } - } - - inline const PolicyValue& get() const - { - if (!ready) - throw std::runtime_error("Policy value should be set once before use."); - - return current; - } - - virtual void onChanged(const PolicyValue& value) = 0; - - const std::string& getName() const noexcept { return name; } - const PolicyValue& getInitial() const noexcept { return initial; } - -protected: - std::string name; - PolicyValue initial; - PolicyValue current; - bool ready = false; -}; - -} // namespace policy -} // namespace vist diff --git a/src/vist/policy/sdk/policy-provider.hpp b/src/vist/policy/sdk/policy-provider.hpp deleted file mode 100644 index c55ff26..0000000 --- a/src/vist/policy/sdk/policy-provider.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -#pragma once - -#include - -#include -#include -#include - -namespace vist { -namespace policy { - -class PolicyProvider { -public: - using FactoryType = PolicyProvider* (*)(); - - explicit PolicyProvider(std::string name) noexcept : name(std::move(name)) {} - virtual ~PolicyProvider() = default; - - inline void add(const std::shared_ptr& policy) - { - policies[policy->getName()] = policy; - } - - inline const std::string& getName() const noexcept { return name; } - static const std::string& getFactoryName() noexcept - { - static std::string name = "PolicyFactory"; - return name; - } - - inline std::size_t size() const noexcept { return policies.size(); } - -private: - std::string name; - std::unordered_map> policies; - - friend class PolicyManager; -}; - -} // namespace policy -} // namespace vist diff --git a/src/vist/policy/sdk/policy-value.hpp b/src/vist/policy/sdk/policy-value.hpp deleted file mode 100644 index e1b2464..0000000 --- a/src/vist/policy/sdk/policy-value.hpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -#pragma once - -namespace vist { -namespace policy { - -// TODO: Support various value type -struct PolicyValue final { - explicit PolicyValue(int value) noexcept : value(value) {} - explicit PolicyValue() noexcept = default; - ~PolicyValue() = default; - - PolicyValue(const PolicyValue&) noexcept = default; - PolicyValue& operator=(const PolicyValue&) noexcept = default; - - PolicyValue(PolicyValue&&) noexcept = default; - PolicyValue& operator=(PolicyValue&&) noexcept = default; - - PolicyValue& operator=(int val) { - value = val; - return *this; - } - - operator int() const { return value; } - bool operator==(const PolicyValue& rhs) const { return value == rhs.value; } - bool operator!=(const PolicyValue& rhs) const { return value != rhs.value; } - bool operator<(const PolicyValue& rhs) const { return value < rhs.value; } - - int value = -1; -}; - -} // namespace policy -} // namespace vist diff --git a/src/vist/policy/sdk/tests/sdk.cpp b/src/vist/policy/sdk/tests/sdk.cpp deleted file mode 100644 index 4be5d8d..0000000 --- a/src/vist/policy/sdk/tests/sdk.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -#include - -#include -#include - -#include - -namespace { - int g_value = -1; -} // anonymous namespace - -using namespace vist::policy; - -class PolicySDKTests : public testing::Test {}; - -class TestPolicyModel : public PolicyModel { -public: - TestPolicyModel() : PolicyModel("test_policy", PolicyValue(1)) {} - - virtual void onChanged(const PolicyValue& value) - { - g_value = value; - } -}; - -class TestPolicyModelFailed : public PolicyModel { -public: - TestPolicyModelFailed() : PolicyModel("test_policy_failed", PolicyValue(1)) {} - - virtual void onChanged(const PolicyValue& value) - { - throw std::runtime_error("Intended exception for test."); - } -}; - -TEST_F(PolicySDKTests, policy_model) -{ - TestPolicyModel policy; - - EXPECT_EQ(policy.getName(), "test_policy"); - EXPECT_EQ(policy.getInitial(), 1); - - // Policy value should be set once before use - bool isRaised = false; - try { - auto value = policy.get(); - } catch (const std::exception&) { - isRaised = true; - } - - EXPECT_TRUE(isRaised); - - policy.set(PolicyValue(3)); - EXPECT_EQ(3, g_value); - EXPECT_EQ(3, policy.get()); -} - -TEST_F(PolicySDKTests, policy_model_failed) -{ - TestPolicyModelFailed policy; - - EXPECT_EQ(policy.getName(), "test_policy_failed"); - EXPECT_EQ(policy.getInitial(), 1); - - bool isRaised = true; - try { - policy.set(PolicyValue(3)); - } catch (const std::exception&) { - isRaised = true; - } - - EXPECT_TRUE(isRaised); -} - -TEST_F(PolicySDKTests, policy_provider) -{ - PolicyProvider provider("testProvider"); - provider.add(std::make_shared()); - provider.add(std::make_shared()); - - EXPECT_EQ(2, provider.size()); -} diff --git a/src/vist/policy/tests/core.cpp b/src/vist/policy/tests/core.cpp new file mode 100644 index 0000000..c5c53d9 --- /dev/null +++ b/src/vist/policy/tests/core.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include + +#include + +namespace vist { +namespace policy { + +class PolicyCoreTests : public testing::Test {}; + +TEST_F(PolicyCoreTests, policy_loader) { + auto& manager = PolicyManager::Instance(); + + EXPECT_TRUE(manager.providers.size() > 0); + EXPECT_TRUE(manager.policies.size() > 0); +} + +TEST_F(PolicyCoreTests, policy_set_get) { + auto& manager = PolicyManager::Instance(); + manager.enroll("testAdmin"); + manager.set("bluetooth", PolicyValue(5), "testAdmin"); + + auto policy = manager.get("bluetooth"); + EXPECT_EQ(policy.value, 5); + + manager.enroll("testAdmin1"); + manager.set("bluetooth", PolicyValue(10), "testAdmin1"); + + /// Manager should return the strongest policy. + policy = manager.get("bluetooth"); + EXPECT_EQ(policy.value, 5); + + manager.disenroll("testAdmin"); + manager.disenroll("testAdmin1"); +} + +} // namespace policy +} // namespace vist diff --git a/src/vist/policy/tests/storage.cpp b/src/vist/policy/tests/storage.cpp new file mode 100644 index 0000000..78fcc39 --- /dev/null +++ b/src/vist/policy/tests/storage.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include + +#include + +#include + +using namespace vist::policy; + +class PolicyStorageTests : public testing::Test { +public: + void SetUp() override + { + this->storage = std::make_shared(DB_PATH); + } + + std::shared_ptr getStorage() + { + return this->storage; + } + +private: + std::shared_ptr storage = nullptr; +}; + +TEST_F(PolicyStorageTests, initialize) +{ + bool isRaised = false; + + try { + // DB is maden at run-time + PolicyStorage storage("/tmp/dummy"); + } catch (const std::exception&) { + isRaised = true; + } + + EXPECT_FALSE(isRaised); +} + +TEST_F(PolicyStorageTests, enrollment) +{ + auto storage = getStorage(); + EXPECT_FALSE(storage->isActivated()); + + storage->enroll("testAdmin0"); + storage->enroll("testAdmin1"); + EXPECT_TRUE(storage->isActivated()); + + storage->disenroll("testAdmin0"); + EXPECT_TRUE(storage->isActivated()); + + storage->disenroll("testAdmin1"); + EXPECT_FALSE(storage->isActivated()); +} + +TEST_F(PolicyStorageTests, update) +{ + auto storage = getStorage(); + storage->enroll("testAdmin"); + + bool isRaised = false; + try { + storage->update("fakeAdmin", "bluetooth", PolicyValue(0)); + } catch (const std::exception&) { + isRaised = true; + } + + isRaised = false; + try { + storage->update("testAdmin", "bluetooth", PolicyValue(0)); + } catch (const std::exception&) { + isRaised = true; + } + EXPECT_FALSE(isRaised); + + isRaised = false; + try { + storage->update("testAdmin", "FakePolicy", PolicyValue(0)); + } catch (const std::exception&) { + isRaised = true; + } + EXPECT_TRUE(isRaised); + + storage->disenroll("testAdmin"); +} + +TEST_F(PolicyStorageTests, strictest) +{ + auto storage = getStorage(); + storage->enroll("testAdmin0"); + storage->enroll("testAdmin1"); + + storage->update("testAdmin0", "bluetooth", PolicyValue(3)); + storage->update("testAdmin1", "bluetooth", PolicyValue(6)); + + bool isRaised = false; + try { + auto value = storage->strictest("FakePolicy"); + } catch (const std::exception&) { + isRaised = true; + } + EXPECT_TRUE(isRaised); + + auto policy = storage->strictest("bluetooth"); + EXPECT_EQ(policy.value, 3); + + storage->disenroll("testAdmin0"); + storage->disenroll("testAdmin1"); +} + +TEST_F(PolicyStorageTests, strictest_all) +{ + auto storage = getStorage(); + storage->enroll("testAdmin"); + + auto policies = storage->strictest(); + EXPECT_TRUE(policies.size() > 0); + + storage->disenroll("testAdmin"); +} + +TEST_F(PolicyStorageTests, admin_list) +{ + auto storage = getStorage(); + + auto admins = storage->getAdmins(); + EXPECT_EQ(admins.size(), 0); + + storage->enroll("testAdmin1"); + admins = storage->getAdmins(); + EXPECT_EQ(admins.size(), 1); + + storage->enroll("testAdmin2"); + admins = storage->getAdmins(); + EXPECT_EQ(admins.size(), 2); + + storage->disenroll("testAdmin2"); + admins = storage->getAdmins(); + EXPECT_EQ(admins.size(), 1); + + storage->disenroll("testAdmin1"); + admins = storage->getAdmins(); + EXPECT_EQ(admins.size(), 0); +} diff --git a/src/vist/sdk/CMakeLists.txt b/src/vist/sdk/CMakeLists.txt new file mode 100644 index 0000000..5e233cf --- /dev/null +++ b/src/vist/sdk/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +FILE(GLOB POLICY_SDK_TESTS "tests/*.cpp") +ADD_VIST_TEST(${POLICY_SDK_TESTS}) diff --git a/src/vist/sdk/policy-model.hpp b/src/vist/sdk/policy-model.hpp new file mode 100644 index 0000000..2194953 --- /dev/null +++ b/src/vist/sdk/policy-model.hpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#pragma once + +#include + +#include +#include + +namespace vist { +namespace policy { + +class PolicyModel { +public: + explicit PolicyModel(std::string name, PolicyValue initial) noexcept : + name(std::move(name)), initial(std::move(initial)) {} + virtual ~PolicyModel() = default; + + PolicyModel(const PolicyModel&) = delete; + PolicyModel& operator=(const PolicyModel&) = delete; + + PolicyModel(PolicyModel&&) = default; + PolicyModel& operator=(PolicyModel&&) = default; + + inline void set(const PolicyValue& value) + { + auto rollback = current; + current = value; + ready = true; + + try { + this->onChanged(value); + } catch (const std::exception& e) { + current = rollback; + ready = false; + std::rethrow_exception(std::current_exception()); + } + } + + inline const PolicyValue& get() const + { + if (!ready) + throw std::runtime_error("Policy value should be set once before use."); + + return current; + } + + virtual void onChanged(const PolicyValue& value) = 0; + + const std::string& getName() const noexcept { return name; } + const PolicyValue& getInitial() const noexcept { return initial; } + +protected: + std::string name; + PolicyValue initial; + PolicyValue current; + bool ready = false; +}; + +} // namespace policy +} // namespace vist diff --git a/src/vist/sdk/policy-provider.hpp b/src/vist/sdk/policy-provider.hpp new file mode 100644 index 0000000..d228681 --- /dev/null +++ b/src/vist/sdk/policy-provider.hpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#pragma once + +#include + +#include +#include +#include + +namespace vist { +namespace policy { + +class PolicyProvider { +public: + using FactoryType = PolicyProvider* (*)(); + + explicit PolicyProvider(std::string name) noexcept : name(std::move(name)) {} + virtual ~PolicyProvider() = default; + + inline void add(const std::shared_ptr& policy) + { + policies[policy->getName()] = policy; + } + + inline const std::string& getName() const noexcept { return name; } + static const std::string& getFactoryName() noexcept + { + static std::string name = "PolicyFactory"; + return name; + } + + inline std::size_t size() const noexcept { return policies.size(); } + +private: + std::string name; + std::unordered_map> policies; + + friend class PolicyManager; +}; + +} // namespace policy +} // namespace vist diff --git a/src/vist/sdk/policy-value.hpp b/src/vist/sdk/policy-value.hpp new file mode 100644 index 0000000..e1b2464 --- /dev/null +++ b/src/vist/sdk/policy-value.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#pragma once + +namespace vist { +namespace policy { + +// TODO: Support various value type +struct PolicyValue final { + explicit PolicyValue(int value) noexcept : value(value) {} + explicit PolicyValue() noexcept = default; + ~PolicyValue() = default; + + PolicyValue(const PolicyValue&) noexcept = default; + PolicyValue& operator=(const PolicyValue&) noexcept = default; + + PolicyValue(PolicyValue&&) noexcept = default; + PolicyValue& operator=(PolicyValue&&) noexcept = default; + + PolicyValue& operator=(int val) { + value = val; + return *this; + } + + operator int() const { return value; } + bool operator==(const PolicyValue& rhs) const { return value == rhs.value; } + bool operator!=(const PolicyValue& rhs) const { return value != rhs.value; } + bool operator<(const PolicyValue& rhs) const { return value < rhs.value; } + + int value = -1; +}; + +} // namespace policy +} // namespace vist diff --git a/src/vist/sdk/tests/sdk.cpp b/src/vist/sdk/tests/sdk.cpp new file mode 100644 index 0000000..d6773b3 --- /dev/null +++ b/src/vist/sdk/tests/sdk.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include + +#include +#include + +#include + +namespace { + int g_value = -1; +} // anonymous namespace + +using namespace vist::policy; + +class PolicySDKTests : public testing::Test {}; + +class TestPolicyModel : public PolicyModel { +public: + TestPolicyModel() : PolicyModel("test_policy", PolicyValue(1)) {} + + virtual void onChanged(const PolicyValue& value) + { + g_value = value; + } +}; + +class TestPolicyModelFailed : public PolicyModel { +public: + TestPolicyModelFailed() : PolicyModel("test_policy_failed", PolicyValue(1)) {} + + virtual void onChanged(const PolicyValue& value) + { + throw std::runtime_error("Intended exception for test."); + } +}; + +TEST_F(PolicySDKTests, policy_model) +{ + TestPolicyModel policy; + + EXPECT_EQ(policy.getName(), "test_policy"); + EXPECT_EQ(policy.getInitial(), 1); + + // Policy value should be set once before use + bool isRaised = false; + try { + auto value = policy.get(); + } catch (const std::exception&) { + isRaised = true; + } + + EXPECT_TRUE(isRaised); + + policy.set(PolicyValue(3)); + EXPECT_EQ(3, g_value); + EXPECT_EQ(3, policy.get()); +} + +TEST_F(PolicySDKTests, policy_model_failed) +{ + TestPolicyModelFailed policy; + + EXPECT_EQ(policy.getName(), "test_policy_failed"); + EXPECT_EQ(policy.getInitial(), 1); + + bool isRaised = true; + try { + policy.set(PolicyValue(3)); + } catch (const std::exception&) { + isRaised = true; + } + + EXPECT_TRUE(isRaised); +} + +TEST_F(PolicySDKTests, policy_provider) +{ + PolicyProvider provider("testProvider"); + provider.add(std::make_shared()); + provider.add(std::make_shared()); + + EXPECT_EQ(2, provider.size()); +} diff --git a/src/vist/service/tests/core.cpp b/src/vist/service/tests/core.cpp index 4153827..8ba411b 100644 --- a/src/vist/service/tests/core.cpp +++ b/src/vist/service/tests/core.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include @@ -42,8 +42,7 @@ TEST_F(CoreTests, query_select) TEST_F(CoreTests, query_update) { - auto& manager = policy::PolicyManager::Instance(); - manager.enroll("admin"); + policy::API::Admin::Enroll("admin"); std::string statement = "SELECT * FROM policy WHERE name = 'bluetooth'"; auto rows = Vist::Query(statement); @@ -58,5 +57,5 @@ TEST_F(CoreTests, query_update) rows = Vist::Query(statement); EXPECT_EQ(rows[0]["value"], std::to_string(3)); - manager.disenroll("admin"); + policy::API::Admin::Disenroll("admin"); }