add notification API
authorYoungjae Shin <yj99.shin@samsung.com>
Fri, 11 Oct 2019 01:58:41 +0000 (10:58 +0900)
committerYoungjae Shin <yj99.shin@samsung.com>
Wed, 18 Mar 2020 08:53:50 +0000 (17:53 +0900)
19 files changed:
client/mdsc_apply_mode.c
client/mdsc_dbus.c
client/mdsc_dbus.h
client/mdsc_noti_mode.c [new file with mode: 0644]
client/mdsc_register_mode.c
client/mdsc_undo_mode.c
common/dbus.xml
include/modes.h
include/modes_errors.h
supervisor/Mode.cpp
supervisor/Mode.h
supervisor/RequestHandler.cpp
supervisor/TAction.h
supervisor/TActionRule.h
unittest/CMakeLists.txt
unittest/modes-gtest-run.sh
unittest/modes_test_client.cpp
unittest/modes_test_noti.cpp [new file with mode: 0644]
unittest/modes_test_parser.cpp

index 630a7c9..62cf89b 100644 (file)
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 #include "modes.h"
+
 #include <glib.h>
 #include "mdsc.h"
 #include "mdsc_dbus.h"
@@ -44,7 +45,7 @@ API int modes_apply_mode(const char *name)
 
        RETV_IF(NULL == name, MODES_ERROR_INVALID_PARAMETER);
 
-       dbus_handle = _mdsc_dbus_start();
+       dbus_handle = mdsc_dbus_start();
        if (NULL == dbus_handle) {
                ERR("_mdsc_dbus_start() Fail");
                return MODES_ERROR_SYSTEM;
@@ -56,7 +57,7 @@ API int modes_apply_mode(const char *name)
                return ret;
        }
 
-       _mdsc_dbus_stop(dbus_handle);
+       mdsc_dbus_stop(dbus_handle);
 
        return MODES_ERROR_NONE;
 }
index e7bf24d..a31cffe 100644 (file)
  * limitations under the License.
  */
 #include "mdsc_dbus.h"
+
 #include <glib.h>
 #include "mdsc.h"
 #include "common/dbus.h"
 #include "common/dbus_def.h"
 
-mdsDbus* _mdsc_dbus_start()
+static mdsDbus *mdsc_proxy = NULL;
+static int mdsc_dbus_cnt = 0;
+
+mdsDbus* mdsc_dbus_start()
 {
+       if (mdsc_proxy) {
+               DBG("bus is already connected");
+               mdsc_dbus_cnt++;
+               return mdsc_proxy;
+       }
+
        GError *gdbusErr = NULL;
-       mdsDbus *ret = mds_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
+       mdsc_proxy = mds_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
                        G_DBUS_PROXY_FLAGS_NONE, MODES_DBUS_INTERFACE, MODES_DBUS_OBJPATH, NULL, &gdbusErr);
-       if (NULL == ret) {
+       if (NULL == mdsc_proxy) {
                ERR("mds_dbus_proxy_new_for_bus_sync() Fail(%s)", gdbusErr ? gdbusErr->message : "unknown");
                g_error_free(gdbusErr);
                return NULL;
        }
-       return ret;
+       return mdsc_proxy;
 }
 
-void _mdsc_dbus_stop(mdsDbus *handle)
+void mdsc_dbus_stop(mdsDbus *handle)
 {
+       //TODO: I'm not sure when the handle should be released.
+       if (mdsc_dbus_cnt) {
+               mdsc_dbus_cnt--;
+               return;
+       }
+
        if (handle)
                g_object_unref(handle);
+
+       mdsc_proxy = NULL;
 }
index 2a57882..4584fdd 100644 (file)
@@ -17,6 +17,6 @@
 
 #include "common/dbus.h"
 
-mdsDbus* _mdsc_dbus_start();
-void _mdsc_dbus_stop(mdsDbus *handle);
+mdsDbus* mdsc_dbus_start();
+void mdsc_dbus_stop(mdsDbus *handle);
 
