* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include <glib.h>
+#include <vconf.h>
#include <gtest/gtest.h>
#include <Plugin.h>
#include <modes_errors.h>
+#include "plugin-log.h"
#include "plugin-def.h"
MODES_NAMESPACE_USE;
extern "C" Plugin *objectCreate(void);
extern "C" void objectDelete(Plugin *plugin);
-TEST(PluginTest, setPluginVconfInt)
+class VconfPluginTest : public ::testing::Test {
+protected:
+ void SetUp() override
+ {
+ plugin = objectCreate();
+ loop = g_main_loop_new(NULL, FALSE);
+ }
+
+ void TearDown() override
+ {
+ objectDelete(plugin);
+ g_main_loop_unref(loop);
+ loop = NULL;
+ result = -1;
+ }
+
+ static void valChangedCb(const std::string &key, void *userData)
+ {
+ DBG("%s changed callback called!", key.c_str());
+ g_main_loop_quit(loop);
+ }
+
+ static void valChangedResetStoredCb(const std::string &key, void *userData)
+ {
+ DBG("%s changed callback called!", key.c_str());
+ result = MODES_ERROR_NONE;
+ }
+
+ static void valChangedResetCb(const std::string &key, void *userData)
+ {
+ DBG("%s changed callback called!", key.c_str());
+ g_main_loop_quit(loop);
+ }
+
+ static gboolean changedCallbackidler(gpointer data)
+ {
+ DBG("start change the value db/setting/mode");
+ vconf_set_int("db/setting/psmode", 7);
+ return G_SOURCE_REMOVE;
+ }
+
+ static int result;
+ static GMainLoop *loop;
+ static Plugin *plugin;
+ static int oldval;
+};
+
+int VconfPluginTest::oldval = 0;
+int VconfPluginTest::result = -1;
+Plugin *VconfPluginTest::plugin = nullptr;
+GMainLoop *VconfPluginTest::loop = NULL;
+
+
+TEST_F(VconfPluginTest, setPluginVconfInt)
{
int ret;
int oldval;
- Plugin *plugin = objectCreate();
ret = plugin->set("db.setting.psmode", 3, nullptr);
EXPECT_EQ(ret, MODES_ERROR_NONE);
ret = plugin->set("db.setting.psmode", 1, &oldval);
EXPECT_EQ(ret, MODES_ERROR_NONE);
EXPECT_EQ(oldval, 3);
-
- objectDelete(plugin);
}
-TEST(PluginTest, setPluginVconfDouble)
+TEST_F(VconfPluginTest, setPluginVconfDouble)
{
int ret;
double oldval;
- Plugin *plugin = objectCreate();
ret = plugin->set("db.system.timechange_external", 1.0, nullptr);
EXPECT_EQ(ret, MODES_ERROR_NONE);
ret = plugin->set("db.system.timechange_external", 0.0, &oldval);
EXPECT_EQ(ret, MODES_ERROR_NONE);
EXPECT_EQ(oldval, 1.0);
-
- objectDelete(plugin);
}
-TEST(PluginTest, setPluginVconfBool)
+TEST_F(VconfPluginTest, setPluginVconfBool)
{
int ret;
bool oldval;
- Plugin *plugin = objectCreate();
ret = plugin->set("db.setting.sound.button_sounds", false, nullptr);
EXPECT_EQ(ret, MODES_ERROR_NONE);
ret = plugin->set("db.setting.sound.button_sounds", true, &oldval);
EXPECT_EQ(ret, MODES_ERROR_NONE);
EXPECT_EQ(oldval, false);
-
- objectDelete(plugin);
}
-TEST(PluginTest, setPluginVconfStr)
+TEST_F(VconfPluginTest, setPluginVconfStr)
{
int ret;
std::string oldval;
- Plugin *plugin = objectCreate();
std::string testVal = "org.tizen.menu-screen.test";
ret = plugin->set("db.setting.menuscreen.package_name", testVal, nullptr);
ret = plugin->set("db.setting.menuscreen.package_name", "org.tizen.menu-screen", &oldval);
EXPECT_EQ(ret, MODES_ERROR_NONE);
EXPECT_EQ(oldval.compare(testVal), 0);
+}
+
+TEST_F(VconfPluginTest, callbackPluginVconf)
+{
+ vconf_get_int("db/setting/psmode", &oldval);
+ int ret = plugin->setChangedCallback(valChangedCb,
+ "db.setting.psmode", nullptr);
+ EXPECT_EQ(ret, MODES_ERROR_NONE);
+ g_idle_add(changedCallbackidler, nullptr);
+ g_main_loop_run(loop);
+
+ ret = plugin->unSetChangedCallback(valChangedCb, "db.setting.psmode", nullptr);
+ EXPECT_EQ(ret, MODES_ERROR_NO_DATA);
+ vconf_set_int("db/setting/psmode", oldval);
+}
+
+TEST_F(VconfPluginTest, callbackPluginVconfReset)
+{
+ int ret;
+ ret = plugin->set("db.setting.psmode", 4, &oldval);
+ EXPECT_EQ(ret, MODES_ERROR_NONE);
+ ret = plugin->setChangedCallback(valChangedResetStoredCb, "db.setting.psmode", nullptr);
+ EXPECT_EQ(ret, MODES_ERROR_NONE);
+ ret = plugin->set("db.setting.psmode", 2, nullptr);
+ EXPECT_EQ(ret, MODES_ERROR_NONE);
+ EXPECT_EQ(MODES_ERROR_NONE, result);
+ ret = plugin->setChangedCallback(valChangedResetCb, "db.setting.psmode", nullptr);
+ EXPECT_EQ(ret, MODES_ERROR_NONE);
+ g_idle_add(changedCallbackidler, nullptr);
+ g_main_loop_run(loop);
- objectDelete(plugin);
+ DBG("loop end and unregister callback start");
+ ret = plugin->unSetChangedCallback(valChangedResetCb, "db.setting.psmode", nullptr);
+ EXPECT_EQ(ret, MODES_ERROR_NO_DATA);
+ vconf_set_int("db/setting/psmode", oldval);
+ EXPECT_EQ(MODES_ERROR_NONE, result);
}
int main(int argc, char **argv) {
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <vconf.h>
-#include <modes_errors.h>
+#include <map>
#include <string>
#include <algorithm>
+#include <vconf.h>
+#include <modes_errors.h>
#include <Plugin.h>
#include "plugin-log.h"
#include "plugin-def.h"
MODES_NAMESPACE_USE;
class VconfPlugin : public Plugin {
-private:
-
public:
VconfPlugin();
double getDouble(const std::string &key) override;
bool getBool(const std::string &key) override;
std::string getString(const std::string &key) override;
+
+ int setChangedCallback(valueChangedCb callback, const std::string &key, void *userData);
+ int unSetChangedCallback(valueChangedCb callback, const std::string &key, void *userData);
+private:
+ struct CallbackData {
+ void *userData;
+ valueChangedCb *callback;
+ };
+
+ int handleChange(const std::string &key);
+ static void vconfChangedCallback(keynode_t *node, void *userData);
+
+ static std::map<std::string, CallbackData> callbackMap;
};
extern "C" API Plugin *objectCreate(void)
delete plugin;
}
+std::map<std::string, VconfPlugin::CallbackData> VconfPlugin::callbackMap;
+
VconfPlugin::VconfPlugin()
{
setName("vconf");
}
}
+ ret = handleChange(newKey);
+ if (MODES_ERROR_NONE != ret) {
+ ERR("handleChange(%s) Fail(%d)", newKey.c_str(), ret);
+ return ret;
+ }
+
ret = vconf_set_int(newKey.c_str(), val);
if (0 != ret) {
ERR("vconf_set_int(%s, %d) Fail(%d)", newKey.c_str(), val, ret);
}
}
+ ret = handleChange(newKey);
+ if (MODES_ERROR_NONE != ret) {
+ ERR("handleChange(%s) Fail(%d)", newKey.c_str(), ret);
+ return ret;
+ }
+
ret = vconf_set_dbl(newKey.c_str(), val);
if (0 != ret) {
ERR("vconf_set_int(%s, %lf) Fail(%d)", newKey.c_str(), val, ret);
*oldVal = prev;
}
+ ret = handleChange(newKey);
+ if (MODES_ERROR_NONE != ret) {
+ ERR("handleChange(%s) Fail(%d)", newKey.c_str(), ret);
+ return ret;
+ }
+
ret = vconf_set_bool(newKey.c_str(), val);
if (0 != ret) {
ERR("vconf_set_bool(%s, %d) Fail(%d)", newKey.c_str(), val, ret);
free(prevStr);
}
+ int ret = handleChange(newKey);
+ if (MODES_ERROR_NONE != ret) {
+ ERR("handleChange(%s) Fail(%d)", newKey.c_str(), ret);
+ return ret;
+ }
- int ret = vconf_set_str(newKey.c_str(), val.c_str());
+ ret = vconf_set_str(newKey.c_str(), val.c_str());
if (0 != ret) {
ERR("vconf_set_str(%s, %s) Fail(%d)", newKey.c_str(), val.c_str(), ret);
return MODES_ERROR_SYSTEM;
return retStr;
}
+
+int VconfPlugin::setChangedCallback(valueChangedCb callback, const std::string &key, void *userData)
+{
+ std::string newKey(key);
+ std::replace(newKey.begin(), newKey.end(), '.', '/');
+
+ callbackMap[newKey].userData = userData;
+ callbackMap[newKey].callback = callback;
+
+ int ret = vconf_notify_key_changed(newKey.c_str(), VconfPlugin::vconfChangedCallback, &callbackMap[newKey]);
+ if (VCONF_OK != ret) {
+ ERR("vconf_notify_key_changed(%s) Fail(%s)", newKey.c_str(), get_error_message(ret));
+ return MODES_ERROR_SYSTEM;
+ }
+
+ DBG("setChangedCallback(%s) Success", newKey.c_str());
+ return MODES_ERROR_NONE;
+}
+
+int VconfPlugin::unSetChangedCallback(valueChangedCb callback, const std::string &key, void *userData)
+{
+ std::string newKey(key);
+ std::replace(newKey.begin(), newKey.end(), '.', '/');
+
+ auto found = callbackMap.find(newKey);
+ if (found == callbackMap.end()) {
+ ERR("No Changed Callback(%s)", newKey.c_str());
+ return MODES_ERROR_NO_DATA;
+ }
+
+ callbackMap.erase(found);
+ int ret = vconf_ignore_key_changed(newKey.c_str(), VconfPlugin::vconfChangedCallback);
+ if (VCONF_OK != ret) {
+ ERR("vconf_ignore_key_changed(%s) Fail(%s)", newKey.c_str(), get_error_message(ret));
+ return MODES_ERROR_SYSTEM;
+ }
+
+ DBG("unSetChangedCallback(%s) Success", newKey.c_str());
+ return MODES_ERROR_NONE;
+}
+
+int VconfPlugin::handleChange(const std::string &key)
+{
+ auto found = callbackMap.find(key);
+ if (callbackMap.end() != found) {
+ DBG("Acition(%s) already exist", key.c_str());
+ found->second.callback(key, found->second.userData);
+
+ callbackMap.erase(found);
+ int ret = vconf_ignore_key_changed(key.c_str(), VconfPlugin::vconfChangedCallback);
+ if (VCONF_OK != ret) {
+ ERR("vconf_ignore_key_changed(%s) Fail(%s)", key.c_str(), get_error_message(ret));
+ return MODES_ERROR_SYSTEM;
+ }
+ }
+ return MODES_ERROR_NONE;
+}
+
+void VconfPlugin::vconfChangedCallback(keynode_t *node, void *userData)
+{
+ CallbackData *cbData = (CallbackData*)userData;
+
+ RET_IF(NULL == userData);
+
+ auto found = callbackMap.find(node->keyname);
+ if (&(found->second) != cbData) {
+ ERR("Unknown callbackData(%s)", node->keyname);
+ return;
+ }
+
+ cbData->callback(node->keyname, cbData->userData);
+ DBG("Action(%s) is Changed", node->keyname);
+
+ callbackMap.erase(found);
+ int ret = vconf_ignore_key_changed(node->keyname, VconfPlugin::vconfChangedCallback);
+ if (VCONF_OK != ret)
+ ERR("vconf_ignore_key_changed(%s) Fail(%s)", node->keyname, get_error_message(ret));
+}