Commit summary: 74/189874/1 tizen
authori.metelytsia <i.metelytsia@samsung.com>
Fri, 21 Sep 2018 09:11:11 +0000 (12:11 +0300)
committeri.metelytsia <i.metelytsia@samsung.com>
Fri, 21 Sep 2018 09:11:11 +0000 (12:11 +0300)
- Test coverage was improved

Change-Id: I7c6d6e2dcd6f4812506bb6126406c9875ed66aab

24 files changed:
daemon/application_service.cpp
daemon/application_service.h
daemon/dbus/dbuslistener.cpp
utest/CMakeLists.txt
utest/mock/app_control_mock.h [new file with mode: 0644]
utest/mock/app_control_stub.cpp [new file with mode: 0644]
utest/mock/app_control_stub.h [new file with mode: 0644]
utest/mock/dbus_mock.h [new file with mode: 0644]
utest/mock/dbus_stub.cpp [new file with mode: 0644]
utest/mock/dbus_stub.h [new file with mode: 0644]
utest/mock/sys_mock.h
utest/mock/sys_stub.cpp
utest/mock/sys_stub.h
utest/test_applicationservice.cpp [new file with mode: 0644]
utest/test_auditdeleteallrules.cpp [new file with mode: 0644]
utest/test_auditrequestrulehandler.cpp [new file with mode: 0644]
utest/test_auditrewriterulehandler.cpp [new file with mode: 0644]
utest/test_auditrewriterulesethandler.cpp [new file with mode: 0644]
utest/test_auditupdaterulesethandler.cpp [new file with mode: 0644]
utest/test_dbuslistener.cpp [new file with mode: 0644]
utest/test_killprocesshandler.cpp [new file with mode: 0644]
utest/test_notificationhandler.cpp [new file with mode: 0644]
utest/test_notifyuserhandler.cpp [new file with mode: 0644]
utest/test_uninstallhandler.cpp [new file with mode: 0644]