diff --git a/client/mdsc_noti_mode.c b/client/mdsc_noti_mode.c
new file mode 100644 (file)
index 0000000..ce35018
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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 "modes.h"
+
+#include <glib.h>
+#include "mdsc.h"
+#include "mdsc_dbus.h"
+
+struct mdsc_noti_data_s {
+       modes_noti_fn cb;
+       void *user_data;
+};
+
+static gulong mdsc_noti_signal_ID = 0;
+static struct mdsc_noti_data_s mdsc_noti_data;
+
+static void _on_changed_mode(mdsDbus *mdsc_dbus, const char *mode, int state, gpointer user_data)
+{
+       RET_IF(NULL == user_data);
+
+       mdsc_noti_data.cb(mode, state, mdsc_noti_data.user_data);
+}
+
+API int modes_subscribe_mode_changes(modes_noti_fn cb, void *user_data)
+{
+       RETV_IF(0 != mdsc_noti_signal_ID, MODES_ERROR_ALREADY);
+
+       mdsDbus *dbus_handle = mdsc_dbus_start();
+       if (NULL == dbus_handle) {
+               ERR("_mdsc_dbus_start() Fail");
+               return MODES_ERROR_SYSTEM;
+       }
+
+       mdsc_noti_data.cb = cb;
+       mdsc_noti_data.user_data = user_data;
+
+       mdsc_noti_signal_ID = g_signal_connect(dbus_handle,
+               "changed-mode",
+               G_CALLBACK(_on_changed_mode),
+               NULL);
+
+       return MODES_ERROR_NONE;
+}
+
+//TODO: modes_noti_disconnect(ModesNotiFunc cb, void *user_data)
+API void modes_unsubscribe_mode_changes()
+{
+       RET_IF(0 == mdsc_noti_signal_ID);
+
+       mdsDbus *dbus_handle = mdsc_dbus_start();
+       if (NULL == dbus_handle)
+               ERR("mdsc_dbus_start() Fail");
+
+       g_signal_handler_disconnect(dbus_handle, mdsc_noti_signal_ID);
+       mdsc_noti_data.cb = NULL;
+       mdsc_noti_data.user_data = NULL;
+
+       mdsc_dbus_stop(dbus_handle);
+}
index 9c053b6..58d3ecd 100644 (file)
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 #include "modes.h"
+
 #include <stdlib.h>
 #include <glib.h>
 #include "mdsc.h"
@@ -33,7 +34,7 @@ struct mds_handle {
        GList *action_list;
 };
 
-int _mdsc_dbus_register_mode_sync(mdsDbus *mdsc_dbus, GVariant *mode_data)
+static int _mdsc_dbus_register_mode_sync(mdsDbus *mdsc_dbus, GVariant *mode_data)
 {
        int result = MODES_ERROR_NONE;
        gboolean ret;
@@ -51,7 +52,7 @@ int _mdsc_dbus_register_mode_sync(mdsDbus *mdsc_dbus, GVariant *mode_data)
        return result;
 }
 
-void _mdsc_free_action(gpointer data)
+static void _mdsc_free_action(gpointer data)
 {
        RET_IF(NULL == data);
 
@@ -63,7 +64,7 @@ void _mdsc_free_action(gpointer data)
        free(action_data);
 }
 
-GVariant* _mdsc_create_mode_data(modes_h mode)
+static GVariant* _mdsc_create_mode_data(modes_h mode)
 {
        RETV_IF(NULL == mode, NULL);
 
@@ -143,9 +144,9 @@ API int modes_register_mode(modes_h mode)
 
        RETV_IF(NULL == mode, MODES_ERROR_INVALID_PARAMETER);
 
-       dbus_handle = _mdsc_dbus_start();
+       dbus_handle = mdsc_dbus_start();
        if (NULL == dbus_handle) {
-               ERR("_mdsc_dbus_start() Fail");
+               ERR("mdsc_dbus_start() Fail");
                return MODES_ERROR_SYSTEM;
        }
 
@@ -158,7 +159,7 @@ API int modes_register_mode(modes_h mode)
                return ret;
        }
 
