From: Kichan Kwon Date: Tue, 7 Jul 2020 10:20:51 +0000 (+0900) Subject: test : add system_info_init_db_test X-Git-Tag: submit/tizen/20201102.030555~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=199fc91903fbe4b9742ff4601740740229646c5c;p=platform%2Fcore%2Fapi%2Fsystem-info.git test : add system_info_init_db_test Change-Id: I8f02ab2d6df029e50309ca1a10d3cb3e690d8be9 Signed-off-by: Kichan Kwon --- diff --git a/packaging/capi-system-info.spec b/packaging/capi-system-info.spec index 97c2702..4b08b80 100644 --- a/packaging/capi-system-info.spec +++ b/packaging/capi-system-info.spec @@ -128,6 +128,8 @@ install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj %files test # API test %{_bindir}/system_info_test +# Init DB test +%{_bindir}/system_info_init_db_test # Plugin test %attr(0755,root,-) %{_bindir}/system_info_external_plugin_test.sh %{_libdir}/libsystem_info_plugins/libsystem_info_test_plugin.so diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cca96c4..fe263b7 100755 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -2,6 +2,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) SET(TESTS api + init_db plugin ) diff --git a/test/init_db/CMakeLists.txt b/test/init_db/CMakeLists.txt new file mode 100755 index 0000000..9bbd44b --- /dev/null +++ b/test/init_db/CMakeLists.txt @@ -0,0 +1,27 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +SET(INIT_DB_TEST "system_info_init_db_test") + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SRCS) + +INCLUDE(FindPkgConfig) +pkg_check_modules(init_db_test_pkgs REQUIRED + libxml-2.0 +) + +FOREACH(flag ${init_db_test_pkgs_CXXFLAGS}) + SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} -g -fno-omit-frame-pointer -finstrument-functions -fpie") + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS}") + +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie") + +ADD_EXECUTABLE(${INIT_DB_TEST} ${SRCS}) +ADD_DEPENDENCIES(${INIT_DB_TEST} ${fw_name}) +TARGET_LINK_LIBRARIES(${INIT_DB_TEST} ${init_db_test_pkgs_LDFLAGS} "-L${CMAKE_SOURCE_DIR} -lcapi-system-info") + +INSTALL(TARGETS ${INIT_DB_TEST} DESTINATION bin) diff --git a/test/init_db/feature.cpp b/test/init_db/feature.cpp new file mode 100644 index 0000000..b5f81b7 --- /dev/null +++ b/test/init_db/feature.cpp @@ -0,0 +1,221 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "system_info_init_db_test.h" +#include "feature.h" +#include "util.h" + +/********** Feature **********/ + +Feature::ModType Feature::getModType(void) +{ + return (ModType)(rand() % static_cast(ModType::NUM_TYPE)); +} + +/********** BoolFeature **********/ + +BoolFeature::BoolFeature(std::string k, std::string v) : Feature(k) +{ + if (!v.compare(STRBOOL_TRUE)) + value = true; + else if (!v.compare(STRBOOL_FALSE)) + value = false; + else { + LOG("Invalid value : key(%s), value(%s)", k.c_str(), v.c_str()); + value = false; + } +} + +int BoolFeature::modifyValue(void) +{ + switch (getModType()) { + case ModType::NONE: + break; + case ModType::EXPAND: + value = false; + break; + case ModType::SHRINK: + value = true; + break; + default: + LOG("Invalid modType"); + return EINVAL; + } + + return util.updateDB(key, STRTYPE_BOOL, value ? STRBOOL_TRUE : STRBOOL_FALSE); +} + +int BoolFeature::verifyValue(void) +{ + int ret; + bool output; + + ret = system_info_get_platform_bool(key.c_str(), &output); + if (ret != SYSTEM_INFO_ERROR_NONE) { + LOG("system_info_get_platform_bool failed (%d)", ret); + return ret; + } + + if (value != output) { + LOG("Failed to verify value : key(%s), value(%s), expected(%s)", + key.c_str(), + output ? STRBOOL_TRUE : STRBOOL_FALSE, + value ? STRBOOL_TRUE : STRBOOL_FALSE); + return -1; + } + + return SUCCEED; +} + +/********** IntFeature **********/ + +IntFeature::IntFeature(std::string k, std::string v) : Feature(k) +{ + value = stoi(v); +} + +int IntFeature::modifyValue(void) +{ + switch (getModType()) { + case ModType::NONE: + break; + case ModType::EXPAND: + if (value < (INT_MAX / 128)) + value *= 128; + else + value = INT_MAX; + break; + case ModType::SHRINK: + value /= 128; + break; + default: + LOG("Invalid modType"); + break; + } + + return util.updateDB(key, STRTYPE_INT, std::to_string(value)); +} + +int IntFeature::verifyValue(void) +{ + int ret; + int output; + + ret = system_info_get_platform_int(key.c_str(), &output); + if (ret != SYSTEM_INFO_ERROR_NONE) { + LOG("system_info_get_platform_int failed (%d)", ret); + return ret; + } + + if (value != output) { + LOG("Failed to verify value : key(%s), value(%d), expected(%d)", + key.c_str(), output, value); + return -1; + } + + return SUCCEED; +} + +/********** DoubleFeature **********/ + +DoubleFeature::DoubleFeature(std::string k, std::string v) : Feature(k) +{ + value = stod(v); +} + +int DoubleFeature::modifyValue(void) +{ + std::ostringstream oss; + + switch (getModType()) { + case ModType::NONE: + break; + case ModType::EXPAND: + value *= 128.0; + break; + case ModType::SHRINK: + value /= 128.0; + break; + default: + LOG("Invalid modType"); + break; + } + + // Set the decimal precision + oss << std::fixed << std::setprecision(15) << value; + + return util.updateDB(key, STRTYPE_DOUBLE, oss.str()); +} + +int DoubleFeature::verifyValue(void) +{ + int ret; + double output; + + ret = system_info_get_platform_double(key.c_str(), &output); + if (ret != SYSTEM_INFO_ERROR_NONE) { + LOG("system_info_get_platform_double failed (%d)", ret); + return ret; + } + + if (value != output) { + LOG("Failed to verify value : key(%s), value(%.16lf), expected(%.16lf)", + key.c_str(), output, value); + return -1; + } + + return SUCCEED; +} + +/********** StringFeature **********/ + +StringFeature::StringFeature(std::string k, std::string v) : Feature(k) +{ + value = v; +} + +int StringFeature::modifyValue(void) +{ + switch (getModType()) { + case ModType::NONE: + break; + case ModType::EXPAND: + value += value; + break; + case ModType::SHRINK: + value.resize(std::max(value.length() / 2, (size_t)1)); + break; + default: + LOG("Invalid modType"); + break; + } + + return util.updateDB(key, STRTYPE_STRING, value); +} + +int StringFeature::verifyValue(void) +{ + int ret; + char *output = nullptr; + + ret = system_info_get_platform_string(key.c_str(), &output); + if (ret != SYSTEM_INFO_ERROR_NONE) { + LOG("system_info_get_platform_string failed (%d)", ret); + return ret; + } + + if (value.compare(output)) { + LOG("Failed to verify value : key(%s), value(%s), expected(%s)", + key.c_str(), output, value.c_str()); + return -1; + } + + return SUCCEED; +} diff --git a/test/init_db/feature.h b/test/init_db/feature.h new file mode 100644 index 0000000..07489af --- /dev/null +++ b/test/init_db/feature.h @@ -0,0 +1,87 @@ +#ifndef __FEATURE_H__ +#define __FEATURE_H__ + +#include +#include + +class Feature { +public: + Feature(std::string k) : key(k) {} + virtual ~Feature() {}; + + /** + * @brief Modify value + * @retval SUCCEED on success, otherwise an error value + */ + virtual int modifyValue(void) = 0; + + /** + * @brief Compare system-info result with DB + * @retval SUCCEED on success, otherwise an error value + */ + virtual int verifyValue(void) = 0; + +protected: + std::string key; + + enum class ModType { + NONE = 0, // Don't modify + EXPAND, // Increase value length + SHRINK, // Decrease value length + NUM_TYPE + }; + + /** + * @brief Decide the value modification type + * @retval Refer to ModType + */ + ModType getModType(void); +}; + +extern std::vectorfeatureList; + +class BoolFeature : public Feature { +public: + BoolFeature(std::string k, std::string v); + + int modifyValue(void); + int verifyValue(void); + +private: + bool value; +}; + +class IntFeature : public Feature { +public: + IntFeature(std::string k, std::string v); + + int modifyValue(void); + int verifyValue(void); + +private: + int value; +}; + +class DoubleFeature : public Feature { +public: + DoubleFeature(std::string k, std::string v); + + int modifyValue(void); + int verifyValue(void); + +private: + double value; +}; + +class StringFeature : public Feature { +public: + StringFeature(std::string k, std::string v); + + int modifyValue(void); + int verifyValue(void); + +private: + std::string value; +}; + +#endif /* __FEATURE_H__ */ diff --git a/test/init_db/system_info_init_db_test.cpp b/test/init_db/system_info_init_db_test.cpp new file mode 100644 index 0000000..7d4bd4a --- /dev/null +++ b/test/init_db/system_info_init_db_test.cpp @@ -0,0 +1,122 @@ +#include +#include +#include + +#include + +#include "feature.h" +#include "system_info_init_db_test.h" +#include "tester.h" +#include "util.h" + +Util util; +std::vector featureList; + +static int initialize(void) +{ + int ret; + + // Move original RO DB + if (access(SYSTEM_INFO_DB_RO_PATH, F_OK) == 0) { + ret = util.forkAndExec("mv", SYSTEM_INFO_DB_RO_PATH, BACKUP_DB_RO_PATH, nullptr); + if (ret != SUCCEED) { + LOG("Failed to move original RO DB (%d)", ret); + return ret; + } + } + + // Move original RW DB + if (access(SYSTEM_INFO_DB_RW_PATH, F_OK) == 0) { + ret = util.forkAndExec("mv", SYSTEM_INFO_DB_RW_PATH, BACKUP_DB_RW_PATH, nullptr); + if (ret != SUCCEED) { + LOG("Failed to move original RW DB (%d)", ret); + return ret; + } + } + + // Read model-config + ret = util.readModelConfig(); + if (ret != SUCCEED) { + LOG("Failed to read model-config (%d)", ret); + return ret; + } + + srand(time(nullptr)); + + return SUCCEED; +} + +static void finalize(void) +{ + int ret; + + // Free feature list + for (auto feature : featureList) + delete(feature); + featureList.clear(); + + // Remove test RW DB + if (access(SYSTEM_INFO_DB_RW_PATH, F_OK) == 0) { + ret = util.forkAndExec("rm", "-rf", SYSTEM_INFO_DB_RW_PATH, nullptr); + if (ret != SUCCEED) { + LOG("Failed to remove RW DB (%d)", ret); + goto handle_ro_db; + } + } + + // Put back original RW DB + if (access(BACKUP_DB_RW_PATH, F_OK) == 0) { + ret = util.forkAndExec("mv", BACKUP_DB_RW_PATH, SYSTEM_INFO_DB_RW_PATH, nullptr); + if (ret != SUCCEED) + LOG("Failed to move original RW DB (%d)", ret); + } + +handle_ro_db: + // Remove test RO DB + if (access(SYSTEM_INFO_DB_RO_PATH, F_OK) == 0) { + ret = util.forkAndExec("rm", "-rf", SYSTEM_INFO_DB_RO_PATH, nullptr); + if (ret != SUCCEED) { + LOG("Failed to remove RO DB (%d)", ret); + return; + } + } + + // Put back original RO DB + if (access(BACKUP_DB_RO_PATH, F_OK) == 0) { + ret = util.forkAndExec("mv", BACKUP_DB_RO_PATH, SYSTEM_INFO_DB_RO_PATH, nullptr); + if (ret != SUCCEED) + LOG("Failed to move original RO DB (%d)", ret); + } +} + +int main(int argc, char *argv[]) +{ + int ret; + + LOG("========== Start system_info_init_db test ==========\n"); + + ret = initialize(); + if (ret != SUCCEED) { + LOG("Failed to initialize (%d)", ret); + finalize(); + return ret; + } + + Tester *testerList[] = { + new CreateDB(), + new InsertKey(), + new ModifyValue(), + new VerifyValue(), + new CreateRWDB(), + }; + + for (auto tester : testerList) { + tester->test(); + delete(tester); + } + + finalize(); + + LOG("========== End system_info_init_db test =========="); + return 0; +} diff --git a/test/init_db/system_info_init_db_test.h b/test/init_db/system_info_init_db_test.h new file mode 100644 index 0000000..5d45018 --- /dev/null +++ b/test/init_db/system_info_init_db_test.h @@ -0,0 +1,21 @@ +#ifndef __SYSTEM_INFO_INIT_DB_TEST_H__ +#define __SYSTEM_INFO_INIT_DB_TEST_H__ + +#define INIT_DB "system_info_init_db" + +#define SUCCEED 0 + +#define LOG(fmt, arg...) printf(fmt "\n", ##arg) + +#define BACKUP_DB_RO_PATH SYSTEM_INFO_DB_RO_PATH "_backup" +#define BACKUP_DB_RW_PATH SYSTEM_INFO_DB_RW_PATH "_backup" + +#define STRTYPE_BOOL "bool" +#define STRTYPE_INT "int" +#define STRTYPE_DOUBLE "double" +#define STRTYPE_STRING "string" + +#define STRBOOL_FALSE "false" +#define STRBOOL_TRUE "true" + +#endif /* __SYSTEM_INFO_INIT_DB_TEST_H__ */ diff --git a/test/init_db/tester.cpp b/test/init_db/tester.cpp new file mode 100644 index 0000000..0a16659 --- /dev/null +++ b/test/init_db/tester.cpp @@ -0,0 +1,141 @@ +#include "feature.h" +#include "system_info_init_db_test.h" +#include "tester.h" +#include "util.h" + +/********** Tester **********/ + +void Tester::test(void) +{ + int ret; + + LOG("[%s] Start", name.c_str()); + + ret = run(); + + LOG("[%s] Result : %d(%s)\n", name.c_str(), ret, + ret == SUCCEED ? "\x1b[32mPASSED\x1b[0m" : "\x1b[31mFAILED\x1b[0m"); +} + +/********** CreateDB **********/ + +int CreateDB::run(void) +{ + return util.forkAndExec(INIT_DB, nullptr); +} + +/********** InsertKey **********/ + +int InsertKey::run(void) +{ + int ret; + int dice; + std::string keyPrefix = "http://tizen.org/test/test.key."; + std::string key; + std::string type; + std::string value; + int valueLen; + Feature *feature = nullptr; + + for (int keyIndex = 0; keyIndex < 100; keyIndex++) { + key = keyPrefix + std::to_string(keyIndex); + + dice = (double)rand() / RAND_MAX * 2000000; // 0 ~ 2M + + /** + * In current, most of model-config features have boolean type. + * So, we insert other type features more. + */ + switch (dice % 10) { + case 0: + // Bool + type = STRTYPE_BOOL; + value = (dice % 2 == 1) ? STRBOOL_TRUE : STRBOOL_FALSE; + feature = new BoolFeature(key, value); + break; + case 1: + case 2: + case 3: + // Int + type = STRTYPE_INT; + value = std::to_string(dice - 1000000); // -1M ~ 1M + feature = new IntFeature(key, value); + break; + case 4: + case 5: + case 6: + // Double + type = STRTYPE_DOUBLE; + value = std::to_string(dice - 1000000.0); // -1.0M ~ 1.0M + feature = new DoubleFeature(key, value); + break; + case 7: + case 8: + case 9: + // String + type = STRTYPE_STRING; + valueLen = (dice % 100) + 1; // 1 ~ 100 + value.clear(); + value.reserve(valueLen); + do { + value += 't'; + } while (--valueLen); + feature = new StringFeature(key, value); + break; + default: + LOG("Invalid dice value (%d)", dice); + return EIO; + } + + featureList.push_back(feature); + + ret = util.updateDB(key, type, value); + if (ret != SUCCEED) { + LOG("Failed to insert key(%d)", ret); + return ret; + } + } + + return SUCCEED; +} + +/********** ModifyValue **********/ + +int ModifyValue::run(void) +{ + int ret; + + for (auto feature : featureList) { + ret = feature->modifyValue(); + if (ret != SUCCEED) { + LOG("Failed to modify value (%d)", ret); + return ret; + } + } + + return SUCCEED; +} + +/********** VerifyValue **********/ + +int VerifyValue::run(void) +{ + int ret; + + for (auto feature : featureList) { + ret = feature->verifyValue(); + if (ret != SUCCEED) { + LOG("Failed to verify value (%d)", ret); + return ret; + } + } + + return SUCCEED; +} + +/********** CreateRWDB **********/ + +int CreateRWDB::run(void) +{ + return util.forkAndExec(INIT_DB, "-i", MODEL_CONFIG_RO_PATH, "-o", SYSTEM_INFO_DB_RW_PATH, nullptr); +} diff --git a/test/init_db/tester.h b/test/init_db/tester.h new file mode 100644 index 0000000..54b7e64 --- /dev/null +++ b/test/init_db/tester.h @@ -0,0 +1,67 @@ +#ifndef __TESTER_H__ +#define __TESTER_H__ + +#include + +class Tester { +public: + Tester(std::string n) : name(n) {} + virtual ~Tester() {} + + /** + * @brief Test and print result + */ + void test(void); + +protected: + /** + * @brief Run test + * @retval SUCCEED on succeed, otherwise an error number + */ + virtual int run(void) = 0; + +private: + std::string name; +}; + +class CreateDB : public Tester { +public: + CreateDB() : Tester("Create DB") {} + +protected: + int run(void); +}; + +class InsertKey : public Tester { +public: + InsertKey() : Tester("Insert key") {} + +protected: + int run(void); +}; + +class ModifyValue : public Tester { +public: + ModifyValue() : Tester("Modify value") {} + +protected: + int run(void); +}; + +class VerifyValue : public Tester { +public: + VerifyValue() : Tester("Verify value") {} + +protected: + int run(void); +}; + +class CreateRWDB : public Tester { +public: + CreateRWDB() : Tester("Create RW DB") {} + +protected: + int run(void); +}; + +#endif /* __TESTER_H__ */ diff --git a/test/init_db/util.cpp b/test/init_db/util.cpp new file mode 100644 index 0000000..0fde55e --- /dev/null +++ b/test/init_db/util.cpp @@ -0,0 +1,194 @@ +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "feature.h" +#include "system_info_init_db_test.h" +#include "util.h" + +int Util::forkAndExec(const char *argv, ...) +{ + int ret; + pid_t pid; + int status; + va_list ap; + const char *arr[256]; + int numArg = 0; + + pid = fork(); + switch (pid) { + case -1: + LOG("fork failed"); + return EIO; + case 0: + // Execute program + va_start(ap, argv); + while (argv && numArg < 255) { + arr[numArg++] = argv; + argv = va_arg(ap, const char *); + } + va_end(ap); + arr[numArg] = nullptr; + + ret = execvp(arr[0], (char * const *)arr); + if (ret == -1) { + LOG("execv for %s failed (%d)", arr[0], errno); + ret = errno; + } else + ret = SUCCEED; + exit(ret); + break; + default: + // Wait until child is terminated + if (wait(&status) == -1) { + LOG("wait failed (%d)", errno); + return errno; + } + if (WIFEXITED(status) && WEXITSTATUS(status) == SUCCEED) + return SUCCEED; + else + return EIO; + break; + } + + return EFAULT; +} + +int Util::updateDB(std::string key, std::string type, std::string value) +{ + return forkAndExec(INIT_DB, + "-g", "platform", + "-k", key.c_str(), + "-t", type.c_str(), + "-v", value.c_str(), + nullptr); +} + +int Util::readModelConfig(void) +{ + int ret; + xmlDocPtr doc = nullptr; + xmlNodePtr nodeRoot = nullptr; + xmlNodePtr nodeTag = nullptr; + xmlNodePtr nodeKey = nullptr; + xmlNode *nodeCur = nullptr; + xmlChar *propName = nullptr; + xmlChar *propType = nullptr; + xmlChar *propValue = nullptr; + std::string name; + std::string type; + std::string value; + Feature *feature = nullptr; + int numBoolKey = 0; + int numIntKey = 0; + int numDoubleKey = 0; + int numStringKey = 0; + + // Read xml file + doc = xmlParseFile(MODEL_CONFIG_RO_PATH); + if (!doc) { + LOG("xmlParseFile failed"); + return ENOENT; + } + + nodeRoot = xmlDocGetRootElement(doc); + if (!nodeRoot) { + LOG("xmlDocGetRootElement failed"); + ret = ENOENT; + goto clean; + } + + if (xmlStrcmp(nodeRoot->name, (const xmlChar *)"model-config")) { + LOG("Failed to find model-config tag"); + ret = ENOENT; + goto clean; + } + + nodeTag = nodeRoot->xmlChildrenNode; + + for (nodeCur = nodeTag; nodeCur; nodeCur = nodeCur->next) { + if (!xmlStrcmp(nodeCur->name, (const xmlChar *)"platform")) { + nodeKey = nodeCur; + break; + } + } + + if (!nodeKey) { + LOG("Failed to find platform tag"); + ret = ENOENT; + goto clean; + } + + nodeKey = nodeKey->xmlChildrenNode; + + // Store each model-config feature + for (nodeCur = nodeKey; nodeCur; nodeCur = nodeCur->next) { + propName = xmlGetProp(nodeCur, (const xmlChar *)"name"); + propType = xmlGetProp(nodeCur, (const xmlChar *)"type"); + propValue = xmlNodeListGetString(doc, nodeCur->xmlChildrenNode, 1); + + if (!propName || !propType || !propValue) { + if (!propName && !propType && !propValue) + continue; + + LOG("Invalid feature : name(%s), type(%s), value(%s)", + (char *)propName, (char *)propType, (char *)propValue); + ret = EIO; + goto clean; + } + + name.assign((char *)propName); + type.assign((char *)propType); + value.assign((char *)propValue); + + if (!type.compare(STRTYPE_BOOL)) { + feature = new BoolFeature(name, value); + numBoolKey++; + } else if (!type.compare(STRTYPE_INT)) { + feature = new IntFeature(name, value); + numIntKey++; + } else if (!type.compare(STRTYPE_DOUBLE)) { + feature = new DoubleFeature(name, value); + numDoubleKey++; + } else if (!type.compare(STRTYPE_STRING)) { + feature = new StringFeature(name, value); + numStringKey++; + } else { + LOG("Invalid type : key(%s), type(%s)", name.c_str(), type.c_str()); + ret = EINVAL; + goto clean; + } + + featureList.push_back(feature); + + xmlFree(propValue); + xmlFree(propType); + xmlFree(propName); + } + + LOG("Number of model-config platform key : Bool(%d), Int(%d), Double(%d), String(%d), Total(%d)\n", + numBoolKey, numIntKey, numDoubleKey, numStringKey, + numBoolKey + numIntKey + numDoubleKey + numStringKey); + ret = SUCCEED; + +clean: + if (propValue) + xmlFree(propValue); + + if (propType) + xmlFree(propType); + + if (propName) + xmlFree(propName); + + if (doc) + xmlFreeDoc(doc); + + return ret; +} diff --git a/test/init_db/util.h b/test/init_db/util.h new file mode 100644 index 0000000..0cbb3b6 --- /dev/null +++ b/test/init_db/util.h @@ -0,0 +1,28 @@ +#ifndef __UTIL_H__ +#define __UTIL_H__ + +class Util { +public: + /** + * @brief Fork and execute program + * @retval SUCCEED on success, otherwise an error value + */ + static int forkAndExec(const char *argv, ...); + + /** + * @brief Update system-info DB + * @retval SUCCEED on success, otherwise an error value + */ + static int updateDB(std::string key, std::string type, std::string value); + + /** + * @brief Read model-config + * @detail Each feature is stored into the featureList + * @retval SUCCEED on success, otherwise an error value + */ + static int readModelConfig(void); +}; + +extern Util util; + +#endif /* __UTIL_H__ */