ADD_DEFINITIONS("-DLIBPATH=\"${LIB_INSTALL_DIR}\"")
ADD_DEFINITIONS("-DSYSTEM_INFO_DB_RO_PATH=\"${DB_RO_PATH}\"")
ADD_DEFINITIONS("-DSYSTEM_INFO_DB_RW_PATH=\"${DB_RW_PATH}\"")
+ADD_DEFINITIONS(-D_GNU_SOURCE) # to make scandirat() available
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=/usr/lib")
ADD_SUBDIRECTORY(src/tizenid)
ADD_SUBDIRECTORY(src/init_db)
ADD_SUBDIRECTORY(src/test)
+ADD_SUBDIRECTORY(src/testplugin)
IF(UNIX)
%description devel
+%package testplugin
+Summary: System-info test plugin package
+Group: Development/System
+
+%description testplugin
+A System Information test plugins
+
%package test
Summary: System-info test package
Group: Development/System
Requires: %{name}
+Requires: %{name}-testplugin
%description test
A System Information library test tool
%{_libdir}/pkgconfig/*.pc
%{_libdir}/libcapi-system-info.so
+%files testplugin
+%{_libdir}/libsystem_info_plugins/libsystem_info_test_plugin.so
+%{_libdir}/libsystem_info_plugins/libsystem_info_test_plugin2.so
+
%files test
%{_bindir}/system_info_test
+%{_bindir}/system_info_external_plugin_test.sh
+%attr(0755,root,-) %{_bindir}/system_info_external_plugin_test.sh
+
%if 0%{?gcov:1}
%files -n system-info-gcov
#include <string.h>
#include <unistd.h>
#include <dlfcn.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdlib.h>
#define BUF_MAX 256
+#define EXTERNAL_PLUGINS_DIR "/usr/lib/libsystem_info_plugins"
#define EXTERNAL_SYSTEM_INFO "/usr/lib/libsystem-info-external-plugin.so"
-
//LCOV_EXCL_START
-int external_get_value(const char *tag, const char *key,
- const char *type, char **val)
+static int plugin_filter(const struct dirent *de)
+{
+ if (NULL == de)
+ return 0;
+
+ if (de->d_type != DT_REG && de->d_type != DT_LNK)
+ return 0;
+
+ return 1;
+}
+
+void external_free_plugin_names(char **tab, int count)
+{
+ for (int i = 0; i < count; ++i)
+ free(tab[i]);
+ free(tab);
+}
+
+char **external_get_plugin_names(size_t *plugin_count)
+{
+ char **tab = NULL;
+ struct dirent **entries = NULL;
+ int count = 0;
+ const int dir_fd = open(EXTERNAL_PLUGINS_DIR, O_DIRECTORY | O_RDONLY);
+ if (dir_fd >= 0) {
+ count = scandirat(dir_fd, EXTERNAL_PLUGINS_DIR, &entries, plugin_filter, alphasort);
+ if (!entries || count < 0) {
+ count = 0;
+ _E("Unable to get additional plugins from directory " EXTERNAL_PLUGINS_DIR ": %m");
+ }
+ close(dir_fd);
+ }
+
+ int tab_count = count + 1;
+ tab = (char **)calloc(sizeof(char *), tab_count);
+ if (!tab)
+ goto out_free_entries;
+
+ tab[0] = strdup(EXTERNAL_SYSTEM_INFO);
+ if (!tab[0]) {
+ _E("strdup failed for alloc plugin path " EXTERNAL_SYSTEM_INFO ", stop listing");
+ external_free_plugin_names(tab, 0);
+ tab = NULL;
+ goto out_free_entries;
+ }
+
+ for (int ei = 0, ti = 1; ei < count; ++ei, ++ti)
+ if (asprintf(&tab[ti], EXTERNAL_PLUGINS_DIR "/%s", entries[ei]->d_name) < 0) {
+ _E("asprintf failed for alloc plugin path (" EXTERNAL_PLUGINS_DIR "/%s), stop listing", entries[ei]->d_name);
+ external_free_plugin_names(tab, ti);
+ tab = NULL;
+ goto out_free_entries;
+ }
+
+ if (plugin_count)
+ *plugin_count = tab_count;
+
+out_free_entries:
+ for (int i = 0; i < count; ++i)
+ free(entries[i]);
+ free(entries);
+
+ return tab;
+}
+
+void *external_open_plugin(const char *so_path, const system_info_external_plugin_interface **plugin)
{
+ if (!plugin)
+ return NULL;
+
void *handle = NULL;
- int ret;
- char buf[BUF_MAX];
- const system_info_external_plugin_interface *plugin;
const system_info_external_plugin_interface *(*system_info_get_external_plugin_interface)(void);
-
- if (access(EXTERNAL_SYSTEM_INFO, F_OK) != 0) {
- _E("No external system info library");
- return SYSTEM_INFO_ERROR_IO_ERROR;
+ if (access(so_path, F_OK) != 0) {
+ _E("No external system info library at path '%s'", so_path);
+ return NULL;
}
- handle = dlopen(EXTERNAL_SYSTEM_INFO, RTLD_NOW);
+ handle = dlopen(so_path, RTLD_NOW);
if (!handle) {
- _E("dlopen(%s) failed(%s)", EXTERNAL_SYSTEM_INFO, dlerror());
- ret = SYSTEM_INFO_ERROR_IO_ERROR;
- goto out;
+ _E("dlopen(%s) failed(%s)", so_path, dlerror());
+ goto out_err;
}
system_info_get_external_plugin_interface = dlsym(handle, "system_info_get_external_plugin_interface");
if (!system_info_get_external_plugin_interface) {
_E("dlsym failed(%s)", dlerror());
- ret = SYSTEM_INFO_ERROR_IO_ERROR;
- goto out;
+ goto out_err;
}
- plugin = system_info_get_external_plugin_interface();
- if (!plugin) {
+ *plugin = system_info_get_external_plugin_interface();
+ if (!*plugin) {
_E("Failed to get plugin");
- ret = SYSTEM_INFO_ERROR_IO_ERROR;
- goto out;
+ goto out_err;
}
+ return handle;
+
+out_err:
+ if (handle)
+ dlclose(handle);
+
+ return NULL;
+}
+
+int external_get_plugin_value(const char *so_path, const char *tag, const char *key,
+ const char *type, char **val)
+{
+ int ret;
+ char buf[BUF_MAX];
+ const system_info_external_plugin_interface *plugin = NULL;
+ void *handle = external_open_plugin(so_path, &plugin);
+
+ if (!handle)
+ return SYSTEM_INFO_ERROR_IO_ERROR;
+
if (plugin->get_value_external == NULL) {
_E("Invalid plugin function");
ret = SYSTEM_INFO_ERROR_IO_ERROR;
}
ret = plugin->get_value_external(tag, key, type, buf, sizeof(buf));
- if (ret < 0) {
- _E("Failed to get value from plugin (ret:%d)", ret);
+ if (ret < 0) { // TODO: add special value when plugin does not provide the key
+ _I("Key %s is not provided by '%s' plugin (ret:%d)", key, so_path, ret);
ret = SYSTEM_INFO_ERROR_IO_ERROR;
goto out;
}
return ret;
}
-int external_get_type(const char *tag, const char *key, char **type)
+int external_get_value(const char *tag, const char *key, const char *type, char **val)
{
- void *handle = NULL;
- int ret;
- char buf[BUF_MAX];
- const system_info_external_plugin_interface *plugin;
- const system_info_external_plugin_interface *(*system_info_get_external_plugin_interface)(void);
+ size_t plugin_count = 0;
+ int ret = SYSTEM_INFO_ERROR_IO_ERROR;
+ char **tab = external_get_plugin_names(&plugin_count);
+ for (size_t i = 0; i < plugin_count && ret != SYSTEM_INFO_ERROR_NONE; ++i)
+ ret = external_get_plugin_value(tab[i], tag, key, type, val);
- if (access(EXTERNAL_SYSTEM_INFO, F_OK) != 0) {
- _E("No external system info library");
- return SYSTEM_INFO_ERROR_IO_ERROR;
- }
+ external_free_plugin_names(tab, plugin_count);
- handle = dlopen(EXTERNAL_SYSTEM_INFO, RTLD_NOW);
- if (!handle) {
- _E("dlopen(%s) failed(%s)", EXTERNAL_SYSTEM_INFO, dlerror());
- ret = SYSTEM_INFO_ERROR_IO_ERROR;
- goto out;
- }
+ if (ret != SYSTEM_INFO_ERROR_NONE)
+ _E("Key value (%s) not obtained by any plugin.", key);
- system_info_get_external_plugin_interface = dlsym(handle, "system_info_get_external_plugin_interface");
- if (!system_info_get_external_plugin_interface) {
- _E("dlsym failed(%s)", dlerror());
- ret = SYSTEM_INFO_ERROR_IO_ERROR;
- goto out;
- }
+ return ret;
+}
- plugin = system_info_get_external_plugin_interface();
- if (!plugin) {
- _E("Failed to get plugin");
- ret = SYSTEM_INFO_ERROR_IO_ERROR;
- goto out;
- }
+int external_get_plugin_type(const char *so_path, const char *tag, const char *key,
+ const char *type, char **val)
+{
+ int ret;
+ char buf[BUF_MAX];
+ const system_info_external_plugin_interface *plugin = NULL;
+ void *handle = external_open_plugin(so_path, &plugin);
+
+ if (!handle)
+ return SYSTEM_INFO_ERROR_IO_ERROR;
if (plugin->get_type_external == NULL) {
_E("Invalid plugin function");
}
ret = plugin->get_type_external(tag, key, buf, sizeof(buf));
- if (ret < 0) {
- _E("Failed to get value from plugin (ret:%d)", ret);
+ if (ret < 0) { // TODO: add special value when plugin does not provide the key
+ _I("Key %s is not provided by '%s' plugin (ret:%d)", key, so_path, ret);
ret = SYSTEM_INFO_ERROR_IO_ERROR;
goto out;
}
- *type = strdup(buf);
- if (*type == NULL) {
+ *val = strdup(buf);
+ if (*val == NULL) {
_E("strdup() failed");
ret = SYSTEM_INFO_ERROR_OUT_OF_MEMORY;
goto out;
return ret;
}
+
+int external_get_type(const char *tag, const char *key, char **type)
+{
+ size_t plugin_count = 0;
+ int ret = SYSTEM_INFO_ERROR_IO_ERROR;
+
+ char **tab = external_get_plugin_names(&plugin_count);
+ for (size_t i = 0; i < plugin_count && ret != SYSTEM_INFO_ERROR_NONE; ++i)
+ ret = external_get_plugin_type(tab[i], tag, key, NULL, type);
+
+ external_free_plugin_names(tab, plugin_count);
+
+ if (ret != SYSTEM_INFO_ERROR_NONE)
+ _E("Key type (%s) not obtained by any plugin.", key);
+
+ return ret;
+}
+
//LCOV_EXCL_STOP
TARGET_LINK_LIBRARIES(${SYSTEM_INFO_TEST} ${SYSTEM_INFO_TEST_pkgs_LDFLAGS} "-L${CMAKE_SOURCE_DIR} -lcapi-system-info")
INSTALL(TARGETS ${SYSTEM_INFO_TEST} DESTINATION bin)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/src/test/system_info_external_plugin_test.sh DESTINATION bin)
+
--- /dev/null
+#!/bin/bash
+
+function test_key_type_string_cmd() {
+ cmd_result="$(system_info_test -g custom -t string -k sysinfotest_ks)"
+ name="'$FUNCNAME'"
+}
+
+function test_string_not_int_cmd() {
+ cmd_result="$(system_info_test -g custom -t int -k sysinfotest_ks)"
+ name="'$FUNCNAME'"
+}
+
+function test_string_not_double_cmd() {
+ cmd_result="$(system_info_test -g custom -t double -k sysinfotest_ks)"
+ name="'$FUNCNAME'"
+}
+
+function test_string_not_bool_cmd() {
+ cmd_result="$(system_info_test -g custom -t bool -k sysinfotest_ks)"
+ name="'$FUNCNAME'"
+}
+
+function test_key_type_int_cmd() {
+ cmd_result="$(system_info_test -g custom -t int -k sysinfotest_ki)"
+ name="'$FUNCNAME'"
+}
+
+function test_key_type_double_cmd() {
+ cmd_result="$(system_info_test -g custom -t double -k sysinfotest_kd)"
+ name="'$FUNCNAME'"
+}
+
+function test_key_type_bool_cmd() {
+ cmd_result="$(system_info_test -g custom -t bool -k sysinfotest_kb)"
+ name="'$FUNCNAME'"
+}
+
+function test_bool_not_string_cmd() {
+ cmd_result="$(system_info_test -g custom -t string -k sysinfotest_kb)"
+ name="'$FUNCNAME'"
+}
+
+function test_bool_not_int_cmd() {
+ cmd_result="$(system_info_test -g custom -t int -k sysinfotest_kb)"
+ name="'$FUNCNAME'"
+}
+
+function test_bool_not_double_cmd() {
+ cmd_result="$(system_info_test -g custom -t double -k sysinfotest_kb)"
+ name="'$FUNCNAME'"
+}
+
+function test_second_plugin_str_cmd() {
+ cmd_result="$(system_info_test -g custom -t string -k sysinfotest_vks_custom)"
+ name="'$FUNCNAME'"
+}
+
+function test_right_plugin_str_cmd() {
+ cmd_result="$(system_info_test -g custom -t string -k sysinfotest_kvs)"
+ name="'$FUNCNAME'"
+}
+
+function get_cmd_result() {
+ check_result="$(echo $1 | cut -d'(' -f6 | cut -d')' -f1)"
+}
+
+function check_file_exists() {
+ cmd_result="$(test -s $1 && echo 'exists' || echo 'not')"
+ name="'$FUNCNAME' $1"
+}
+
+function check_command_exists() {
+ command_exists="$(type -p system_info_test)"
+}
+
+function check_result() {
+ local test_cmd=$1
+ local expected_result=$2
+
+ $test_cmd
+ get_cmd_result "$cmd_result"
+
+ #check if a variable is a number (formating cmd output)
+ re='^[+-]?[0-9]+([.][0-9]+)?$'
+ if [[ $check_result =~ $re ]] ; then
+ check_result="$(printf '%.2f' $check_result)"
+ if [[ $expected_result =~ $re ]] ; then
+ expected_result="$(printf '%.2f' $expected_result)"
+ fi
+ fi
+
+ sign='='
+ nsign='!'
+ if [[ $# -ge 3 && $3 == '!' ]]; then
+ nsign=$sign
+ sign=$3
+ fi
+ if [[ $check_result == '' ]]; then
+ check_result='EMPTY_RESULT'
+ fi
+ if [[ ( $check_result != 'EMPTY_RESULT' && ( $sign == '!' && "$check_result" != "$expected_result" ) || ( "$check_result" == "$expected_result" ) ) ]]; then
+ echo -e '\033[32m[' ' OK ' ']\e[0m' "$name:\t" "$sign('$expected_result')"
+ else
+ echo -e '\033[31m[' 'FAIL' ']\e[0m' "$name:\t" "('\033[31m$check_result\e[0m'" "$nsign=" "'\033[32m$expected_result\e[0m')"
+ return_code=1
+ fi
+}
+
+check_command_exists result
+if [ -z "$command_exists" ]; then
+ exit 1
+fi
+
+return_code=0
+
+PLUGIN_FILE='/usr/lib/libsystem_info_plugins/libsystem_info_test_plugin.so'
+check_result "check_file_exists $PLUGIN_FILE" 'exists'
+PLUGIN_FILE='/usr/lib/libsystem_info_plugins/libsystem_info_test_plugin2.so'
+check_result "check_file_exists $PLUGIN_FILE" 'exists'
+
+check_result test_key_type_string_cmd 'plugin'
+check_result test_string_not_int_cmd 'ERROR : -22'
+check_result test_string_not_double_cmd 'ERROR : -22'
+check_result test_string_not_bool_cmd 'ERROR : -22'
+check_result test_key_type_int_cmd '1'
+check_result test_key_type_double_cmd '2.0'
+check_result test_key_type_bool_cmd '1'
+check_result test_bool_not_string_cmd 'ERROR : -22'
+check_result test_bool_not_int_cmd 'ERROR : -22'
+check_result test_bool_not_double_cmd 'ERROR : -22'
+check_result test_second_plugin_str_cmd 'various key'
+check_result test_right_plugin_str_cmd 'first_in_lexicographical_order'
+check_result test_right_plugin_str_cmd 'second_in_lexicographical_order' '!'
+check_result test_right_plugin_str_cmd 'ERROR : -22' '!'
+
+exit $return_code
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+SET(SI_PLUGIN "system_info_test_plugin")
+
+SET(SRCS ${CMAKE_SOURCE_DIR}/src/testplugin/plugin_test.c)
+
+INCLUDE_DIRECTORIES(include)
+
+ADD_LIBRARY(${SI_PLUGIN} MODULE ${SRCS})
+SET_TARGET_PROPERTIES(${SI_PLUGIN} PROPERTIES COMPILE_FLAGS -DPLUGIN_FIRST)
+ADD_LIBRARY(${SI_PLUGIN}2 MODULE ${SRCS})
+
+INSTALL(TARGETS ${SI_PLUGIN} DESTINATION ${LIB_INSTALL_DIR}/libsystem_info_plugins)
+INSTALL(TARGETS ${SI_PLUGIN}2 DESTINATION ${LIB_INSTALL_DIR}/libsystem_info_plugins)
--- /dev/null
+#include <string.h>
+#include <system_info_intf.h>
+
+#include "system_info_type.h"
+
+#define VALUES_COUNT (sizeof value_descriptors / sizeof *value_descriptors)
+
+#ifdef PLUGIN_FIRST
+ #define PLUGIN_STRING_VALUE "first_in_lexicographical_order"
+ #define PLUGIN_STRING_KEY ""
+#else
+ #define PLUGIN_STRING_VALUE "second_in_lexicographical_order"
+ #define PLUGIN_STRING_KEY "_custom"
+#endif
+
+const struct entity {
+ const char *key;
+ const char *type;
+ const char *value;
+} value_descriptors[] = {
+ { "sysinfotest_kvs", TYPE_STR, PLUGIN_STRING_VALUE },
+ { "sysinfotest_vks" PLUGIN_STRING_KEY, TYPE_STR, "various key" },
+ { "sysinfotest_ks", TYPE_STR, "plugin" },
+ { "sysinfotest_ki", TYPE_INT, "1" },
+ { "sysinfotest_kd", TYPE_DBL, "2.0" },
+ { "sysinfotest_kb", TYPE_BOOL, "true" }
+};
+
+static int get_value(const char *tag, const char *key, const char *type, char *buf, unsigned int len)
+{
+ if (key && type)
+ for (size_t i = 0; i < VALUES_COUNT; ++i)
+ if (!strcmp(key, value_descriptors[i].key) && !strcmp(type, value_descriptors[i].type)) {
+ if (!strncpy(buf, value_descriptors[i].value, len))
+ return SYSTEM_INFO_ERROR_INVALID_PARAMETER;
+ return SYSTEM_INFO_ERROR_NONE;
+ }
+ return SYSTEM_INFO_ERROR_IO_ERROR;
+}
+
+static int get_type(const char *tag, const char *key, char *buf, unsigned int len)
+{
+ if (key)
+ for (size_t i = 0; i < VALUES_COUNT; ++i)
+ if (!strcmp(key, value_descriptors[i].key)) {
+ if (!strncpy(buf, value_descriptors[i].type, len))
+ return SYSTEM_INFO_ERROR_INVALID_PARAMETER;
+ return SYSTEM_INFO_ERROR_NONE;
+ }
+ return SYSTEM_INFO_ERROR_IO_ERROR;
+}
+
+const system_info_external_plugin_interface intf = {
+ .get_value_external = get_value,
+ .get_type_external = get_type,
+};
+
+__attribute__ ((visibility ("default")))
+const system_info_external_plugin_interface *system_info_get_external_plugin_interface(void)
+{
+ return &intf;
+}