-       _mdsc_dbus_stop(dbus_handle);
+       mdsc_dbus_stop(dbus_handle);
 
        return MODES_ERROR_NONE;
 }
index 9dca233..5ba39e6 100644 (file)
  * limitations under the License.
  */
 #include "modes.h"
+
 #include <glib.h>
 #include "mdsc.h"
 #include "mdsc_dbus.h"
 #include "common/dbus.h"
 
-int _mdsc_dbus_undo_mode_sync(mdsDbus *mdsc_dbus, const char *mode)
+static int _mdsc_dbus_undo_mode_sync(mdsDbus *mdsc_dbus, const char *mode)
 {
        gboolean ret;
        GError *error = NULL;
@@ -40,13 +41,13 @@ int _mdsc_dbus_undo_mode_sync(mdsDbus *mdsc_dbus, const char *mode)
 API int modes_undo_mode(const char *name)
 {
        int ret;
-       mdsDbusdbus_handle;
+       mdsDbus *dbus_handle;
 
        RETV_IF(NULL == name, MODES_ERROR_INVALID_PARAMETER);
 
-       dbus_handle = _mdsc_dbus_start();
+       dbus_handle = mdsc_dbus_start();
        if (NULL == dbus_handle) {
-               ERR("_mdsc_dbus_start() Fail");
+               ERR("mdsc_dbus_start() Fail");
                return MODES_ERROR_SYSTEM;
        }
 
@@ -56,7 +57,7 @@ API int modes_undo_mode(const char *name)
                return ret;
        }
 
-       _mdsc_dbus_stop(dbus_handle);
+       mdsc_dbus_stop(dbus_handle);
 
        return MODES_ERROR_NONE;
 }
index dadf185..aee273f 100644 (file)
                        <arg type="(siv)" name="modeData" direction="in"/>
                        <arg type="i" name="ret" direction="out"/>
                </method>
+
+               <signal name="changedMode">
+                       <arg type="s" name="modeName"/>
+                       <arg type="i" name="modeState"/>
+               </signal>
        </interface>
 </node>
index 494443d..9b71e30 100644 (file)
@@ -151,6 +151,46 @@ int modes_register_mode(modes_h mode);
  */
 void modes_destroy_mode(modes_h mode);
 
+
+/**
+ * @brief Specifies the type of function passed to modes_noti_connect().
+ * @details When the Modes apply/undo a mode, it is called, immediately.
+ * @since_tizen 6.0
+ * @param[in] mode_name The name of mode which was changed state
+ * @param[in] user_data The user data to pass to the function
+ *
+ * @pre The callback must be registered using modes_noti_connect()
+ *
+ * @see modes_subscribe_mode_changes()
+ * @see modes_unsubscribe_mode_changes()
+ */
+typedef int(*modes_noti_fn) (const char *mode_name, int state, void *user_data);
+
+/**
+ * @brief Adds callback for recognizing the changed of mode.
+ * @details Sets a function to be called when the mode is changed.
+ * @since_tizen 6.0
+ *
+ * @param[in] cb The callback function to invoke
+ * @param[in] user_data The user data to pass to the function
+ *
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #MODES_ERROR_NONE Successful
+ * @retval #MODES_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see modes_unsubscribe_mode_changes()
+ */
+int modes_subscribe_mode_changes(modes_noti_fn cb, void *user_data);
+
+/**
+ * @brief stop recognizing the changed of mode.
+ * @details Removes a function to be called when the mode is changed.
+ * @since_tizen 6.0
+ *
+ * @see modes_subscribe_mode_changes()
+ */
+void modes_unsubscribe_mode_changes();
+
 /**
  * @}
  */