index e79134f..3589b04 100644 (file)
@@ -94,7 +94,6 @@ int ApplicationService::uninstall(const std::string& package_name)
 {
     int res = -1;
     device_policy_manager_h handle = dpm_manager_create();
-
     if (handle) {
         res = dpm_application_uninstall_package(handle, package_name.c_str());
         LOG_D(TAG, "dpm_application_uninstall_package returned %d", res);
@@ -180,12 +179,6 @@ std::vector<int> ApplicationService::get_processes_ids_by_path(const std::string
     return pids;
 }
 
-int ApplicationService::device_power_off()
-{
-    sync();
-    return reboot(RB_POWER_OFF);
-}
-
 std::string ApplicationService::find_this_executable()
 {
     std::string exe;
index 5adf758..16e6df4 100644 (file)
@@ -89,13 +89,6 @@ public:
     static std::vector<int> get_processes_ids_by_path(const std::string& path);
 
     /**
-     * @brief Power off the device
-     * @details This API can be used to power off the device
-     * @return 0 if success
-     */
-    static int device_power_off();
-
-    /**
      * @brief Returns path of current executable
      * @return Thie axecutable path as string
      */
index 6bad766..979e93a 100644 (file)
@@ -62,7 +62,7 @@ DBusListener::DBusListener(AllowedPredicate&& allowed) : m_connection(nullptr),
 
     if (dbus_bus_request_name(m_connection, "com.samsung.sam.sink", DBUS_NAME_FLAG_REPLACE_EXISTING , nullptr) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
         LOG_E(TAG, "dbus_bus_request_name failed!");
-        dbus_connection_close(m_connection);
+        dbus_connection_unref(m_connection);
         throw std::runtime_error("dbus_bus_request_name failed!");
     }
 
@@ -73,11 +73,6 @@ DBusListener::DBusListener(AllowedPredicate&& allowed) : m_connection(nullptr),
 DBusListener::~DBusListener()
 {
     dbus_connection_unref(m_connection);
-    /*
-    You may not close a shared connection.
-    Connections created with dbus_connection_open() or dbus_bus_get() are shared.
-    */
-    //dbus_connection_close(m_connection);
 }
 
 bool DBusListener::addHandler(const std::string& type, DBusHandler* handler)
index 8785933..7f9e67a 100644 (file)
@@ -2,7 +2,7 @@ project(utest)
 
 add_definitions(-D__MOCK_THIRDPARTY__ -DUNIT_TESTS)
 
-file(GLOB SRCS *.cpp ../daemon/*.cpp ../daemon/dpm/*.cpp ../daemon/audit/*.cpp mock/*.cpp)
+file(GLOB SRCS *.cpp ../daemon/*.cpp ../daemon/dpm/*.cpp ../daemon/audit/*.cpp ../daemon/dbus/*.cpp mock/*.cpp)
 
 file(GLOB DAEMON_MAIN ../daemon/main.cpp)
 file(GLOB DAEMON_MAIN_THREAD ../daemon/main_thread.cpp)
@@ -14,12 +14,12 @@ list(REMOVE_ITEM SRCS ${DAEMON_DBUS_THREAD})
 
 add_executable (${PROJECT_NAME} ${SRCS})
 
-pkg_check_modules(UTEST_DEPS REQUIRED boost libcurl dpm dlog audit-trail capi-system-info systemd capi-appfw-app-control)
+pkg_check_modules(UTEST_DEPS REQUIRED boost libcurl dpm dlog audit-trail capi-system-info systemd capi-appfw-app-control dbus-1)
 
 add_dependencies(${PROJECT_NAME} communication)
 
 include_directories(SYSTEM ${UTEST_DEPS_INCLUDE_DIRS})
-include_directories(../common/inc ../communication/inc ../daemon ../daemon/dpm ../daemon/audit mock)
+include_directories(../common/inc ../communication/inc ../daemon ../daemon/dpm ../daemon/audit ../daemon/dbus mock)
 target_compile_definitions(${PROJECT_NAME}
     PRIVATE CONFIG_FILE_PATH=${DAEMON_CONFIG_DIR}/${DAEMON_CONFIG_FILE})
 
@@ -31,7 +31,8 @@ target_link_libraries(${PROJECT_NAME}
     boost_system
     dlog
     curl
-    capi-appfw-app-control)
+    capi-appfw-app-control
+    dbus-1)
 
 install(TARGETS ${PROJECT_NAME} DESTINATION ${BIN_DIR})
 install(FILES tests.manifest DESTINATION ${MANIFESTDIR})
diff --git a/utest/mock/app_control_mock.h b/utest/mock/app_control_mock.h
new file mode 100644 (file)
index 0000000..d6ca90a
--- /dev/null
@@ -0,0 +1,41 @@
+/**
+ * Samsung Ukraine R&D Center (SRK under a contract between)
+ * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
+ * Copyright (C) 2018 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
+ */
+#ifndef APPCONTROLMOCK_H
+#define APPCONTROLMOCK_H
+
+#include <gmock/gmock.h>
+#include "app_control_stub.h"
+
+class AppControlMock: public IAppControl
+{
+public:
+    AppControlMock(): IAppControl()
+    {
+    }
+
+    MOCK_METHOD1(app_control_create, int(app_control_h*));
+    MOCK_METHOD0(app_control_destroy, int());
+
+    MOCK_METHOD1(app_control_set_operation, int(const char*));
+    MOCK_METHOD1(app_control_set_app_id, int(const char*));
+    MOCK_METHOD2(app_control_add_extra_data, int(const char*, const char*));
+
+    MOCK_METHOD2(app_control_send_launch_request, int(app_control_reply_cb, void*));
+};
+
+#endif // APPCONTROLMOCK_H
diff --git a/utest/mock/app_control_stub.cpp b/utest/mock/app_control_stub.cpp
new file mode 100644 (file)
index 0000000..4c6946d
--- /dev/null
@@ -0,0 +1,81 @@
+/**
+ * Samsung Ukraine R&D Center (SRK under a contract between)
+ * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
+ * Copyright (C) 2018 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 <cassert>
+#include "app_control_stub.h"
+
+namespace
+{
+static IAppControl* app_control = nullptr;
+
+void app_control_set_implementation(IAppControl* impl)
+{
+    app_control = impl;
+}
+
+IAppControl* app_control_from_handle(app_control_h handle)
+{
+    assert(handle);
+    IAppControl** p = reinterpret_cast<IAppControl**>(handle);
+    assert(*p);
+    return *p;
+}
+}
+
+IAppControl::IAppControl()
+{
+    app_control_set_implementation(this);
+}
+IAppControl::~IAppControl()
+{
+    app_control_set_implementation(nullptr);
+}
+
+int app_control_create(app_control_h* handle)
+{
+    assert(app_control);
+    int ret = app_control->app_control_create(handle);
+    *handle = (app_control_h)&app_control;
+    return ret;
+}
+int app_control_destroy(app_control_h handle)
+{
+    assert(handle);
+    IAppControl** p = reinterpret_cast<IAppControl**>(handle);
+    if (p != nullptr && *p != nullptr && *p == app_control) {
+        (*p)->app_control_destroy();
+    }
+    return 0;
+}
+
+int app_control_set_operation(app_control_h handle, const char* operation)
+{
+    return app_control_from_handle(handle)->app_control_set_operation(operation);
+}
+int app_control_set_app_id(app_control_h handle, const char* app_id)
+{
+    return app_control_from_handle(handle)->app_control_set_app_id(app_id);
+}
+int app_control_add_extra_data(app_control_h handle, const char* key, const char* value)
+{
+    return app_control_from_handle(handle)->app_control_add_extra_data(key, value);
+}
+
+int app_control_send_launch_request(app_control_h handle, app_control_reply_cb callback, void* user_data)
+{
+    return app_control_from_handle(handle)->app_control_send_launch_request(callback, user_data);
+}
diff --git a/utest/mock/app_control_stub.h b/utest/mock/app_control_stub.h
new file mode 100644 (file)
index 0000000..5b56dc3
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * Samsung Ukraine R&D Center (SRK under a contract between)
+ * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
+ * Copyright (C) 2018 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
+ */
+#ifndef APPCONTROLSTUB_H
+#define APPCONTROLSTUB_H
+
+#include <app_control.h>
+
+class IAppControl
+{
+public:
+    IAppControl();
+    virtual ~IAppControl();
+
+    virtual int app_control_create(app_control_h* handle) = 0;
+    virtual int app_control_destroy() = 0;
+
+    virtual int app_control_set_operation(const char* operation) = 0;
+    virtual int app_control_set_app_id(const char* app_id) = 0;
+    virtual int app_control_add_extra_data(const char* key, const char* value) = 0;
+
+    virtual int app_control_send_launch_request(app_control_reply_cb callback, void* user_data) = 0;
+};
+
+#endif // APPCONTROLSTUB_H
diff --git a/utest/mock/dbus_mock.h b/utest/mock/dbus_mock.h
new file mode 100644 (file)
index 0000000..e699f5a
--- /dev/null
@@ -0,0 +1,63 @@
+/**
+ * Samsung Ukraine R&D Center (SRK under a contract between)
+ * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
+ * Copyright (C) 2018 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
+ */
+#ifndef DBUSMOCK_H
+#define DBUSMOCK_H
+
+#include <gmock/gmock.h>
+#include "dbus_stub.h"
+
+class DBusConnectionMock : public IDBusConnection
+{
+public:
+    DBusConnectionMock()
+    {
+    }
+
+    MOCK_METHOD2(dbus_bus_get, void*(DBusBusType, DBusError*));
+    MOCK_METHOD3(dbus_bus_request_name, int(const char*, unsigned int, DBusError*));
+    MOCK_METHOD2(dbus_bus_add_match, void(const char*, DBusError*));
+    MOCK_METHOD1(dbus_connection_read_write, dbus_bool_t(int));
+    MOCK_METHOD0(dbus_connection_pop_message, void*());
+    MOCK_METHOD0(dbus_connection_flush, void());
+    MOCK_METHOD0(dbus_connection_unref, void());
+};
+
+class DBusMessageMock : public IDBusMessage
+{
+public:
+    DBusMessageMock()
+    {
+    }
+
+    MOCK_METHOD2(dbus_message_is_signal, dbus_bool_t(const char*, const char*));
+    MOCK_METHOD1(dbus_message_iter_init, dbus_bool_t(DBusMessageIter*));
+    MOCK_METHOD0(dbus_message_unref, void());
+};
+
+class DBusMessageIterMock : public IDBusMessageIter
+{
+public:
+    DBusMessageIterMock()
+    {
+    }
+
+    MOCK_METHOD0(dbus_message_iter_get_arg_type, int());
+    MOCK_METHOD1(dbus_message_iter_get_basic, void(void*));
+};
+
+#endif // DBUSMOCK_H
diff --git a/utest/mock/dbus_stub.cpp b/utest/mock/dbus_stub.cpp
new file mode 100644 (file)
index 0000000..6cac430
--- /dev/null
@@ -0,0 +1,147 @@
+/**
+ * Samsung Ukraine R&D Center (SRK under a contract between)
+ * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
+ * Copyright (C) 2018 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 <cassert>
+#include "dbus_stub.h"
+
+namespace
+{
+static IDBusConnection* dbus_connection = nullptr;
+static IDBusMessage* dbus_message = nullptr;
+static IDBusMessageIter* dbus_message_iter = nullptr;
+
+void dbus_connection_set_implementation(IDBusConnection* impl)
+{
+    dbus_connection = impl;
+}
+
+IDBusConnection* get_dbus_connection(DBusConnection* connection)
+{
+    assert(connection);
+    return reinterpret_cast<IDBusConnection*>(connection);
+}
+
+void dbus_message_set_implementation(IDBusMessage* impl)
+{
+    dbus_message = impl;
+}
+
+IDBusMessage* get_dbus_message(DBusMessage* message)
+{
+    assert(message);
+    return reinterpret_cast<IDBusMessage*>(message);
+}
+
+void dbus_message_iter_set_implementation(IDBusMessageIter* impl)
+{
+    dbus_message_iter = impl;
+}
+
+IDBusMessageIter* get_dbus_message_iter(DBusMessageIter* iter)
+{
+    assert(dbus_message_iter);
+    return dbus_message_iter;
+}
+}
+
+IDBusConnection::IDBusConnection()
+{
+    dbus_connection_set_implementation(this);
+}
+IDBusConnection::~IDBusConnection()
+{
+    dbus_connection_set_implementation(nullptr);
+}
+
+DBusConnection* dbus_bus_get(DBusBusType type, DBusError* error)
+{
+    assert(dbus_connection);
+    return (DBusConnection*)(dbus_connection->dbus_bus_get(type, error));
+}
+
+int dbus_bus_request_name(DBusConnection* connection, const char* name, unsigned int flags, DBusError* error)
+{
+    return get_dbus_connection(connection)->dbus_bus_request_name(name, flags, error);
+}
+
+void dbus_bus_add_match(DBusConnection* connection, const char* rule, DBusError* error)
+{
+    get_dbus_connection(connection)->dbus_bus_add_match(rule, error);
+}
+
+dbus_bool_t dbus_connection_read_write(DBusConnection* connection, int timeout_milliseconds)
+{
+    return get_dbus_connection(connection)->dbus_connection_read_write(timeout_milliseconds);
+}
+
+DBusMessage* dbus_connection_pop_message(DBusConnection* connection)
+{
+    return (DBusMessage*)get_dbus_connection(connection)->dbus_connection_pop_message();
+}
+
+void dbus_connection_flush(DBusConnection* connection)
+{
+    get_dbus_connection(connection)->dbus_connection_flush();
+}
+
+void dbus_connection_unref(DBusConnection* connection)
+{
+    get_dbus_connection(connection)->dbus_connection_unref();
+}
+
+IDBusMessage::IDBusMessage()
+{
+    dbus_message_set_implementation(this);
+}
+IDBusMessage::~IDBusMessage()
+{
+    dbus_message_set_implementation(nullptr);
+}
+
+dbus_bool_t dbus_message_is_signal(DBusMessage* message, const char* iface, const char* signal_name)
+{
+    return get_dbus_message(message)->dbus_message_is_signal(iface, signal_name);
+}
+
+dbus_bool_t dbus_message_iter_init(DBusMessage* message, DBusMessageIter* iter)
+{
+    return get_dbus_message(message)->dbus_message_iter_init(iter);
+}
+
+void dbus_message_unref(DBusMessage* message)
+{
+    get_dbus_message(message)->dbus_message_unref();
+}
+
+IDBusMessageIter::IDBusMessageIter()
+{
+    dbus_message_iter_set_implementation(this);
+}
+IDBusMessageIter::~IDBusMessageIter()
+{
+    dbus_message_iter_set_implementation(nullptr);
+}
+
+int dbus_message_iter_get_arg_type(DBusMessageIter* iter)
+{
+    return get_dbus_message_iter(iter)->dbus_message_iter_get_arg_type();
+}
+
+void dbus_message_iter_get_basic(DBusMessageIter* iter, void* value)
+{
+    get_dbus_message_iter(iter)->dbus_message_iter_get_basic(value);
+}
diff --git a/utest/mock/dbus_stub.h b/utest/mock/dbus_stub.h
new file mode 100644 (file)
index 0000000..72cad84
--- /dev/null
@@ -0,0 +1,60 @@
+/**
+ * Samsung Ukraine R&D Center (SRK under a contract between)
+ * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
+ * Copyright (C) 2018 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
+ */
+#ifndef DBUSSTUB_H
+#define DBUSSTUB_H
+
+#include <dbus/dbus.h>
+
+class IDBusConnection
+{
+public:
+    IDBusConnection();
+    virtual ~IDBusConnection();
+
+    virtual void* dbus_bus_get(DBusBusType type, DBusError* error) = 0;
+    virtual int dbus_bus_request_name(const char* name, unsigned int flags, DBusError* error) = 0;
+    virtual void dbus_bus_add_match(const char* rule, DBusError* error) = 0;
+    virtual dbus_bool_t dbus_connection_read_write(int timeout_milliseconds) = 0;
+    virtual void* dbus_connection_pop_message() = 0;
+    virtual void dbus_connection_flush() = 0;
+    virtual void dbus_connection_unref() = 0;
+};
+
+class IDBusMessage
+{
+public:
+    IDBusMessage();
+    virtual ~IDBusMessage();
+
+    virtual dbus_bool_t dbus_message_is_signal(const char* iface, const char* signal_name) = 0;
+    virtual dbus_bool_t dbus_message_iter_init(DBusMessageIter* iter) = 0;
+    virtual void dbus_message_unref() = 0;
+};
+
+class IDBusMessageIter
+{
+public:
+    IDBusMessageIter();
+    ~IDBusMessageIter();
+
+    virtual int dbus_message_iter_get_arg_type() = 0;
+    virtual void dbus_message_iter_get_basic(void* value) = 0;
+};
+
+
+#endif // DBUSSTUB_H
index 45f4a60..192cccb 100644 (file)
@@ -31,6 +31,8 @@ public:
 
     MOCK_METHOD1(uname, int(struct utsname*));
 
+    MOCK_METHOD2(kill, int(pid_t, int));
+
     MOCK_METHOD2(system_info_get_platform_string, int(const char*, char**));
     MOCK_METHOD2(system_info_get_value_string, int(system_info_key_e, char**));
 };
index cff4e57..ef580c6 100644 (file)
@@ -50,6 +50,11 @@ int __attribute__ ((visibility ("protected"))) uname(struct utsname* buf)
     return SysI::instance()->uname(buf);
 }
 
+int __attribute__ ((visibility ("protected"))) kill(pid_t pid, int sig)
+{
+    return SysI::instance()->kill(pid, sig);
+}
+
 int system_info_get_platform_string(const char* key, char** value)
 {
     return SysI::instance()->system_info_get_platform_string(key, value);
index d974d7e..f8d8ef6 100644 (file)
@@ -18,6 +18,8 @@
 #ifndef SYSSTUB_H
 #define SYSSTUB_H
 
+#include <signal.h>
+#include <sys/types.h>
 #include <sys/utsname.h>
 #include <system/system_info.h>
 
@@ -33,6 +35,8 @@ public:
 
     virtual int uname(struct utsname* buf) = 0;
 
+    virtual int kill(pid_t pid, int sig) = 0;
+
     virtual int system_info_get_platform_string(const char* key, char** value) = 0;
     virtual int system_info_get_value_string(system_info_key_e key, char** value) = 0;
 
diff --git a/utest/test_applicationservice.cpp b/utest/test_applicationservice.cpp
new file mode 100644 (file)
index 0000000..e7ef861
--- /dev/null
@@ -0,0 +1,117 @@
+/**
+ * Samsung Ukraine R&D Center (SRK under a contract between)
+ * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
+ * Copyright (C) 2018 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 <gmock/gmock.h>
+#include "application_service.h"
+#include "app_control_mock.h"
+#include "device_policy_manager_mock.h"
+#include "sys_mock.h"
+
+using ::testing::_;
+using ::testing::A;
+using ::testing::DoAll;
+using ::testing::SaveArg;
+using ::testing::Eq;
+using ::testing::StrEq;
+using ::testing::TypedEq;
+using ::testing::Return;
+
+namespace
+{
+const std::string APP_ID{"test_app"};
+const std::string EX_DATA_KEY{"ex_data_key"};
+const std::string EX_DATA_VAL{"ex_data_val"};
+}
+
+/**
+ * @brief Test for ApplicationService::launch
+ */
+TEST(TestApplicationService, test_launch_failed)
+{
+    AppControlMock app_ctrl;
+    EXPECT_CALL(app_ctrl, app_control_create(_)).WillOnce(Return(-1));
+    ASSERT_EQ(-1, agent::ApplicationService::launch(APP_ID, EX_DATA_KEY, EX_DATA_VAL));
+}
+
+/**
+ * @brief Test for ApplicationService::launch
+ */
+TEST(TestApplicationService, test_launch_success)
+{
+    AppControlMock app_ctrl;
+    EXPECT_CALL(app_ctrl, app_control_create(_)).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_set_operation(_)).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_set_app_id(StrEq(APP_ID))).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_add_extra_data(StrEq(EX_DATA_KEY), StrEq(EX_DATA_VAL))).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_send_launch_request(_, _)).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_destroy()).WillOnce(Return(0));
+    ASSERT_EQ(0, agent::ApplicationService::launch(APP_ID, EX_DATA_KEY, EX_DATA_VAL));
+}
+
+/**
+ * @brief Test for ApplicationService::install
+ */
+TEST(TestApplicationService, test_install_failed)
+{
+    DPMMock dpmm;
+    EXPECT_CALL(dpmm, dpm_manager_create()).WillOnce(Return(nullptr));
+    ASSERT_EQ(-1, agent::ApplicationService::install(APP_ID));
+}
+
+/**
+ * @brief Test for ApplicationService::install
+ */
+TEST(TestApplicationService, test_install_success)
+{
+    DPMMock dpmm;
+    EXPECT_CALL(dpmm, dpm_manager_create()).WillOnce(Return(&dpmm));
+    EXPECT_CALL(dpmm, dpm_application_install_package(StrEq(APP_ID))).WillOnce(Return(0));
+    EXPECT_CALL(dpmm, dpm_manager_destroy()).Times(1);
+    ASSERT_EQ(0, agent::ApplicationService::install(APP_ID));
+}
+
+/**
+ * @brief Test for ApplicationService::uninstall
+ */
+TEST(TestApplicationService, test_uninstall_failed)
+{
+    DPMMock dpmm;
+    EXPECT_CALL(dpmm, dpm_manager_create()).WillOnce(Return(nullptr));
+    ASSERT_EQ(-1, agent::ApplicationService::uninstall(APP_ID));
+}
+
+/**
+ * @brief Test for ApplicationService::uninstall
+ */
+TEST(TestApplicationService, test_uninstall_success)
+{
+    DPMMock dpmm;
+    EXPECT_CALL(dpmm, dpm_manager_create()).WillOnce(Return(&dpmm));
+    EXPECT_CALL(dpmm, dpm_application_uninstall_package(StrEq(APP_ID))).WillOnce(Return(0));
+    EXPECT_CALL(dpmm, dpm_manager_destroy()).Times(1);
+    ASSERT_EQ(0, agent::ApplicationService::uninstall(APP_ID));
+}
+
+/**
+ * @brief Test for ApplicationService::kill_process
+ */
+TEST(TestApplicationService, test_kill_process)
+{
+    SysMock sys;
+    EXPECT_CALL(sys, kill(Eq(1234), Eq(SIGKILL))).WillOnce(Return(0));
+    EXPECT_EQ(0, agent::ApplicationService::kill_process(1234));
+}
diff --git a/utest/test_auditdeleteallrules.cpp b/utest/test_auditdeleteallrules.cpp
new file mode 100644 (file)
index 0000000..feed475
--- /dev/null
@@ -0,0 +1,91 @@
+/**
+ * Samsung Ukraine R&D Center (SRK under a contract between)
+ * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
+ * Copyright (C) 2018 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 <gmock/gmock.h>
+#include <jsoncpp/json/reader.h>
+#include "auditdeleteallrules.h"
+#include "restservicemock.h"
+#include "audit_trail_mock.h"
+#include "settings.h"
+
+using ::testing::_;
+using ::testing::A;
+using ::testing::DoAll;
+using ::testing::SaveArg;
+using ::testing::Eq;
+using ::testing::TypedEq;
+using ::testing::Return;
+using ::testing::Invoke;
+
+namespace
+{
+const std::string TEST_DUID{"device-id"};
+const std::chrono::milliseconds TEST_KEEPALIVE{1};
+const std::string TEST_EVENT_TYPE{"rule"};
+const std::string TEST_EVENT_URI{"test-uri"};
+const std::string TEST_EVENT_CURI{"test-curi"};
+const std::string TEST_RESP_CONTENT{R"#({"type":"status-rule","data":{"rules":[]}})#"};
+}
+
+/**
+ * @brief TEST that event not confirmed when device is locked
+ */
+TEST(TestAuditDeleteAllRules, test_accept_when_locked)
+{
+    RestServiceMock rest;
+    Json::Value event_msg;
+    agent::Settings::instance().setLock(true);
+    event_msg["type"] = TEST_EVENT_TYPE;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::AuditDeleteAllRules handler(conn);
+    communication::Event event(event_msg, conn);
+
+    EXPECT_NO_THROW(handler.accept(event));
+    agent::Settings::instance().setLock(false);
+}
+
+/**
+ * @brief TEST for normal accept sequence
+ */
+TEST(TestAuditDeleteAllRules, test_accept)
+{
+    RestServiceMock rest;
+    Json::Value event_msg;
+    AuditTrailMock audit;
+    event_msg["type"] = TEST_EVENT_TYPE;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    Json::Reader reader;
+    Json::Value response;
+    reader.parse(TEST_RESP_CONTENT, response);
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::AuditDeleteAllRules handler(conn);
+    communication::Event event(event_msg, conn);
+
+    EXPECT_CALL(audit, audit_trail_create(_))
+            .WillRepeatedly(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(audit, audit_trail_foreach_rule(_, _))
+            .WillRepeatedly(Return(AUDIT_TRAIL_ERROR_NONE));
+    //EXPECT_CALL(audit, audit_trail_remove_rule(_))
+            //.WillOnce(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(rest, doPost(_, Eq(TEST_EVENT_CURI), TypedEq<const Json::Value&>(response)))
+            .Times(1);
+
+    ASSERT_NO_THROW(handler.accept(event));
+}
diff --git a/utest/test_auditrequestrulehandler.cpp b/utest/test_auditrequestrulehandler.cpp
new file mode 100644 (file)
index 0000000..4b26e43
--- /dev/null
@@ -0,0 +1,119 @@
+/**
+ * Samsung Ukraine R&D Center (SRK under a contract between)
+ * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
+ * Copyright (C) 2018 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 <gmock/gmock.h>
+#include <stdexcept>
+#include <jsoncpp/json/reader.h>
+#include "auditrequestrulehandler.h"
+#include "restservicemock.h"
+#include "audit_trail_mock.h"
+#include "settings.h"
+
+using ::testing::_;
+using ::testing::A;
+using ::testing::DoAll;
+using ::testing::SaveArg;
+using ::testing::Eq;
+using ::testing::TypedEq;
+using ::testing::Return;
+using ::testing::Throw;
+
+namespace
+{
+const std::string TEST_DUID{"device-id"};
+const std::chrono::milliseconds TEST_KEEPALIVE{1};
+const std::string TEST_EVENT_URI{"test-uri"};
+const std::string TEST_EVENT_CURI{"test-curi"};
+const std::string REQUEST_KEY{"request-existing-rules"};
+const std::string ENFORCE_KEY{"response-existing-rules"};
+const std::string RESPONSE_KEY{"state-rule"};
+const std::string REQUEST_CONTENT{R"#({"type":"request-existing-rules"})#"};
+const std::string ENFORCE_CONTENT{R"#({"type":"response-existing-rules","data":[{"key":"test","syscall":[1]}]})#"};
+const std::string RESPONSE_CONTENT{R"#({"type":"state-rule","data":[{"condition":[],"key":"test","syscall":[1]}]})#"};
+}
+
+/**
+ * @brief TEST for normal request sequence
+ */
+TEST(TestAuditRequestRuleHandler, test_request)
+{
+    RestServiceMock rest;
+    Json::Reader reader;
+    Json::Value request;
+    reader.parse(REQUEST_CONTENT, request);
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::AuditRequestRuleHandler handler(conn);
+
+    EXPECT_CALL(rest, sendData(_, TypedEq<const Json::Value&>(request)))
+            .WillOnce(Throw(std::runtime_error("sendData failed!")))
+            .WillOnce(Return());
+
+    ASSERT_NO_THROW(handler.request());
+}
+
+/**
+ * @brief TEST that event not confirmed when device is locked
+ */
+TEST(TestAuditRequestRuleHandler, test_accept_when_locked)
+{
+    RestServiceMock rest;
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::AuditRequestRuleHandler handler(conn);
+    Json::Value event_msg;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    event_msg["type"] = ENFORCE_KEY;
+    communication::Event event(event_msg, conn);
+
+    agent::Settings::instance().setLock(true);
+    EXPECT_NO_THROW(handler.accept(event));
+    agent::Settings::instance().setLock(false);
+}
+
+/**
+ * @brief TEST for normal accept sequence
+ */
+TEST(TestAuditRequestRuleHandler, test_accept)
+{
+    AuditTrailMock audit_trail;
+    AuditRuleMock audit_rule;
+    RestServiceMock rest;
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::AuditRequestRuleHandler handler(conn);
+    Json::Value event_msg;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    event_msg["type"] = ENFORCE_KEY;
+    communication::Event event(event_msg, conn);
+    Json::Reader reader;
+    Json::Value response;
+    reader.parse(RESPONSE_CONTENT, response);
+
+    EXPECT_CALL(audit_trail, audit_trail_create(_)).WillRepeatedly(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(audit_rule, audit_rule_create(_)).WillOnce(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(audit_rule, audit_rule_add_condition(_, _, _)).WillOnce(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(audit_rule, audit_rule_add_systemcall(_)).WillOnce(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(audit_trail, audit_trail_add_rule(_)).WillOnce(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(audit_rule, audit_rule_destroy()).WillOnce(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(audit_trail, audit_trail_foreach_rule(_, _)).WillOnce(Return(AUDIT_TRAIL_ERROR_NONE));
+
+    EXPECT_CALL(rest, doGet(_, Eq(TEST_EVENT_URI))).WillOnce(Return(ENFORCE_CONTENT));
+    EXPECT_CALL(rest, sendData(_, TypedEq<const Json::Value&>(response))).Times(1);
+    EXPECT_CALL(rest, doPost(_, Eq(TEST_EVENT_CURI), A<const std::string&>())).Times(1);
+
+    ASSERT_NO_THROW(handler.accept(event));
+}
diff --git a/utest/test_auditrewriterulehandler.cpp b/utest/test_auditrewriterulehandler.cpp
new file mode 100644 (file)
index 0000000..aa91e23
--- /dev/null
@@ -0,0 +1,95 @@
+/**
+ * Samsung Ukraine R&D Center (SRK under a contract between)
+ * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
+ * Copyright (C) 2018 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 <gmock/gmock.h>
+#include <jsoncpp/json/reader.h>
+#include "auditrewriterulehandler.h"
+#include "restservicemock.h"
+#include "audit_trail_mock.h"
+#include "settings.h"
+
+using ::testing::_;
+using ::testing::A;
+using ::testing::DoAll;
+using ::testing::SaveArg;
+using ::testing::Eq;
+using ::testing::TypedEq;
+using ::testing::Return;
+
+namespace
+{
+const std::string TEST_DUID{"device-id"};
+const std::chrono::milliseconds TEST_KEEPALIVE{1};
+const std::string TEST_EVENT_URI{"test-uri"};
+const std::string TEST_EVENT_CURI{"test-curi"};
+const std::string ENFORCE_KEY{"rewrite-rule"};
+const std::string RESPONSE_KEY{"status-rule"};
+const std::string ENFORCE_CONTENT{R"#({"type":"rewrite-rule","data":[{"new":{"key":"test","syscall":[1]}}]})#"};
+const std::string RESPONSE_CONTENT{R"#({"data":{"result":[{"new":{"key":"test","syscall":[1]},"status":0}],"rules":[{"condition":[],"key":"test","syscall":[1]}]},"type":"status-rule"})#"};
+}
+
+/**
+ * @brief TEST that event not confirmed when device is locked
+ */
+TEST(TestAuditRewriteRuleHandler, test_accept_when_locked)
+{
+    RestServiceMock rest;
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::AuditRewriteRuleHandler handler(conn);
+    Json::Value event_msg;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    event_msg["type"] = ENFORCE_KEY;
+    communication::Event event(event_msg, conn);
+
+    agent::Settings::instance().setLock(true);
+    EXPECT_NO_THROW(handler.accept(event));
+    agent::Settings::instance().setLock(false);
+}
+
+/**
+ * @brief TEST for normal accept sequence
+ */
+TEST(TestAuditRewriteRuleHandler, test_accept)
+{
+    AuditTrailMock audit_trail;
+    AuditRuleMock audit_rule;
+    RestServiceMock rest;
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::AuditRewriteRuleHandler handler(conn);
+    Json::Value event_msg;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    event_msg["type"] = ENFORCE_KEY;
+    communication::Event event(event_msg, conn);
+    Json::Reader reader;
+    Json::Value response;
+    reader.parse(RESPONSE_CONTENT, response);
+
+    EXPECT_CALL(audit_trail, audit_trail_create(_)).WillRepeatedly(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(audit_trail, audit_trail_foreach_rule(_, _)).WillRepeatedly(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(audit_rule, audit_rule_create(_)).WillOnce(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(audit_rule, audit_rule_add_condition(_, _, _)).WillOnce(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(audit_rule, audit_rule_add_systemcall(_)).WillOnce(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(audit_trail, audit_trail_add_rule(_)).WillOnce(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(audit_rule, audit_rule_destroy()).WillOnce(Return(AUDIT_TRAIL_ERROR_NONE));
+
+    EXPECT_CALL(rest, doGet(_, Eq(TEST_EVENT_URI))).WillOnce(Return(ENFORCE_CONTENT));
+    EXPECT_CALL(rest, doPost(_, Eq(TEST_EVENT_CURI), TypedEq<const Json::Value&>(response))).Times(1);
+
+    ASSERT_NO_THROW(handler.accept(event));
+}
diff --git a/utest/test_auditrewriterulesethandler.cpp b/utest/test_auditrewriterulesethandler.cpp
new file mode 100644 (file)
index 0000000..23914ed
--- /dev/null
@@ -0,0 +1,90 @@
+/**
+ * Samsung Ukraine R&D Center (SRK under a contract between)
+ * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
+ * Copyright (C) 2018 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 <gmock/gmock.h>
+#include <jsoncpp/json/reader.h>
+#include "auditrewriterulesethandler.h"
+#include "restservicemock.h"
+#include "audit_trail_mock.h"
+#include "settings.h"
+
+using ::testing::_;
+using ::testing::A;
+using ::testing::DoAll;
+using ::testing::SaveArg;
+using ::testing::Eq;
+using ::testing::TypedEq;
+using ::testing::Return;
+
+namespace
+{
+const std::string TEST_DUID{"device-id"};
+const std::chrono::milliseconds TEST_KEEPALIVE{1};
+const std::string TEST_EVENT_URI{"test-uri"};
+const std::string TEST_EVENT_CURI{"test-curi"};
+const std::string ENFORCE_KEY{"rewrite-profile"};
+const std::string RESPONSE_KEY{"status-profile"};
+const std::string ENFORCE_CONTENT{R"#({"type":"rewrite-profile", "data":["profile"]})#"};
+const std::string RESPONSE_CONTENT{R"#({"type":"status-profile","data":{"result":[{"name":"profile","status":0}],"rules":[]}})#"};
+}
+
+/**
+ * @brief TEST that event not confirmed when device is locked
+ */
+TEST(TestAuditRewriteRulesetHandler, test_accept_when_locked)
+{
+    RestServiceMock rest;
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::AuditRewriteRulesetHandler handler(conn);
+    Json::Value event_msg;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    event_msg["type"] = ENFORCE_KEY;
+    communication::Event event(event_msg, conn);
+
+    agent::Settings::instance().setLock(true);
+    EXPECT_NO_THROW(handler.accept(event));
+    agent::Settings::instance().setLock(false);
+}
+
+/**
+ * @brief TEST for normal accept sequence
+ */
+TEST(TestAuditRewriteRulesetHandler, test_accept)
+{
+    AuditTrailMock audit_trail;
+    RestServiceMock rest;
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::AuditRewriteRulesetHandler handler(conn);
+    Json::Value event_msg;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    event_msg["type"] = ENFORCE_KEY;
+    communication::Event event(event_msg, conn);
+    Json::Reader reader;
+    Json::Value response;
+    reader.parse(RESPONSE_CONTENT, response);
+
+    EXPECT_CALL(audit_trail, audit_trail_create(_)).WillRepeatedly(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(audit_trail, audit_trail_foreach_rule(_, _)).WillRepeatedly(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(audit_trail, audit_trail_load_ruleset(_)).WillOnce(Return(AUDIT_TRAIL_ERROR_NONE));
+
+    EXPECT_CALL(rest, doGet(_, Eq(TEST_EVENT_URI))).WillOnce(Return(ENFORCE_CONTENT));
+    EXPECT_CALL(rest, doPost(_, Eq(TEST_EVENT_CURI), TypedEq<const Json::Value&>(response))).Times(1);
+
+    ASSERT_NO_THROW(handler.accept(event));
+}
diff --git a/utest/test_auditupdaterulesethandler.cpp b/utest/test_auditupdaterulesethandler.cpp
new file mode 100644 (file)
index 0000000..7bbcfa6
--- /dev/null
@@ -0,0 +1,149 @@
+/**
+ * Samsung Ukraine R&D Center (SRK under a contract between)
+ * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
+ * Copyright (C) 2018 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 <gmock/gmock.h>
+#include <jsoncpp/json/reader.h>
+#include "auditupdaterulesethandler.h"
+#include "restservicemock.h"
+#include "audit_trail_mock.h"
+#include "settings.h"
+
+using ::testing::_;
+using ::testing::A;
+using ::testing::DoAll;
+using ::testing::SaveArg;
+using ::testing::Eq;
+using ::testing::TypedEq;
+using ::testing::Return;
+
+namespace
+{
+const std::string TEST_DUID{"device-id"};
+const std::chrono::milliseconds TEST_KEEPALIVE{1};
+const std::string TEST_EVENT_TYPE{"rule"};
+const std::string TEST_EVENT_URI{"test-uri"};
+const std::string TEST_EVENT_CURI{"test-curi"};
+const std::string TEST_UPDATE_CONTENT{R"#({"type":"update-profile", "data":["profile"]})#"};
+const std::string TEST_RESP_CONTENT{R"#({"type":"status-profile","data":{"result":[{"name":"profile","status":0}],"rules":[]}})#"};
+const std::string TEST_EMPTY_CONTENT{""};
+const std::string TEST_RESP_EMPTY_CONTENT{R"#({"type":"status-profile","data":null})#"};
+const std::string TEST_MALFORMED_CONTENT{"!@#$%^&*()_"};
+}
+
+/**
+ * @brief TEST that event not confirmed when device is locked
+ */
+TEST(TestAuditUpdateRulesetHandler, test_accept_when_locked)
+{
+    RestServiceMock rest;
+    Json::Value event_msg;
+    agent::Settings::instance().setLock(true);
+    event_msg["type"] = TEST_EVENT_TYPE;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::AuditUpdateRulesetHandler handler(conn);
+    communication::Event event(event_msg, conn);
+
+    EXPECT_NO_THROW(handler.accept(event));
+    agent::Settings::instance().setLock(false);
+}
+
+/**
+ * @brief TEST for normal accept sequence
+ */
+TEST(TestAuditUpdateRulesetHandler, test_accept)
+{
+    RestServiceMock rest;
+    Json::Value event_msg;
+    AuditTrailMock audit;
+    event_msg["type"] = TEST_EVENT_TYPE;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    Json::Reader reader;
+    Json::Value response;
+    reader.parse(TEST_RESP_CONTENT, response);
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::AuditUpdateRulesetHandler handler(conn);
+    communication::Event event(event_msg, conn);
+
+    EXPECT_CALL(audit, audit_trail_create(_))
+            .WillRepeatedly(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(audit, audit_trail_load_ruleset(_))
+            .WillOnce(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(audit, audit_trail_foreach_rule(_, _))
+            .WillOnce(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(rest, doGet(_, Eq(TEST_EVENT_URI)))
+            .WillOnce(Return(TEST_UPDATE_CONTENT));
+    EXPECT_CALL(rest, doPost(_, Eq(TEST_EVENT_CURI), TypedEq<const Json::Value&>(response)))
+            .Times(1);
+
+    ASSERT_NO_THROW(handler.accept(event));
+}
+
+/**
+ * @brief TEST work when event content is empty
+ */
+TEST(TestAuditUpdateRulesetHandler, test_empty_content)
+{
+    RestServiceMock rest;
+    Json::Value event_msg;
+    AuditTrailMock audit;
+    event_msg["type"] = TEST_EVENT_TYPE;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    Json::Reader reader;
+    Json::Value response;
+    reader.parse(TEST_RESP_EMPTY_CONTENT, response);
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::AuditUpdateRulesetHandler handler(conn);
+    communication::Event event(event_msg, conn);
+
+    EXPECT_CALL(audit, audit_trail_create(_))
+            .WillRepeatedly(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(rest, doGet(_, Eq(TEST_EVENT_URI)))
+            .WillOnce(Return(TEST_EMPTY_CONTENT));
+    EXPECT_CALL(rest, doPost(_, Eq(TEST_EVENT_CURI), TypedEq<const Json::Value&>(response)))
+            .Times(1);
+
+    ASSERT_NO_THROW(handler.accept(event));
+}
+
+/**
+ * @brief TEST malformed JSON is recieved
+ */
+TEST(TestAuditUpdateRulesetHandler, test_exception_in_accept)
+{
+    RestServiceMock rest;
+    Json::Value event_msg, result;
+    AuditTrailMock audit;
+    event_msg["type"] = TEST_EVENT_TYPE;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::AuditUpdateRulesetHandler handler(conn);
+    communication::Event event(event_msg, conn);
+
+    EXPECT_CALL(audit, audit_trail_create(_))
+            .WillRepeatedly(Return(AUDIT_TRAIL_ERROR_NONE));
+    EXPECT_CALL(rest, doGet(_, Eq(TEST_EVENT_URI)))
+            .WillOnce(Return(TEST_MALFORMED_CONTENT));
+    EXPECT_CALL(rest, doPost(_, Eq(TEST_EVENT_CURI), A<const Json::Value&>()))
+            .WillOnce(SaveArg<2>(&result));
+
+    ASSERT_NO_THROW(handler.accept(event));
+}
diff --git a/utest/test_dbuslistener.cpp b/utest/test_dbuslistener.cpp
new file mode 100644 (file)
index 0000000..44f80d9
--- /dev/null
@@ -0,0 +1,94 @@
+/**
+ * Samsung Ukraine R&D Center (SRK under a contract between)
+ * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
+ * Copyright (C) 2018 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 <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <memory>
+#include <functional>
+#include <thread>
+#include "dbuslistener.h"
+#include "dbushandler.h"
+#include "dbus_mock.h"
+
+using ::testing::_;
+using ::testing::Eq;
+using ::testing::Return;
+
+/**
+ * @brief Test for failed CTOR
+ */
+TEST(TestDBusListener, test_ctor_failed_1)
+{
+    DBusConnectionMock conn;
+    EXPECT_CALL(conn, dbus_bus_get(_, _)).WillOnce(Return(nullptr));
+
+    std::shared_ptr<dbus::DBusListener> listener = nullptr;
+    EXPECT_ANY_THROW(listener = std::make_shared<dbus::DBusListener>([](){return true;}));
+}
+
+/**
+ * @brief Test for failed CTOR
+ */
+TEST(TestDBusListener, test_ctor_failed_2)
+{
+    DBusConnectionMock conn;
+    EXPECT_CALL(conn, dbus_bus_get(_, _)).WillOnce(Return(&conn));
+    EXPECT_CALL(conn, dbus_bus_request_name(_, _, _)).WillOnce(Return(-1));
+    EXPECT_CALL(conn, dbus_connection_unref()).Times(1);
+
+    std::shared_ptr<dbus::DBusListener> listener = nullptr;
+    EXPECT_ANY_THROW(listener = std::make_shared<dbus::DBusListener>([](){return true;}));
+}
+
+/**
+ * @brief Test CTOR for normal sequence
+ */
+TEST(TestDBusListener, test_ctor_success)
+{
+    DBusConnectionMock conn;
+    EXPECT_CALL(conn, dbus_bus_get(_, _)).WillOnce(Return(&conn));
+    EXPECT_CALL(conn, dbus_bus_request_name(_, _, _)).WillOnce(Return(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER));
+    EXPECT_CALL(conn, dbus_bus_add_match(_, _)).Times(1);
+    EXPECT_CALL(conn, dbus_connection_flush()).Times(1);
+    EXPECT_CALL(conn, dbus_connection_unref()).Times(1);
+
+    std::shared_ptr<dbus::DBusListener> listener = nullptr;
+    EXPECT_NO_THROW(listener = std::make_shared<dbus::DBusListener>([](){return true;}));
+}
+
+/**
+ * @brief Test loop for normal sequence
+ */
+TEST(TestDBusListener, test_loop)
+{
+    DBusConnectionMock conn;
+    EXPECT_CALL(conn, dbus_bus_get(_, _)).WillOnce(Return(&conn));
+    EXPECT_CALL(conn, dbus_bus_request_name(_, _, _)).WillOnce(Return(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER));
+    EXPECT_CALL(conn, dbus_bus_add_match(_, _)).Times(1);
+    EXPECT_CALL(conn, dbus_connection_flush()).Times(1);
+    EXPECT_CALL(conn, dbus_connection_read_write(_)).WillOnce(Return(true));
+    EXPECT_CALL(conn, dbus_connection_pop_message()).WillOnce(Return(nullptr));
+    EXPECT_CALL(conn, dbus_connection_unref()).Times(1);
+
+    bool allowed = true;
+    dbus::DBusListener listener{[&allowed](){return allowed;}};
+
+    std::thread t(&dbus::DBusListener::loop, &listener);
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    allowed = false;
+    t.join();
+}
diff --git a/utest/test_killprocesshandler.cpp b/utest/test_killprocesshandler.cpp
new file mode 100644 (file)
index 0000000..326f7b8
--- /dev/null
@@ -0,0 +1,175 @@
+/**
+ * Samsung Ukraine R&D Center (SRK under a contract between)
+ * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
+ * Copyright (C) 2018 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 <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <memory>
+#include <functional>
+#include <thread>
+#include <jsoncpp/json/reader.h>
+#include <jsoncpp/json/writer.h>
+#include "dbuslistener.h"
+#include "dbushandler.h"
+#include "killprocesshandler.h"
+#include "settings.h"
+#include "dbus_mock.h"
+#include "sys_mock.h"
+
+using ::testing::_;
+using ::testing::Eq;
+using ::testing::StrEq;
+using ::testing::Return;
+using ::testing::DoAll;
+using ::testing::Invoke;
+
+namespace
+{
+const int PID = 1234;
+const char* TEST_SIGNAL = "{\"type\":\"kill_process\",\"data\":{\"pid\":1234}}";
+const char* TEST_SIGNAL_EMPTY_DATA = "{\"type\":\"kill_process\",\"data\":{}}";
+const char* TEST_SIGNAL_INCORRECT_PID = "{\"type\":\"kill_process\",\"data\":{\"pid\":\"1234\"}}";
+}
+
+/**
+ * @brief Test signal when device is locked
+ */
+TEST(TestKillProcessHandler, test_process_locked)
+{
+    DBusConnectionMock conn;
+    DBusMessageMock msg;
+    DBusMessageIterMock iter;
+    EXPECT_CALL(conn, dbus_bus_get(_, _)).WillOnce(Return(&conn));
+    EXPECT_CALL(conn, dbus_bus_request_name(_, _, _)).WillOnce(Return(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER));
+    EXPECT_CALL(conn, dbus_bus_add_match(_, _)).Times(1);
+    EXPECT_CALL(conn, dbus_connection_flush()).Times(1);
+    EXPECT_CALL(conn, dbus_connection_read_write(_)).WillRepeatedly(Return(true));
+    EXPECT_CALL(conn, dbus_connection_pop_message()).WillOnce(Return(&msg)).WillRepeatedly(Return(nullptr));
+    EXPECT_CALL(conn, dbus_connection_unref()).Times(1);
+    EXPECT_CALL(msg, dbus_message_is_signal(_, _)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_iter_init(_)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_unref()).Times(1);
+    EXPECT_CALL(iter, dbus_message_iter_get_arg_type()).WillOnce(Return(DBUS_TYPE_STRING));
+    EXPECT_CALL(iter, dbus_message_iter_get_basic(_)).WillOnce(Invoke([](void* value) {*(char**)value = strdup(TEST_SIGNAL);}));
+
+    bool allowed = true;
+    dbus::DBusListener listener{[&allowed](){return allowed;}};
+    dbus::KillProcessHandler handler{listener};
+
+    agent::Settings::instance().setLock(true);
+
+    std::thread t(&dbus::DBusListener::loop, &listener);
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    allowed = false;
+    t.join();
+
+    agent::Settings::instance().setLock(false);
+}
+
+/**
+ * @brief Test signal with empty data
+ */
+TEST(TestKillProcessHandler, test_process_empty_data)
+{
+    DBusConnectionMock conn;
+    DBusMessageMock msg;
+    DBusMessageIterMock iter;
+    EXPECT_CALL(conn, dbus_bus_get(_, _)).WillOnce(Return(&conn));
+    EXPECT_CALL(conn, dbus_bus_request_name(_, _, _)).WillOnce(Return(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER));
+    EXPECT_CALL(conn, dbus_bus_add_match(_, _)).Times(1);
+    EXPECT_CALL(conn, dbus_connection_flush()).Times(1);
+    EXPECT_CALL(conn, dbus_connection_read_write(_)).WillRepeatedly(Return(true));
+    EXPECT_CALL(conn, dbus_connection_pop_message()).WillOnce(Return(&msg)).WillRepeatedly(Return(nullptr));
+    EXPECT_CALL(conn, dbus_connection_unref()).Times(1);
+    EXPECT_CALL(msg, dbus_message_is_signal(_, _)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_iter_init(_)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_unref()).Times(1);
+    EXPECT_CALL(iter, dbus_message_iter_get_arg_type()).WillOnce(Return(DBUS_TYPE_STRING));
+    EXPECT_CALL(iter, dbus_message_iter_get_basic(_)).WillOnce(Invoke([](void* value) {*(char**)value = strdup(TEST_SIGNAL_EMPTY_DATA);}));
+
+    bool allowed = true;
+    dbus::DBusListener listener{[&allowed](){return allowed;}};
+    dbus::KillProcessHandler handler{listener};
+
+    std::thread t(&dbus::DBusListener::loop, &listener);
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    allowed = false;
+    t.join();
+}
+
+/**
+ * @brief Test signal with invalid pid
+ */
+TEST(TestKillProcessHandler, test_process_invalid_pid)
+{
+    DBusConnectionMock conn;
+    DBusMessageMock msg;
+    DBusMessageIterMock iter;
+    EXPECT_CALL(conn, dbus_bus_get(_, _)).WillOnce(Return(&conn));
+    EXPECT_CALL(conn, dbus_bus_request_name(_, _, _)).WillOnce(Return(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER));
+    EXPECT_CALL(conn, dbus_bus_add_match(_, _)).Times(1);
+    EXPECT_CALL(conn, dbus_connection_flush()).Times(1);
+    EXPECT_CALL(conn, dbus_connection_read_write(_)).WillRepeatedly(Return(true));
+    EXPECT_CALL(conn, dbus_connection_pop_message()).WillOnce(Return(&msg)).WillRepeatedly(Return(nullptr));
+    EXPECT_CALL(conn, dbus_connection_unref()).Times(1);
+    EXPECT_CALL(msg, dbus_message_is_signal(_, _)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_iter_init(_)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_unref()).Times(1);
+    EXPECT_CALL(iter, dbus_message_iter_get_arg_type()).WillOnce(Return(DBUS_TYPE_STRING));
+    EXPECT_CALL(iter, dbus_message_iter_get_basic(_)).WillOnce(Invoke([](void* value) {*(char**)value = strdup(TEST_SIGNAL_INCORRECT_PID);}));
+
+    bool allowed = true;
+    dbus::DBusListener listener{[&allowed](){return allowed;}};
+    dbus::KillProcessHandler handler{listener};
+
+    std::thread t(&dbus::DBusListener::loop, &listener);
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    allowed = false;
+    t.join();
+}
+
+/**
+ * @brief Test signal for normal sequence
+ */
+TEST(TestKillProcessHandler, test_process)
+{
+    DBusConnectionMock conn;
+    DBusMessageMock msg;
+    DBusMessageIterMock iter;
+    SysMock sys;
+    EXPECT_CALL(conn, dbus_bus_get(_, _)).WillOnce(Return(&conn));
+    EXPECT_CALL(conn, dbus_bus_request_name(_, _, _)).WillOnce(Return(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER));
+    EXPECT_CALL(conn, dbus_bus_add_match(_, _)).Times(1);
+    EXPECT_CALL(conn, dbus_connection_flush()).Times(1);
+    EXPECT_CALL(conn, dbus_connection_read_write(_)).WillRepeatedly(Return(true));
+    EXPECT_CALL(conn, dbus_connection_pop_message()).WillOnce(Return(&msg)).WillRepeatedly(Return(nullptr));
+    EXPECT_CALL(conn, dbus_connection_unref()).Times(1);
+    EXPECT_CALL(msg, dbus_message_is_signal(_, _)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_iter_init(_)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_unref()).Times(1);
+    EXPECT_CALL(iter, dbus_message_iter_get_arg_type()).WillOnce(Return(DBUS_TYPE_STRING));
+    EXPECT_CALL(iter, dbus_message_iter_get_basic(_)).WillOnce(Invoke([](void* value) {*(char**)value = strdup(TEST_SIGNAL);}));
+    EXPECT_CALL(sys, kill(Eq(PID), Eq(SIGKILL))).WillOnce(Return(0));
+
+    bool allowed = true;
+    dbus::DBusListener listener{[&allowed](){return allowed;}};
+    dbus::KillProcessHandler handler{listener};
+
+    std::thread t(&dbus::DBusListener::loop, &listener);
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    allowed = false;
+    t.join();
+}
diff --git a/utest/test_notificationhandler.cpp b/utest/test_notificationhandler.cpp
new file mode 100644 (file)
index 0000000..09d16c4
--- /dev/null
@@ -0,0 +1,207 @@
+/**
+ * Samsung Ukraine R&D Center (SRK under a contract between)
+ * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
+ * Copyright (C) 2018 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 <gmock/gmock.h>
+#include <jsoncpp/json/reader.h>
+#include "notificationhandler.h"
+#include "restservicemock.h"
+#include "app_control_mock.h"
+#include "settings.h"
+
+using ::testing::_;
+using ::testing::A;
+using ::testing::DoAll;
+using ::testing::SaveArg;
+using ::testing::Eq;
+using ::testing::StrEq;
+using ::testing::TypedEq;
+using ::testing::Return;
+
+namespace
+{
+const std::string TEST_DUID{"device-id"};
+const std::chrono::milliseconds TEST_KEEPALIVE{1};
+const std::string TEST_EVENT_URI{"test-uri"};
+const std::string TEST_EVENT_CURI{"test-curi"};
+const std::string ENFORCE_KEY{"notify_user"};
+const std::string EMPTY_CONTENT{""};
+const std::string NOTIFICATION_SERVICE{"org.example.samnotificationservice"};
+const std::string UNINSTALL_APP_EMPTY_CONTENT{R"#({"type":"notify-user","data":{"action":"uninstall_application"}})#"};
+const std::string UNINSTALL_APP_CONTENT{R"#({"type":"notify-user","data":{"action":"uninstall_application","subject":"org.example.photostealware"}})#"};
+const std::string UNINSTALL_APP_EX_DATA_KEY{ENFORCE_KEY};
+const std::string UNINSTALL_APP_EX_DATA_VAL{"{\"title\":\"SAM notification\",\"body\":\"Stealware process was detected [photostealware]. Remove it?\",\"buttons\":[{\"action\":{\"data\":{\"app_id\":\"org.example.photostealware\"},\"type\":\"uninstall_application\"},\"caption\":\"YES\"},{\"caption\":\"NO\"}]}"};
+const std::string KILL_PROCESS_EMPTY_CONTENT{R"#({"type":"notify-user","data":{"action":"kill_process"}})#"};
+const std::string KILL_PROCESS_CONTENT{R"#({"type":"notify-user","data":{"action":"kill_process","pid":1234,"path":"/usr/app/xmrstack"}})#"};
+const std::string KILL_PROCESS_EX_DATA_KEY{ENFORCE_KEY};
+const std::string KILL_PROCESS_EX_DATA_VAL{""};
+const std::string UNKNOWN_ACTION_CONTENT{R"#({"type":"notify-user","data":{"action":"undef"}})#"};
+}
+
+/**
+ * @brief TEST that event not confirmed when device is locked
+ */
+TEST(TestNotificationHandler, test_accept_when_locked)
+{
+    RestServiceMock rest;
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::NotificationHandler handler(conn);
+    Json::Value event_msg;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    event_msg["type"] = ENFORCE_KEY;
+    communication::Event event(event_msg, conn);
+
+    agent::Settings::instance().setLock(true);
+    EXPECT_NO_THROW(handler.accept(event));
+    agent::Settings::instance().setLock(false);
+}
+
+/**
+ * @brief TEST for empty content
+ */
+TEST(TestNotificationHandler, test_accept_empty_content)
+{
+    RestServiceMock rest;
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::NotificationHandler handler(conn);
+    Json::Value event_msg;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    event_msg["type"] = ENFORCE_KEY;
+    communication::Event event(event_msg, conn);
+
+    EXPECT_CALL(rest, doGet(_, Eq(TEST_EVENT_URI))).WillOnce(Return(EMPTY_CONTENT));
+    EXPECT_CALL(rest, doPost(_, Eq(TEST_EVENT_CURI), A<const std::string&>())).Times(1);
+
+    ASSERT_NO_THROW(handler.accept(event));
+}
+
+/**
+ * @brief TEST for uninstall application with empty subject
+ */
+TEST(TestNotificationHandler, test_accept_uninstall_application_empty_content)
+{
+    RestServiceMock rest;
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::NotificationHandler handler(conn);
+    Json::Value event_msg;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    event_msg["type"] = ENFORCE_KEY;
+    communication::Event event(event_msg, conn);
+
+    EXPECT_CALL(rest, doGet(_, Eq(TEST_EVENT_URI))).WillOnce(Return(UNINSTALL_APP_EMPTY_CONTENT));
+    EXPECT_CALL(rest, doPost(_, Eq(TEST_EVENT_CURI), A<const std::string&>())).Times(1);
+
+    ASSERT_NO_THROW(handler.accept(event));
+}
+
+/**
+ * @brief TEST for uninstall application
+ */
+TEST(TestNotificationHandler, test_accept_uninstall_application)
+{
+    RestServiceMock rest;
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::NotificationHandler handler(conn);
+    Json::Value event_msg;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    event_msg["type"] = ENFORCE_KEY;
+    communication::Event event(event_msg, conn);
+    AppControlMock app_ctrl;
+
+    EXPECT_CALL(app_ctrl, app_control_create(_)).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_set_operation(_)).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_set_app_id(StrEq(NOTIFICATION_SERVICE))).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_add_extra_data(StrEq(UNINSTALL_APP_EX_DATA_KEY), _)).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_send_launch_request(_, _)).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_destroy()).WillOnce(Return(0));
+
+    EXPECT_CALL(rest, doGet(_, Eq(TEST_EVENT_URI))).WillOnce(Return(UNINSTALL_APP_CONTENT));
+    EXPECT_CALL(rest, doPost(_, Eq(TEST_EVENT_CURI), A<const std::string&>())).Times(1);
+
+    ASSERT_NO_THROW(handler.accept(event));
+}
+
+/**
+ * @brief TEST for kill process with empty content
+ */
+TEST(TestNotificationHandler, test_accept_kill_process_empty_content)
+{
+    RestServiceMock rest;
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::NotificationHandler handler(conn);
+    Json::Value event_msg;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    event_msg["type"] = ENFORCE_KEY;
+    communication::Event event(event_msg, conn);
+
+    EXPECT_CALL(rest, doGet(_, Eq(TEST_EVENT_URI))).WillOnce(Return(KILL_PROCESS_EMPTY_CONTENT));
+    EXPECT_CALL(rest, doPost(_, Eq(TEST_EVENT_CURI), A<const std::string&>())).Times(1);
+
+    ASSERT_NO_THROW(handler.accept(event));
+}
+
+/**
+ * @brief TEST for kill process
+ */
+TEST(TestNotificationHandler, test_accept_kill_process)
+{
+    RestServiceMock rest;
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::NotificationHandler handler(conn);
+    Json::Value event_msg;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    event_msg["type"] = ENFORCE_KEY;
+    communication::Event event(event_msg, conn);
+    AppControlMock app_ctrl;
+
+    EXPECT_CALL(app_ctrl, app_control_create(_)).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_set_operation(_)).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_set_app_id(StrEq(NOTIFICATION_SERVICE))).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_add_extra_data(StrEq(KILL_PROCESS_EX_DATA_KEY), _)).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_send_launch_request(_, _)).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_destroy()).WillOnce(Return(0));
+
+    EXPECT_CALL(rest, doGet(_, Eq(TEST_EVENT_URI))).WillOnce(Return(KILL_PROCESS_CONTENT));
+    EXPECT_CALL(rest, doPost(_, Eq(TEST_EVENT_CURI), A<const std::string&>())).Times(1);
+
+    ASSERT_NO_THROW(handler.accept(event));
+}
+
+/**
+ * @brief TEST for unknown action
+ */
+TEST(TestNotificationHandler, test_accept_unknown_action)
+{
+    RestServiceMock rest;
+    communication::Connection conn(TEST_DUID, TEST_KEEPALIVE, &rest, [](){return true;});
+    agent::NotificationHandler handler(conn);
+    Json::Value event_msg;
+    event_msg["uri"] = TEST_EVENT_URI;
+    event_msg["curi"] = TEST_EVENT_CURI;
+    event_msg["type"] = ENFORCE_KEY;
+    communication::Event event(event_msg, conn);
+
+    EXPECT_CALL(rest, doGet(_, Eq(TEST_EVENT_URI))).WillOnce(Return(UNKNOWN_ACTION_CONTENT));
+    EXPECT_CALL(rest, doPost(_, Eq(TEST_EVENT_CURI), A<const std::string&>())).Times(1);
+
+    ASSERT_NO_THROW(handler.accept(event));
+}
diff --git a/utest/test_notifyuserhandler.cpp b/utest/test_notifyuserhandler.cpp
new file mode 100644 (file)
index 0000000..d3dd1fe
--- /dev/null
@@ -0,0 +1,150 @@
+/**
+ * Samsung Ukraine R&D Center (SRK under a contract between)
+ * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
+ * Copyright (C) 2018 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 <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <memory>
+#include <functional>
+#include <thread>
+#include <jsoncpp/json/reader.h>
+#include <jsoncpp/json/writer.h>
+#include "dbuslistener.h"
+#include "dbushandler.h"
+#include "notifyuserhandler.h"
+#include "settings.h"
+#include "dbus_mock.h"
+#include "app_control_mock.h"
+
+using ::testing::_;
+using ::testing::Eq;
+using ::testing::StrEq;
+using ::testing::Return;
+using ::testing::DoAll;
+using ::testing::Invoke;
+
+namespace
+{
+const std::string APP_ID{"org.example.samnotificationservice"};
+const std::string EX_DATA_KEY{"notify_user"};
+const std::string EX_DATA_VAL{"{\"title\":\"TITLE\"}\n"};
+const char* TEST_SIGNAL = "{\"type\":\"notify_user\",\"data\":{\"title\":\"TITLE\"}}";
+const char* TEST_SIGNAL_EMPTY_DATA = "{\"type\":\"notify_user\",\"data\":{}}";
+}
+
+/**
+ * @brief Test signal when device is locked
+ */
+TEST(TestNotifyUserHandler, test_process_locked)
+{
+    DBusConnectionMock conn;
+    DBusMessageMock msg;
+    DBusMessageIterMock iter;
+    EXPECT_CALL(conn, dbus_bus_get(_, _)).WillOnce(Return(&conn));
+    EXPECT_CALL(conn, dbus_bus_request_name(_, _, _)).WillOnce(Return(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER));
+    EXPECT_CALL(conn, dbus_bus_add_match(_, _)).Times(1);
+    EXPECT_CALL(conn, dbus_connection_flush()).Times(1);
+    EXPECT_CALL(conn, dbus_connection_read_write(_)).WillRepeatedly(Return(true));
+    EXPECT_CALL(conn, dbus_connection_pop_message()).WillOnce(Return(&msg)).WillRepeatedly(Return(nullptr));
+    EXPECT_CALL(conn, dbus_connection_unref()).Times(1);
+    EXPECT_CALL(msg, dbus_message_is_signal(_, _)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_iter_init(_)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_unref()).Times(1);
+    EXPECT_CALL(iter, dbus_message_iter_get_arg_type()).WillOnce(Return(DBUS_TYPE_STRING));
+    EXPECT_CALL(iter, dbus_message_iter_get_basic(_)).WillOnce(Invoke([](void* value) {*(char**)value = strdup(TEST_SIGNAL);}));
+
+    bool allowed = true;
+    dbus::DBusListener listener{[&allowed](){return allowed;}};
+    dbus::NotifyUserHandler handler{listener};
+
+    agent::Settings::instance().setLock(true);
+
+    std::thread t(&dbus::DBusListener::loop, &listener);
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    allowed = false;
+    t.join();
+
+    agent::Settings::instance().setLock(false);
+}
+
+/**
+ * @brief Test signal with empty data
+ */
+TEST(TestNotifyUserHandler, test_process_empty_data)
+{
+    DBusConnectionMock conn;
+    DBusMessageMock msg;
+    DBusMessageIterMock iter;
+    EXPECT_CALL(conn, dbus_bus_get(_, _)).WillOnce(Return(&conn));
+    EXPECT_CALL(conn, dbus_bus_request_name(_, _, _)).WillOnce(Return(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER));
+    EXPECT_CALL(conn, dbus_bus_add_match(_, _)).Times(1);
+    EXPECT_CALL(conn, dbus_connection_flush()).Times(1);
+    EXPECT_CALL(conn, dbus_connection_read_write(_)).WillRepeatedly(Return(true));
+    EXPECT_CALL(conn, dbus_connection_pop_message()).WillOnce(Return(&msg)).WillRepeatedly(Return(nullptr));
+    EXPECT_CALL(conn, dbus_connection_unref()).Times(1);
+    EXPECT_CALL(msg, dbus_message_is_signal(_, _)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_iter_init(_)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_unref()).Times(1);
+    EXPECT_CALL(iter, dbus_message_iter_get_arg_type()).WillOnce(Return(DBUS_TYPE_STRING));
+    EXPECT_CALL(iter, dbus_message_iter_get_basic(_)).WillOnce(Invoke([](void* value) {*(char**)value = strdup(TEST_SIGNAL_EMPTY_DATA);}));
+
+    bool allowed = true;
+    dbus::DBusListener listener{[&allowed](){return allowed;}};
+    dbus::NotifyUserHandler handler{listener};
+
+    std::thread t(&dbus::DBusListener::loop, &listener);
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    allowed = false;
+    t.join();
+}
+
+/**
+ * @brief Test signal for normal sequence
+ */
+TEST(TestNotifyUserHandler, test_process)
+{
+    DBusConnectionMock conn;
+    DBusMessageMock msg;
+    DBusMessageIterMock iter;
+    AppControlMock app_ctrl;
+    EXPECT_CALL(conn, dbus_bus_get(_, _)).WillOnce(Return(&conn));
+    EXPECT_CALL(conn, dbus_bus_request_name(_, _, _)).WillOnce(Return(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER));
+    EXPECT_CALL(conn, dbus_bus_add_match(_, _)).Times(1);
+    EXPECT_CALL(conn, dbus_connection_flush()).Times(1);
+    EXPECT_CALL(conn, dbus_connection_read_write(_)).WillRepeatedly(Return(true));
+    EXPECT_CALL(conn, dbus_connection_pop_message()).WillOnce(Return(&msg)).WillRepeatedly(Return(nullptr));
+    EXPECT_CALL(conn, dbus_connection_unref()).Times(1);
+    EXPECT_CALL(msg, dbus_message_is_signal(_, _)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_iter_init(_)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_unref()).Times(1);
+    EXPECT_CALL(iter, dbus_message_iter_get_arg_type()).WillOnce(Return(DBUS_TYPE_STRING));
+    EXPECT_CALL(iter, dbus_message_iter_get_basic(_)).WillOnce(Invoke([](void* value) {*(char**)value = strdup(TEST_SIGNAL);}));
+    EXPECT_CALL(app_ctrl, app_control_create(_)).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_set_operation(_)).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_set_app_id(StrEq(APP_ID))).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_add_extra_data(StrEq(EX_DATA_KEY), StrEq(EX_DATA_VAL))).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_send_launch_request(_, _)).WillOnce(Return(0));
+    EXPECT_CALL(app_ctrl, app_control_destroy()).WillOnce(Return(0));
+
+    bool allowed = true;
+    dbus::DBusListener listener{[&allowed](){return allowed;}};
+    dbus::NotifyUserHandler handler{listener};
+
+    std::thread t(&dbus::DBusListener::loop, &listener);
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    allowed = false;
+    t.join();
+}
diff --git a/utest/test_uninstallhandler.cpp b/utest/test_uninstallhandler.cpp
new file mode 100644 (file)
index 0000000..7ce144b
--- /dev/null
@@ -0,0 +1,177 @@
+/**
+ * Samsung Ukraine R&D Center (SRK under a contract between)
+ * LLC "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
+ * Copyright (C) 2018 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 <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <memory>
+#include <functional>
+#include <thread>
+#include <jsoncpp/json/reader.h>
+#include <jsoncpp/json/writer.h>
+#include "dbuslistener.h"
+#include "dbushandler.h"
+#include "uninstallhandler.h"
+#include "settings.h"
+#include "dbus_mock.h"
+#include "device_policy_manager_mock.h"
+
+using ::testing::_;
+using ::testing::Eq;
+using ::testing::StrEq;
+using ::testing::Return;
+using ::testing::DoAll;
+using ::testing::Invoke;
+
+namespace
+{
+const std::string APP_ID = "org.example.photostealware";
+const char* TEST_SIGNAL = "{\"type\":\"uninstall_application\",\"data\":{\"app_id\":\"org.example.photostealware\"}}";
+const char* TEST_SIGNAL_EMPTY_DATA = "{\"type\":\"uninstall_application\"}";
+const char* TEST_SIGNAL_INCORRECT_APP_ID = "{\"type\":\"uninstall_application\",\"data\":{\"app_id\":0}}";
+}
+
+/**
+ * @brief Test signal when device is locked
+ */
+TEST(TestUninstallHandler, test_process_locked)
+{
+    DBusConnectionMock conn;
+    DBusMessageMock msg;
+    DBusMessageIterMock iter;
+    EXPECT_CALL(conn, dbus_bus_get(_, _)).WillOnce(Return(&conn));
+    EXPECT_CALL(conn, dbus_bus_request_name(_, _, _)).WillOnce(Return(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER));
+    EXPECT_CALL(conn, dbus_bus_add_match(_, _)).Times(1);
+    EXPECT_CALL(conn, dbus_connection_flush()).Times(1);
+    EXPECT_CALL(conn, dbus_connection_read_write(_)).WillRepeatedly(Return(true));
+    EXPECT_CALL(conn, dbus_connection_pop_message()).WillOnce(Return(&msg)).WillRepeatedly(Return(nullptr));
+    EXPECT_CALL(conn, dbus_connection_unref()).Times(1);
+    EXPECT_CALL(msg, dbus_message_is_signal(_, _)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_iter_init(_)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_unref()).Times(1);
+    EXPECT_CALL(iter, dbus_message_iter_get_arg_type()).WillOnce(Return(DBUS_TYPE_STRING));
+    EXPECT_CALL(iter, dbus_message_iter_get_basic(_)).WillOnce(Invoke([](void* value) {*(char**)value = strdup(TEST_SIGNAL);}));
+
+    bool allowed = true;
+    dbus::DBusListener listener{[&allowed](){return allowed;}};
+    dbus::UninstallHandler handler{listener};
+
+    agent::Settings::instance().setLock(true);
+
+    std::thread t(&dbus::DBusListener::loop, &listener);
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    allowed = false;
+    t.join();
+
+    agent::Settings::instance().setLock(false);
+}
+
+/**
+ * @brief Test signal with empty data
+ */
+TEST(TestUninstallHandler, test_process_empty_data)
+{
+    DBusConnectionMock conn;
+    DBusMessageMock msg;
+    DBusMessageIterMock iter;
+    EXPECT_CALL(conn, dbus_bus_get(_, _)).WillOnce(Return(&conn));
+    EXPECT_CALL(conn, dbus_bus_request_name(_, _, _)).WillOnce(Return(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER));
+    EXPECT_CALL(conn, dbus_bus_add_match(_, _)).Times(1);
+    EXPECT_CALL(conn, dbus_connection_flush()).Times(1);
+    EXPECT_CALL(conn, dbus_connection_read_write(_)).WillRepeatedly(Return(true));
+    EXPECT_CALL(conn, dbus_connection_pop_message()).WillOnce(Return(&msg)).WillRepeatedly(Return(nullptr));
+    EXPECT_CALL(conn, dbus_connection_unref()).Times(1);
+    EXPECT_CALL(msg, dbus_message_is_signal(_, _)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_iter_init(_)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_unref()).Times(1);
+    EXPECT_CALL(iter, dbus_message_iter_get_arg_type()).WillOnce(Return(DBUS_TYPE_STRING));
+    EXPECT_CALL(iter, dbus_message_iter_get_basic(_)).WillOnce(Invoke([](void* value) {*(char**)value = strdup(TEST_SIGNAL_EMPTY_DATA);}));
+
+    bool allowed = true;
+    dbus::DBusListener listener{[&allowed](){return allowed;}};
+    dbus::UninstallHandler handler{listener};
+
+    std::thread t(&dbus::DBusListener::loop, &listener);
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    allowed = false;
+    t.join();
+}
+
+/**
+ * @brief Test signal with invalid application id
+ */
+TEST(TestUninstallHandler, test_process_invalid_app_id)
+{
+    DBusConnectionMock conn;
+    DBusMessageMock msg;
+    DBusMessageIterMock iter;
+    EXPECT_CALL(conn, dbus_bus_get(_, _)).WillOnce(Return(&conn));
+    EXPECT_CALL(conn, dbus_bus_request_name(_, _, _)).WillOnce(Return(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER));
+    EXPECT_CALL(conn, dbus_bus_add_match(_, _)).Times(1);
+    EXPECT_CALL(conn, dbus_connection_flush()).Times(1);
+    EXPECT_CALL(conn, dbus_connection_read_write(_)).WillRepeatedly(Return(true));
+    EXPECT_CALL(conn, dbus_connection_pop_message()).WillOnce(Return(&msg)).WillRepeatedly(Return(nullptr));
+    EXPECT_CALL(conn, dbus_connection_unref()).Times(1);
+    EXPECT_CALL(msg, dbus_message_is_signal(_, _)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_iter_init(_)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_unref()).Times(1);
+    EXPECT_CALL(iter, dbus_message_iter_get_arg_type()).WillOnce(Return(DBUS_TYPE_STRING));
+    EXPECT_CALL(iter, dbus_message_iter_get_basic(_)).WillOnce(Invoke([](void* value) {*(char**)value = strdup(TEST_SIGNAL_INCORRECT_APP_ID);}));
+
+    bool allowed = true;
+    dbus::DBusListener listener{[&allowed](){return allowed;}};
+    dbus::UninstallHandler handler{listener};
+
+    std::thread t(&dbus::DBusListener::loop, &listener);
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    allowed = false;
+    t.join();
+}
+
+/**
+ * @brief Test signal for normal sequence
+ */
+TEST(TestUninstallHandler, test_process)
+{
+    DBusConnectionMock conn;
+    DBusMessageMock msg;
+    DBusMessageIterMock iter;
+    DPMMock dpm;
+    EXPECT_CALL(conn, dbus_bus_get(_, _)).WillOnce(Return(&conn));
+    EXPECT_CALL(conn, dbus_bus_request_name(_, _, _)).WillOnce(Return(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER));
+    EXPECT_CALL(conn, dbus_bus_add_match(_, _)).Times(1);
+    EXPECT_CALL(conn, dbus_connection_flush()).Times(1);
+    EXPECT_CALL(conn, dbus_connection_read_write(_)).WillRepeatedly(Return(true));
+    EXPECT_CALL(conn, dbus_connection_pop_message()).WillOnce(Return(&msg)).WillRepeatedly(Return(nullptr));
+    EXPECT_CALL(conn, dbus_connection_unref()).Times(1);
+    EXPECT_CALL(msg, dbus_message_is_signal(_, _)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_iter_init(_)).WillOnce(Return(true));
+    EXPECT_CALL(msg, dbus_message_unref()).Times(1);
+    EXPECT_CALL(iter, dbus_message_iter_get_arg_type()).WillOnce(Return(DBUS_TYPE_STRING));
+    EXPECT_CALL(iter, dbus_message_iter_get_basic(_)).WillOnce(Invoke([](void* value) {*(char**)value = strdup(TEST_SIGNAL);}));
+    EXPECT_CALL(dpm, dpm_manager_create()).WillOnce(Return(&dpm));
+    EXPECT_CALL(dpm, dpm_application_uninstall_package(StrEq(APP_ID))).WillOnce(Return(0));
+    EXPECT_CALL(dpm, dpm_manager_destroy()).Times(1);
+
+    bool allowed = true;
+    dbus::DBusListener listener{[&allowed](){return allowed;}};
+    dbus::UninstallHandler handler{listener};
+
+    std::thread t(&dbus::DBusListener::loop, &listener);
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    allowed = false;
+    t.join();
+}