index 4f52361..7596445 100644 (file)
    */
 typedef enum {
        MODES_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */
+       MODES_ERROR_ALREADY = TIZEN_ERROR_ALREADY_IN_PROGRESS, /** Operation already in progress */
+       MODES_ERROR_NO_DATA = TIZEN_ERROR_NO_DATA, /**< No data available */
+       MODES_ERROR_TIMEOUT = TIZEN_ERROR_TIMED_OUT, /**< Time out */
        MODES_ERROR_IO_ERROR = TIZEN_ERROR_IO_ERROR, /**< I/O error */
+       MODES_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< Not supported */
        MODES_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */
        MODES_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */
-       MODES_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< Not supported */
        MODES_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
-       MODES_ERROR_NO_DATA = TIZEN_ERROR_NO_DATA, /**< No data available */
-       MODES_ERROR_TIMEOUT = TIZEN_ERROR_TIMED_OUT, /**< Time out */
-       MODES_ERROR_INVALID_TYPE = TIZEN_ERROR_MODES | 0x03, /**< Invalid type */
+       MODES_ERROR_SYSTEM = TIZEN_ERROR_MODES | 0x03, /**< System errors */
        MODES_ERROR_CONFLICT = TIZEN_ERROR_MODES | 0x04, /**< Conflict */
-       MODES_ERROR_SYSTEM = TIZEN_ERROR_MODES | 0x06, /**< System errors */
 } modes_error_e;
 
 /*
  * MODES_ERROR_NONE 0
- * MODES_ERROR_IO_ERROR -5
- * MODES_ERROR_OUT_OF_MEMORY -12
- * MODES_ERROR_PERMISSION_DENIED -13
- * MODES_ERROR_NOT_SUPPORTED -1073741822
- * MODES_ERROR_INVALID_PARAMETER -22
- * MODES_ERROR_NO_DATA -61
- * MODES_ERROR_TIMEOUT -1073741823
+ * MODES_ERROR_ALREADY - 114
+ * MODES_ERROR_NO_DATA - 61
+ * MODES_ERROR_TIMEOUT - 1073741823
+ * MODES_ERROR_IO_ERROR - 5
+ * MODES_ERROR_NOT_SUPPORTED - 1073741822
+ * MODES_ERROR_OUT_OF_MEMORY - 12
+ * MODES_ERROR_PERMISSION_DENIED - 13
+ * MODES_ERROR_INVALID_PARAMETER - 22
+ * MODES_ERROR_SYSTEM - 50462717
+ * MODES_ERROR_CONFLICT - 50462716
  */
 
+
 /**
  * @}
  */
index 875782a..8c5855a 100644 (file)
@@ -74,7 +74,7 @@ void Mode::setModeType(int val)
        }
 }
 
-const Mode::ModeType Mode::getModeType() const
+Mode::ModeType Mode::getModeType() const
 {
        return type;
 }
@@ -84,7 +84,7 @@ void Mode::setCustomized(bool data)
        customized = data;
 }
 
-const bool Mode::getCustomized() const
+bool Mode::getCustomized() const
 {
        return customized;
 }
index 7d90974..a53e638 100644 (file)
@@ -38,10 +38,10 @@ public:
 
        void setModeType(const std::string &data);
        void setModeType(int val);
-       const ModeType getModeType() const;
+       ModeType getModeType() const;
 
        void setCustomized(bool data);
-       const bool getCustomized() const;
+       bool getCustomized() const;
 
        void addAction(Action *action);
        std::list<std::shared_ptr<Action>> getActionList() const;
index 0fb5f29..8ae12c3 100644 (file)
@@ -45,6 +45,8 @@ gboolean RequestHandler::applyModeHandler(mdsDbus *object, GDBusMethodInvocation
        int ret = modeMgr->applyMode(modeName);
 
        mds_dbus_complete_apply_mode(object, invocation, ret);
+       if (MODES_ERROR_NONE == ret)
+               mds_dbus_emit_changed_mode(object, modeName, 1);
 
        return TRUE;
 }
@@ -60,6 +62,8 @@ gboolean RequestHandler::undoModeHandler(mdsDbus *object, GDBusMethodInvocation
        int ret = modeMgr->undoMode(modeName);
 
        mds_dbus_complete_undo_mode(object, invocation, ret);
+       if (MODES_ERROR_NONE == ret)
+               mds_dbus_emit_changed_mode(object, modeName, 0);
 
        return TRUE;
 }
index bcb1d39..939b3e3 100644 (file)
@@ -64,7 +64,8 @@ public:
                                std::istringstream iss(val);
                                iss >> value;
                        } else {
-                               return MODES_ERROR_INVALID_TYPE;
+                               ERR("Action(%s) has Invalid val(%s)", ruleName.c_str(), val.c_str());
+                               return MODES_ERROR_NOT_SUPPORTED;
                        }
                }
 
index 920ee35..3f60c08 100644 (file)
@@ -45,8 +45,9 @@ public:
        {
                ValueChecker checker;
                if (false == checker.checkValue(T(), value)) {
-                       ERR("checkValue() Fail");
-                       return MODES_ERROR_INVALID_TYPE;
+                       ERR("checkValue(Rule:%s, Alias:%s, Val:%s) Fail",
+                               ruleName.c_str(), alias.c_str(), value.c_str());
+                       return MODES_ERROR_NOT_SUPPORTED;
                }
 
                T realVal;
index 43d8ee5..16d8b24 100644 (file)
@@ -13,6 +13,24 @@ SET(SUPERVISOR_DIR "${CMAKE_SOURCE_DIR}/supervisor/" )
 FILE(GLOB SRC "modes_test_main.cpp")
 
 #=======================================================================================#
+SET(GTEST_NOTI "modes-gtest-noti")
+SET(GTEST_NOTI_SRCS modes_test_noti.cpp)
+ADD_EXECUTABLE(${GTEST_NOTI} ${SRC} ${GTEST_NOTI_SRCS})
+TARGET_LINK_LIBRARIES(${GTEST_NOTI} ${CLIENT} ${gtest_pkgs_LIBRARIES})
+INSTALL(TARGETS ${GTEST_NOTI} DESTINATION ${TEST_INSTALL_DIR})
+#=======================================================================================#
+SET(GTEST_CLIENT "modes-gtest-client")
+SET(GTEST_CLIENT_SRCS modes_test_client.cpp)
+ADD_EXECUTABLE(${GTEST_CLIENT} ${SRC} ${GTEST_CLIENT_SRCS})
+TARGET_LINK_LIBRARIES(${GTEST_CLIENT} ${CLIENT} ${gtest_pkgs_LIBRARIES})
+INSTALL(TARGETS ${GTEST_CLIENT} DESTINATION ${TEST_INSTALL_DIR})
+#=======================================================================================#
+SET(TEST_APPLY_MODE "modes-apply-mode-test")
+SET(TEST_APPLY_MODE_SRC modes_apply_mode.c)
+ADD_EXECUTABLE(${TEST_APPLY_MODE} ${TEST_APPLY_MODE_SRC})
+TARGET_LINK_LIBRARIES(${TEST_APPLY_MODE} ${CLIENT})
+INSTALL(TARGETS ${TEST_APPLY_MODE} DESTINATION ${TEST_INSTALL_DIR})
+#=======================================================================================#
 SET(GTEST_MODEMGR "modes-gtest-modemgr")
 FILE(GLOB GTEST_MODEMGR_SRCS
                ${SUPERVISOR_DIR}/ModeTag.cpp
@@ -64,21 +82,6 @@ FILE(GLOB GTEST_PARSER_SRCS
 ADD_EXECUTABLE(${GTEST_PARSER} ${SRC} ${GTEST_PARSER_SRCS})
 TARGET_LINK_LIBRARIES(${GTEST_PARSER} ${gtest_pkgs_LIBRARIES} dl)
 INSTALL(TARGETS ${GTEST_PARSER} DESTINATION ${TEST_INSTALL_DIR})
-
-#=======================================================================================#
-SET(GTEST_CLIENT "modes-gtest-client")
-SET(GTEST_CLIENT_SRCS modes_test_client.cpp)
-ADD_EXECUTABLE(${GTEST_CLIENT} ${SRC} ${GTEST_CLIENT_SRCS})
-TARGET_LINK_LIBRARIES(${GTEST_CLIENT} ${CLIENT} ${gtest_pkgs_LIBRARIES})
-INSTALL(TARGETS ${GTEST_CLIENT} DESTINATION ${TEST_INSTALL_DIR})
-
-#=======================================================================================#
-SET(TEST_APPLY_MODE "modes-apply-mode-test")
-SET(TEST_APPLY_MODE_SRC modes_apply_mode.c)
-ADD_EXECUTABLE(${TEST_APPLY_MODE} ${TEST_APPLY_MODE_SRC})
-TARGET_LINK_LIBRARIES(${TEST_APPLY_MODE} ${CLIENT})
-INSTALL(TARGETS ${TEST_APPLY_MODE} DESTINATION ${TEST_INSTALL_DIR})
-
 #=======================================================================================#
 SET(GTEST_GENERATOR "modes-gtest-generator")
 FILE(GLOB GTEST_GENERATOR_SRCS
index 996a5c3..daa57b5 100755 (executable)
@@ -27,6 +27,7 @@ then # on building
 else # on Target
        cp $DATA_DIR/schema/*.xsd ./
        ./modes-gtest-client
+       ./modes-gtest-noti
 fi
 
 ./modes-gtest-rulemgr
index 7718394..7b26712 100644 (file)
@@ -30,7 +30,7 @@ protected:
                loop = NULL;
        }
 
-       static gboolean apply_mode_idler(gpointer data)
+       static gboolean applyModeIdler(gpointer data)
        {
                result = modes_apply_mode((const char*)data);
 
@@ -38,18 +38,18 @@ protected:
                return G_SOURCE_REMOVE;
        }
 
-       static gboolean undo_mode_idler(gpointer data)
+       static gboolean undoModeIdler(gpointer data)
        {
                result = modes_apply_mode((const char*)data);
                EXPECT_EQ(MODES_ERROR_NONE, result);
-               sleep(5);
+               sleep(1);
                result = modes_undo_mode((const char*)data);
 
                g_main_loop_quit(loop);
                return G_SOURCE_REMOVE;
        }
 
-       static gboolean request_register_mode_idler(gpointer data)
+       static gboolean registerModeIdler(gpointer data)
        {
                modes_h mode_handle = modes_create_mode("created", MODES_TYPE_MODE_NORMAL);
                action_h action_handle[2];
@@ -77,21 +77,21 @@ GMainLoop *ClientTest::loop = NULL;
 
 TEST_F(ClientTest, applyModeP)
 {
-       g_idle_add(apply_mode_idler, (gpointer)"ex1");
+       g_idle_add(applyModeIdler, (gpointer)"ex1");
        g_main_loop_run(loop);
        EXPECT_EQ(MODES_ERROR_NONE, result);
 }
 
 TEST_F(ClientTest, applyModeN)
 {
-       g_idle_add(apply_mode_idler, (gpointer)"non_ex2");
+       g_idle_add(applyModeIdler, (gpointer)"non_ex2");
        g_main_loop_run(loop);
        EXPECT_EQ(MODES_ERROR_NO_DATA, result);
 }
 
 TEST_F(ClientTest, registerMode)
 {
-       g_idle_add(request_register_mode_idler, NULL);
+       g_idle_add(registerModeIdler, NULL);
        g_main_loop_run(loop);
        EXPECT_EQ(MODES_ERROR_NONE, result);
 }
@@ -99,7 +99,7 @@ TEST_F(ClientTest, registerMode)
 TEST_F(ClientTest, undoModeEx1)
 {
        modes_undo_mode("ex1");
-       g_idle_add(undo_mode_idler, (gpointer)"ex1");
+       g_idle_add(undoModeIdler, (gpointer)"ex1");
        g_main_loop_run(loop);
        EXPECT_EQ(MODES_ERROR_NONE, result);
 }
@@ -107,7 +107,7 @@ TEST_F(ClientTest, undoModeEx1)
 TEST_F(ClientTest, undoModeEx2)
 {
        modes_undo_mode("ex2");
-       g_idle_add(undo_mode_idler, (gpointer)"ex2");
+       g_idle_add(undoModeIdler, (gpointer)"ex2");
        g_main_loop_run(loop);
        EXPECT_EQ(MODES_ERROR_NONE, result);
 }
diff --git a/unittest/modes_test_noti.cpp b/unittest/modes_test_noti.cpp
new file mode 100644 (file)
index 0000000..bad0789
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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 <glib.h>
+#include <gtest/gtest.h>
+#include <modes.h>
+
+class ClientNotiTest : public ::testing::Test {
+protected:
+       void SetUp() override
+       {
+               loop = g_main_loop_new(NULL, FALSE);
+       }
+
+       void TearDown() override
+       {
+               g_main_loop_unref(loop);
+               loop = NULL;
+       }
+
+       static gboolean undoTimeout(gpointer data)
+       {
+               expectedState = 0;
+               int ret = modes_undo_mode((const char*)data);
+               EXPECT_EQ(MODES_ERROR_NONE, ret);
+
+               g_main_loop_quit(loop);
+               return  G_SOURCE_REMOVE;
+       }
+
+       static int notiFunc(const char *modeName, int state, void *user_data)
+       {
+               char *requestMode = (char*)user_data;
+
+               std::cout << "Changed Mode : " << modeName << std::endl;
+               EXPECT_EQ(requestMode, std::string(modeName));
+               std::cout << "state : " << state << std::endl;
+               EXPECT_EQ(expectedState, state);
+
+               g_main_loop_quit(loop);
+               return MODES_ERROR_NONE;
+       }
+
+       static int expectedState;
+       static GMainLoop *loop;
+};
+
+int ClientNotiTest::expectedState = 1;
+GMainLoop *ClientNotiTest::loop = NULL;
+
+TEST_F(ClientNotiTest, notiConnect)
+{
+       const char *testMode = "ex2";
+       int ret = modes_subscribe_mode_changes(notiFunc, (void*)testMode);
+       EXPECT_EQ(MODES_ERROR_NONE, ret);
+
+       ClientNotiTest::expectedState = 1;
+       ret = modes_apply_mode(testMode);
+       EXPECT_EQ(MODES_ERROR_NONE, ret);
+
+       g_timeout_add_seconds(1, undoTimeout, (void*)testMode);
+
+       g_main_loop_run(loop);
+
+       modes_unsubscribe_mode_changes();
+}
index c9513e8..d526341 100644 (file)
@@ -107,3 +107,20 @@ TEST_F(ParserTest, invalidActionValue)
        ModeXMLParser modeparser2("tizen_invalid2_mode.xml", ruleMgr, piMgr);
        EXPECT_THROW(modeparser2.getMode(), ModesEx);
 }
+
+TEST_F(ParserTest, printError)
+{
+       EXPECT_NO_THROW(
+               std::cout << "MODES_ERROR_NONE " << MODES_ERROR_NONE << std::endl;
+       std::cout << "MODES_ERROR_ALREADY " << MODES_ERROR_ALREADY << std::endl;
+       std::cout << "MODES_ERROR_NO_DATA " << MODES_ERROR_NO_DATA << std::endl;
+       std::cout << "MODES_ERROR_TIMEOUT " << MODES_ERROR_TIMEOUT << std::endl;
+       std::cout << "MODES_ERROR_IO_ERROR " << MODES_ERROR_IO_ERROR << std::endl;
+       std::cout << "MODES_ERROR_NOT_SUPPORTED " << MODES_ERROR_NOT_SUPPORTED << std::endl;
+       std::cout << "MODES_ERROR_OUT_OF_MEMORY " << MODES_ERROR_OUT_OF_MEMORY << std::endl;
+       std::cout << "MODES_ERROR_PERMISSION_DENIED " << MODES_ERROR_PERMISSION_DENIED << std::endl;
+       std::cout << "MODES_ERROR_INVALID_PARAMETER " << MODES_ERROR_INVALID_PARAMETER << std::endl;
+       std::cout << "MODES_ERROR_SYSTEM " << MODES_ERROR_SYSTEM << std::endl;
+       std::cout << "MODES_ERROR_CONFLICT " << MODES_ERROR_CONFLICT << std::endl;
+       );
+}