libsessiond API. 00/273500/10
authorArkadiusz Nowak <a.nowak3@samsung.com>
Tue, 22 Mar 2022 07:37:26 +0000 (08:37 +0100)
committerMateusz Majewski <m.majewski2@samsung.com>
Thu, 14 Apr 2022 14:40:25 +0000 (16:40 +0200)
subsession_add_user
subsession_remove_user
subsession_switch_user

subsession_add_user_wait_callback
subsession_add_user_wait_done
subsession_remove_user_wait_callback
subsession_remove_user_wait_done

Change-Id: I52ef7ea8aec569e3995f06ce3d2bd92159736f7e

14 files changed:
CMakeLists.txt
libsessiond/CMakeLists.txt
libsessiond/include/sessiond.h
libsessiond/src/lib.c
libsessiond/src/lib.h [new file with mode: 0644]
libsessiond/target_test/CMakeLists.txt [new file with mode: 0644]
libsessiond/target_test/test_api_add_remove_user.cpp [new file with mode: 0644]
libsessiond/target_test/test_api_add_remove_user_wait.cpp [new file with mode: 0644]
libsessiond/target_test/test_api_adduser.cpp [new file with mode: 0644]
libsessiond/target_test/test_api_adduserwait.cpp [new file with mode: 0644]
libsessiond/target_test/test_api_removeuser.cpp [new file with mode: 0644]
libsessiond/target_test/test_api_switchuser.cpp [new file with mode: 0644]
libsessiond/test/CMakeLists.txt
packaging/sessiond.spec

index 23ce9161a94b3b0d9c41d92597d59e7506c91df5..727ce1bcdbe0c1ab813a5602dd0f81ec00f4159f 100644 (file)
@@ -13,6 +13,13 @@ set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie")
 add_subdirectory(libsessiond)
 add_subdirectory(sessiond)
 
+option(ENABLE_TARGET_TESTS "On target tests" ON)
+if(ENABLE_TARGET_TESTS)
+       find_package(GTest REQUIRED)
+       add_subdirectory(libsessiond/target_test)
+endif(ENABLE_TARGET_TESTS)
+
+
 enable_testing()
 
 #set ON if want run libsessiond test
@@ -25,8 +32,9 @@ endif(ENABLE_LIB_TESTS)
 
 #set ON if want run sessiond tests
 option(ENABLE_SESSIOND_TESTS "Run sessiond unit tests after build" OFF)
+
 if(ENABLE_SESSIOND_TESTS)
        find_package(GTest REQUIRED)
        include(CTest)
        add_subdirectory(sessiond/test)
-endif(ENABLE_SESSIOND_TESTS)
+endif(ENABLE_SESSIOND_TEST)
index 3f139d663a8817b3d06150271b43757bde98abde..9bf90c54abadf828b16027fe6c0699500b7c8dfa 100644 (file)
@@ -1,5 +1,5 @@
 find_package(PkgConfig)
-pkg_check_modules(DEPS REQUIRED IMPORTED_TARGET capi-base-common)
+pkg_check_modules(DEPS REQUIRED IMPORTED_TARGET capi-base-common gio-2.0)
 
 set(
        libsessiond_SRCS
index cc5bd85de991e790b41dfba9b0d840c3b57cb0bd..2abea12ddce2cbb6a67e591c6916c434e99875d1 100644 (file)
@@ -29,7 +29,6 @@ extern "C" {
 #include <tizen.h>
 
 typedef  int (*reply_callback) (int result, void *cb_data);
-
 int subsession_add_user(int session_uid, int user, reply_callback cb, void *cb_data);
 int subsession_remove_user(int session_uid, int user, reply_callback cb, void *cb_data);
 int subsession_switch_user(int session_uid, int prev_user, int next_user, reply_callback cb, void *cb_data);
@@ -51,8 +50,11 @@ int subsession_switch_wait_callback(int session_uid, switch_wait_callback cb, vo
 int subsession_switch_wait_done(int session_uid, uint64_t switch_id);
 //Amd →(CALL)→ Sessiond
 
-typedef int (*switch_completion_callback)(int session_uid, uint64_t switch_id);
+typedef int (*switch_completion_callback)(int session_uid, int prev_user, int next_user, uint64_t switch_id);
 int subsession_switch_completion_callback(int session_uid, switch_completion_callback cb, void *cb_data);
+//new
+
+
 int subsession_get_user_list(int session_uid, int **user_list, int *user_count);
 int subsession_get_current_user(int session_uid, int *user);
 int subsession_is_supported (int *supported);
index 30a259ef0c32529244367a1b188d4ff54174c8c1..66c4b025a7c6e325826eeb7998860e15c53553aa 100644 (file)
@@ -1,3 +1,4 @@
+
 /* MIT License
  *
  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  * THE SOFTWARE. */
 
 
+#include <gio/gio.h>
+#include "lib.h"
 #include "sessiond.h"
 
+session_connection_data_t session_connection_data = {
+       .connection = NULL,
+       .bus_name = "org.tizen.sessiond",
+       .objpath = "/org/tizen/sessiond",
+       .interface = "org.tizen.sessiond.subsession.Manager",
+};
+
+static struct {
+       gchar * AddUser;
+       gchar * RemoveUser;
+       gchar * SwitchUser;
+       gchar * AddUserWait;
+       gchar * AddUserDone;
+       gchar * RemoveUserWait;
+       gchar * RemoveUserDone;
+
+} dbus_method_call = {
+       .AddUser = "AddUser",
+       .RemoveUser = "RemoveUser",
+       .SwitchUser = "SwitchUser",
+       .AddUserWait = "AddUserWait",
+       .AddUserDone = "AddUserDone",
+       .RemoveUserWait = "RemoveUserWait",
+       .RemoveUserDone = "RemoveUserDone",
+};
+
+static struct {
+       gchar * AddUserCompleted;
+       gchar * RemoveUserCompleted;
+       gchar * SwitchUserCompleted;
+       gchar * AddUserStarted;
+       gchar * RemoveUserStarted;
+
+} dbus_signal_name = {
+       .AddUserCompleted = "AddUserCompleted",
+       .RemoveUserCompleted = "RemoveUserCompleted",
+       .SwitchUserCompleted = "SwitchUserCompleted",
+       .AddUserStarted = "AddUserStarted",
+       .RemoveUserStarted = "RemoveUserStarted"
+};
+
+typedef  struct {
+       guint AddUserCompleted;
+       guint RemoveUserCompleted;
+       guint SwitchUserCompleted;
+       guint AddUserStarted;
+       guint RemoveUserStarted;
+ } dbus_signal_subscribed_t;
+
+dbus_signal_subscribed_t  dbus_signal_subscribed = {
+       .AddUserCompleted = 0,
+       .RemoveUserCompleted = 0,
+       .SwitchUserCompleted = 0,
+       .AddUserStarted = 0,
+       .RemoveUserStarted = 0,
+};
+
+GList *add_user_callbacks_list = NULL;
+GMutex add_user_mutex;
+
+GList *remove_user_callbacks_list = NULL;
+GMutex remove_user_mutex;
+
+
+GList *switch_user_callbacks_list = NULL;
+GMutex switch_user_mutex;
+
+
+GList *add_user_wait_callbacks_list = NULL;
+GMutex add_user_wait_mutex;
+
+
+typedef struct {
+       void *client_callback;
+       void *client_callback_data;
+       GVariant *params;
+       int signal_subscribed;
+} signal_client_data_t;
+
+signal_client_data_t *make_new_signal_callback_client_data(void *client_callback, void *client_callback_data, GVariant *params) {
+
+       signal_client_data_t *signal_data = (signal_client_data_t *)malloc(sizeof(signal_client_data_t));
+
+       if(signal_data != NULL) {
+               signal_data->client_callback = client_callback;
+               signal_data->client_callback_data = client_callback_data;
+               signal_data->params = params;
+               g_variant_ref(signal_data->params);
+               g_assert(params != NULL);
+               return signal_data;
+       }
+       return NULL;
+}
+
+gint g_compare_user_params (  gconstpointer client_data,   gconstpointer parameters) {
+
+       signal_client_data_t *signal_client_data = (signal_client_data_t*)client_data;
+
+       int client_session_uid = 0;
+       int client_user = 0;
+       g_variant_get(signal_client_data->params, "(ii)", &client_session_uid, &client_user);
+
+       GVariant *params = (GVariant *)parameters;
+
+       int params_session_uid = 0;
+       int params_user = 0;
+       int params_status = 0;
+
+       g_variant_get(params, "(iii)", &params_session_uid, &params_user, &params_status);
+
+       if( client_session_uid == params_session_uid &&
+               client_user == params_user) {
+
+                       return 0;
+               }
+       return -1;
+}
+
+static void signal_add_user_complete_handler(
+       GDBusConnection *connection,
+       const gchar *sender_name,
+       const gchar *object_path,
+       const gchar *interface_name,
+       const gchar *signal_name,
+       GVariant *parameters,
+       gpointer client_data) {
+
+       int ret_session_uid = 0;
+       int ret_user = 0;
+       int ret_status = 0;
+       g_variant_get(parameters, "(iii)", &ret_session_uid, &ret_user, &ret_status);
+
+       signal_client_data_t *signal_data = NULL;
+       g_mutex_lock(&add_user_mutex);
+               GList *found_data = g_list_find_custom( add_user_callbacks_list, (gconstpointer) parameters, g_compare_user_params );
+               if (found_data != NULL) {
+                       signal_data = (signal_client_data_t*)found_data->data;
+                       add_user_callbacks_list = g_list_remove(add_user_callbacks_list, found_data->data);
+                       g_list_free (g_steal_pointer (&found_data));
+               }
+       g_mutex_unlock(&add_user_mutex);
+
+       if(signal_data == NULL) {
+               return;
+       }
+
+       if(signal_data->client_callback == NULL) {
+               return ;
+       }
+
+       reply_callback reply_cb = signal_data->client_callback;
+
+       void *client_callback_data = signal_data->client_callback_data;
+       reply_cb(ret_status, client_callback_data);
+
+       g_variant_unref(signal_data->params);
+       free(signal_data);
+       return;
+}
+
+static void signal_remove_user_complete_handler(
+       GDBusConnection *connection,
+       const gchar *sender_name,
+       const gchar *object_path,
+       const gchar *interface_name,
+       const gchar *signal_name,
+       GVariant *parameters,
+       gpointer client_data) {
+
+       int ret_session_uid = 0;
+       int ret_user = 0;
+       int ret_status = 0;
+       g_variant_get(parameters, "(iii)", &ret_session_uid, &ret_user, &ret_status);
+
+       signal_client_data_t *signal_data = NULL;
+       g_mutex_lock(&remove_user_mutex);
+               GList *found_data = g_list_find_custom( remove_user_callbacks_list, (gconstpointer) parameters, g_compare_user_params );
+               if (found_data != NULL) {
+                       signal_data = (signal_client_data_t*)found_data->data;
+                       remove_user_callbacks_list = g_list_remove(remove_user_callbacks_list, found_data->data);
+                       g_list_free (g_steal_pointer (&found_data));
+               }
+       g_mutex_unlock(&remove_user_mutex);
+
+       if(signal_data == NULL) {
+               return;
+       }
+
+       if(signal_data->client_callback == NULL) {
+               return ;
+       }
+
+       reply_callback reply_cb = signal_data->client_callback;
+
+       void *client_callback_data = signal_data->client_callback_data;
+       reply_cb(ret_status, client_callback_data);
+
+       g_variant_unref(signal_data->params);
+       free(signal_data);
+       return;
+}
+
+gint g_compare_switch_user_params (  gconstpointer client_data,   gconstpointer parameters) {
+
+       signal_client_data_t *signal_client_data = (signal_client_data_t*)client_data;
+
+       int client_session_uid = 0;
+       int client_prev_user = 0;
+       int client_next_user = 0;
+       g_variant_get(signal_client_data->params, "(iii)", &client_session_uid, &client_prev_user, &client_next_user);
+
+       GVariant *params = (GVariant *)parameters;
+
+       int params_session_uid = 0;
+       int params_switch_id = 0;
+       int params_prev_user = 0;
+       int params_next_user = 0;
+       int status_code = 0;
+
+       g_variant_get(params, "(ixiii)", &params_session_uid, &params_switch_id, &params_prev_user, &params_next_user, &status_code );
+
+       gboolean all_ok = (client_session_uid == params_session_uid) &&
+                                        (client_prev_user == params_prev_user) &&
+                                        (client_next_user == params_next_user);
+
+
+       if( all_ok) {
+                       return 0;
+       }
+       return -1;
+}
+
+static void signal_switch_user_complete_handler(
+       GDBusConnection *connection,
+       const gchar *sender_name,
+       const gchar *object_path,
+       const gchar *interface_name,
+       const gchar *signal_name,
+       GVariant *parameters,
+       gpointer client_data) {
+
+
+       int ret_session_uid = 0;
+       int ret_switch_id = 0;
+       int ret_prev_user = 0;
+       int ret_next_user = 0;
+       int ret_code = 0;
+       g_variant_get(parameters, "(ixiii)", &ret_session_uid, &ret_switch_id, &ret_prev_user, &ret_next_user, &ret_code );
+
+       signal_client_data_t *signal_data = NULL;
+       g_mutex_lock(&switch_user_mutex);
+
+               GList *found_data = g_list_find_custom( switch_user_callbacks_list, (gconstpointer) parameters, g_compare_switch_user_params );
+               if (found_data != NULL) {
+                       signal_data = (signal_client_data_t*)found_data->data;
+                       switch_user_callbacks_list = g_list_remove(switch_user_callbacks_list, found_data->data);
+                       g_list_free (g_steal_pointer (&found_data));
+               }
+       g_mutex_unlock(&switch_user_mutex);
+
+       if(signal_data == NULL) {
+               return;
+       }
+
+       if(signal_data->client_callback == NULL) {
+               return ;
+       }
+
+       reply_callback reply_cb = signal_data->client_callback;
+
+       void *client_callback_data = signal_data->client_callback_data;
+       reply_cb(ret_code, client_callback_data);
+
+       g_variant_unref(signal_data->params);
+       free(signal_data);
+       return;
+}
+
+static void signal_add_user_started_callback(GDBusConnection *connection,
+       const gchar *sender_name,
+       const gchar *object_path,
+       const gchar *interface_name,
+       const gchar *signal_name,
+       GVariant *parameters,
+       gpointer client_data)
+{
+
+       signal_client_data_t *signal_data = (signal_client_data_t *)client_data;
+
+       add_user_wait_callback add_user_wait_cb = signal_data->client_callback;
+
+       int ret_session_uid = 0;
+       int ret_user_id = 0;
+       g_variant_get(parameters,"(ii)", &ret_session_uid,  &ret_user_id);
+
+       int par_session_uid = 0;
+
+       GVariant *signal_variant_params = signal_data->params;
+       g_variant_get(signal_variant_params, "(i)", &par_session_uid );
+
+       gboolean all_params_ok = (par_session_uid == ret_session_uid);
+
+       if (all_params_ok ) {
+                       g_variant_unref(signal_data->params);
+                       add_user_wait_cb(ret_session_uid, ret_user_id, signal_data->client_callback_data);
+               //      g_dbus_connection_signal_unsubscribe(connection, signal_data->signal_subscribed);
+                       return;
+       }
+
+       g_variant_unref(signal_data->params);
+       add_user_wait_cb(-EFAULT, -EFAULT,  signal_data->client_callback_data);
+       //g_dbus_connection_signal_unsubscribe(connection, signal_data->signal_subscribed);
+       return;
+}
+
+static void signal_remove_user_started_callback(GDBusConnection *connection,
+       const gchar *sender_name,
+       const gchar *object_path,
+       const gchar *interface_name,
+       const gchar *signal_name,
+       GVariant *parameters,
+       gpointer client_data)
+{
+
+       signal_client_data_t *signal_data = (signal_client_data_t *)client_data;
+
+       remove_user_wait_callback remove_user_wait_cb = signal_data->client_callback;
+
+       int ret_session_uid = 0;
+       int ret_user_id = 0;
+       g_variant_get(parameters,"(ii)", &ret_session_uid,  &ret_user_id);
+
+       int par_session_uid = 0;
+
+       GVariant *signal_variant_params = signal_data->params;
+       g_variant_get(signal_variant_params, "(i)", &par_session_uid );
+
+       gboolean all_params_ok = (par_session_uid == ret_session_uid);
+
+       if (all_params_ok ) {
+                       g_variant_unref(signal_data->params);
+                       remove_user_wait_cb(ret_session_uid, ret_user_id, signal_data->client_callback_data);
+                       //g_dbus_connection_signal_unsubscribe(connection, signal_data->signal_subscribed);
+                       return;
+       }
+
+       g_variant_unref(signal_data->params);
+       remove_user_wait_cb(-EFAULT, -EFAULT,  signal_data->client_callback_data);
+       //g_dbus_connection_signal_unsubscribe(connection, signal_data->signal_subscribed);
+       return;
+}
+
+static void signal_unsubscribed_callback(void *data) {
+       if(data == NULL) {
+               return;
+       }
+       signal_client_data_t *signal_data = (signal_client_data_t *)data;
+       free(signal_data);
+}
+
+int method_call(gchar *method, GVariant *params, gchar *signal_name, GDBusSignalCallback signal_callback, void *client_callback, void *client_callback_data) {
+
+       GError *error;
+       error = NULL;
+
+       if (session_connection_data.connection == NULL) {
+               session_connection_data.connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+               g_assert_no_error(error);
+               g_assert(session_connection_data.connection != NULL);
+       }
+
+       if(client_callback == NULL || client_callback_data == NULL ) {
+               return -EINVAL;
+       }
+
+       signal_client_data_t *signal_client_data = make_new_signal_callback_client_data(client_callback, client_callback_data, params);
+
+       if(signal_client_data == NULL) {
+               return -ENOMEM;
+       }
+
+               signal_client_data->signal_subscribed = g_dbus_connection_signal_subscribe( session_connection_data.connection,
+               session_connection_data.bus_name ,
+               session_connection_data.interface,
+               signal_name,
+               session_connection_data.objpath,
+               NULL,
+               G_DBUS_SIGNAL_FLAGS_NONE,
+               signal_callback,
+               signal_client_data,
+               signal_unsubscribed_callback
+               );
+
+       g_print("signal name: %s : signal_subscribed %d\n", signal_name, signal_client_data->signal_subscribed );
+
+       GVariant *retgv = NULL;
+       GError *call_sync_error;
+       call_sync_error = NULL;
+
+       retgv = g_dbus_connection_call_sync(
+               session_connection_data.connection,
+               session_connection_data.bus_name,
+               session_connection_data.objpath,
+               session_connection_data.interface,
+               method, params,
+               NULL,
+               G_DBUS_CALL_FLAGS_NONE,
+               10,
+        NULL,
+        &call_sync_error
+       );
+
+       if (!retgv || call_sync_error) {
+               g_error_free(call_sync_error);
+               return -EFAULT;
+       }
+       return 0;
+}
+
+int method_call_MS(gchar *method, GVariant *params, gchar *signal_name, guint *signal_subscribed_id, GDBusSignalCallback signal_callback) {
+       GError *error;
+       error = NULL;
+
+       if (session_connection_data.connection == NULL) {
+               session_connection_data.connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+               g_assert_no_error(error);
+               g_assert(session_connection_data.connection != NULL);
+       }
+
+       if( *signal_subscribed_id == 0 ) {
+                       *signal_subscribed_id = g_dbus_connection_signal_subscribe( session_connection_data.connection,
+                       session_connection_data.bus_name ,
+                       session_connection_data.interface,
+                       signal_name,
+                       session_connection_data.objpath,
+                       NULL,
+                       G_DBUS_SIGNAL_FLAGS_NONE,
+                       signal_callback,
+                       NULL,
+                       signal_unsubscribed_callback );
+       }
+
+       GVariant *retgv = NULL;
+       GError *call_sync_error;
+       call_sync_error = NULL;
+
+       retgv = g_dbus_connection_call_sync(
+               session_connection_data.connection,
+               session_connection_data.bus_name,
+               session_connection_data.objpath,
+               session_connection_data.interface,
+               method, params,
+               NULL,
+               G_DBUS_CALL_FLAGS_NONE,
+               10,
+        NULL,
+        &call_sync_error
+       );
+
+       if (!retgv || call_sync_error) {
+               g_error_free(call_sync_error);
+               return -EFAULT;
+       }
+       return 0;
+}
+
+int method_call_no_signal(gchar *method, GVariant *params) {
+
+       GError *error;
+       error = NULL;
+
+       if (session_connection_data.connection == NULL) {
+               session_connection_data.connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+               g_assert_no_error(error);
+               g_assert(session_connection_data.connection != NULL);
+       }
+
+       GVariant *retgv = NULL;
+       GError *call_sync_error;
+       call_sync_error = NULL;
+
+       retgv = g_dbus_connection_call_sync(
+               session_connection_data.connection,
+               session_connection_data.bus_name,
+               session_connection_data.objpath,
+               session_connection_data.interface,
+               method, params,
+               NULL,
+               G_DBUS_CALL_FLAGS_NONE,
+               10,
+        NULL,
+        &call_sync_error
+       );
+
+       if (!retgv || call_sync_error) {
+               g_error_free(call_sync_error);
+               return -EFAULT;
+       }
+       return 0;
+}
+
 int subsession_add_user(int session_uid, int user, reply_callback cb, void *cb_data) {
-       return TIZEN_ERROR_ACCOUNT;
+
+       g_mutex_lock (&add_user_mutex);
+
+       if(add_user_callbacks_list == NULL ) {
+               GVariant * empty_params;
+               empty_params = g_variant_new("(ii)", -1, -1);
+               signal_client_data_t *signal_client_empty_data =  make_new_signal_callback_client_data(NULL, NULL, empty_params);
+               add_user_callbacks_list = g_list_append(add_user_callbacks_list, (gpointer) signal_client_empty_data);
+       }
+
+       GVariant * params;
+       params = g_variant_new("(ii)", session_uid, user);
+
+       signal_client_data_t *signal_client_data = make_new_signal_callback_client_data(cb, cb_data, params);
+       add_user_callbacks_list = g_list_append(add_user_callbacks_list, (gpointer) signal_client_data);
+
+       g_mutex_unlock(&add_user_mutex);
+
+       return  method_call_MS (
+               dbus_method_call.AddUser, params,
+               dbus_signal_name.AddUserCompleted,
+               &dbus_signal_subscribed.AddUserCompleted,
+               signal_add_user_complete_handler);
 }
 
 int subsession_remove_user(int session_uid, int user, reply_callback cb, void *cb_data) {
-       return TIZEN_ERROR_ACCOUNT;
+
+       g_mutex_lock (&remove_user_mutex);
+
+       if(add_user_callbacks_list == NULL ) {
+               GVariant * empty_params;
+               empty_params = g_variant_new("(ii)", -1, -1);
+               signal_client_data_t *signal_client_empty_data =  make_new_signal_callback_client_data(NULL, NULL, empty_params);
+               remove_user_callbacks_list = g_list_append(remove_user_callbacks_list, (gpointer) signal_client_empty_data);
+       }
+
+       GVariant * params;
+       params = g_variant_new("(ii)", session_uid, user);
+
+       signal_client_data_t *signal_client_data = make_new_signal_callback_client_data(cb, cb_data, params);
+       remove_user_callbacks_list = g_list_append(remove_user_callbacks_list, (gpointer) signal_client_data);
+
+       g_mutex_unlock(&remove_user_mutex);
+
+       return  method_call_MS (
+               dbus_method_call.RemoveUser, params,
+               dbus_signal_name.RemoveUserCompleted,
+               &dbus_signal_subscribed.RemoveUserCompleted,
+               signal_remove_user_complete_handler);
+
 }
 
 int subsession_switch_user(int session_uid, int prev_user, int next_user, reply_callback cb, void *cb_data) {
 
-       return TIZEN_ERROR_ACCOUNT;
+
+       g_mutex_lock (&switch_user_mutex);
+
+       if(add_user_callbacks_list == NULL ) {
+               GVariant * empty_params;
+               empty_params = g_variant_new("(iii)", -1, -1, -1);
+               signal_client_data_t *signal_client_empty_data =  make_new_signal_callback_client_data(NULL, NULL, empty_params);
+               switch_user_callbacks_list = g_list_append(switch_user_callbacks_list, (gpointer) signal_client_empty_data);
+       }
+
+       GVariant * params;
+       params = g_variant_new("(iii)", session_uid, prev_user, next_user);
+
+       signal_client_data_t *signal_client_data = make_new_signal_callback_client_data(cb, cb_data, params);
+       switch_user_callbacks_list = g_list_append(switch_user_callbacks_list, (gpointer) signal_client_data);
+
+       g_mutex_unlock(&switch_user_mutex);
+
+
+       return  method_call_MS (
+               dbus_method_call.SwitchUser, params,
+               dbus_signal_name.SwitchUserCompleted,
+               &dbus_signal_subscribed.SwitchUserCompleted,
+               signal_switch_user_complete_handler);
+       return 0;
 }
 
 //Amd →(REGISTER WAIT CALLBACK)→ Sessiond
@@ -42,21 +615,48 @@ int subsession_switch_user(int session_uid, int prev_user, int next_user, reply_
 
 int subsession_add_user_wait_callback(int session_uid, add_user_wait_callback cb, void *cb_data) {
 
+
+       GVariant * params;
+       params = g_variant_new("(i)", session_uid);
+       return  method_call (
+               dbus_method_call.AddUserWait, params,
+               dbus_signal_name.AddUserStarted,
+               signal_add_user_started_callback,
+               (void*)cb, cb_data);
+
        return TIZEN_ERROR_ACCOUNT;
 }
 
 int subsession_add_user_wait_done(int session_uid, int user) {
 
+       GVariant * params;
+       params = g_variant_new("(ii)", session_uid, user);
+
+       return method_call_no_signal(dbus_method_call.AddUserDone, params);
+
        return TIZEN_ERROR_ACCOUNT;
 }
 
 int subsession_remove_user_wait_callback(int session_uid, remove_user_wait_callback cb, void *cb_data) {
 
+       GVariant * params;
+       params = g_variant_new("(i)", session_uid);
+       return  method_call (
+               dbus_method_call.RemoveUserWait, params,
+               dbus_signal_name.RemoveUserStarted,
+               signal_remove_user_started_callback,
+               (void*)cb, cb_data);
+
        return TIZEN_ERROR_ACCOUNT;
 }
 
 int subsession_remove_user_wait_done(int session_uid, int user) {
 
+       GVariant * params;
+       params = g_variant_new("(ii)", session_uid, user);
+
+       return method_call_no_signal(dbus_method_call.RemoveUserDone, params);
+
        return TIZEN_ERROR_ACCOUNT;
 }
 
@@ -69,10 +669,11 @@ int subsession_switch_wait_done(int session_uid, uint64_t switch_id) {
 
        return TIZEN_ERROR_ACCOUNT;
 }
-//Amd →(CALL)→ Sessiond
+
 
 int subsession_switch_completion_callback(int session_uid, switch_completion_callback cb, void *cb_data) {
 
+
        return TIZEN_ERROR_ACCOUNT;
 }
 
diff --git a/libsessiond/src/lib.h b/libsessiond/src/lib.h
new file mode 100644 (file)
index 0000000..7cc01e3
--- /dev/null
@@ -0,0 +1,40 @@
+/* MIT License
+ *
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE. */
+
+#pragma once
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <gio/gio.h>
+
+
+typedef struct {
+       GDBusConnection *connection;
+       gchar * bus_name;
+       gchar * objpath;
+       gchar * interface;
+} session_connection_data_t;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libsessiond/target_test/CMakeLists.txt b/libsessiond/target_test/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5194f60
--- /dev/null
@@ -0,0 +1,19 @@
+find_package(PkgConfig)
+pkg_check_modules(DEPS REQUIRED IMPORTED_TARGET glib-2.0 gio-2.0 gobject-2.0)
+
+function(add_libsd_target_test name wraps)
+       message("target_test: cmake src dir ====> ${CMAKE_SOURCE_DIR}")
+       set(CMAKE_CXX_STANDARD 20)
+       add_executable(test_${name} test_${name}.cpp)
+       message("CMAKE_BIN_DIR======> ${CMAKE_BINARY_DIR}")
+       include_directories(${CMAKE_SOURCE_DIR}/libsessiond/include ${CMAKE_SOURCE_DIR}/libsessiond/src)
+       target_link_libraries(test_${name} libsessiond gtest_main gtest PkgConfig::DEPS ${wraps})
+       install(TARGETS test_${name})
+endfunction(add_libsd_dev_test)
+
+add_libsd_target_test(api_adduser  "")
+add_libsd_target_test(api_removeuser  "")
+add_libsd_target_test(api_add_remove_user  "")
+add_libsd_target_test(api_switchuser  "")
+add_libsd_target_test(api_adduserwait  "")
+add_libsd_target_test(api_add_remove_user_wait  "")
diff --git a/libsessiond/target_test/test_api_add_remove_user.cpp b/libsessiond/target_test/test_api_add_remove_user.cpp
new file mode 100644 (file)
index 0000000..f855748
--- /dev/null
@@ -0,0 +1,98 @@
+#include<iostream>
+#include <gtest/gtest.h>
+#include <gio/gio.h>
+#include <pthread.h>
+#include "sessiond.h"
+
+// Test
+
+typedef struct {
+       int callback_result;
+} test_user_data;
+
+typedef struct {
+               GMainLoop * loop;
+               test_user_data *user_data;
+}ud_ctrl;
+
+
+int callback_pending_reference;
+
+gboolean callback_pending(gpointer data) {
+
+       ud_ctrl *ud = (ud_ctrl*)data;
+       gboolean is_pending = g_main_context_pending(NULL);
+       gint ctrl_value = g_atomic_int_get(&callback_pending_reference);
+
+       if(is_pending == TRUE) {
+               return TRUE;
+       }
+
+       if(ctrl_value >= 2) {
+               g_main_loop_quit((GMainLoop*)ud->loop);
+       }
+  return TRUE;
+}
+
+int test_reply_adduser_callback (int result, void *cb_data) {
+
+       g_atomic_int_inc(&callback_pending_reference);
+
+       test_user_data *user_data = (test_user_data *)cb_data;
+       user_data->callback_result = result;
+
+       if (result < 0) {
+               return result;
+       }
+
+       if (cb_data == NULL) {
+               return -EBADR;
+       }
+
+       return 0;
+}
+
+int test_reply_removeuser_callback (int result, void *cb_data) {
+
+       g_atomic_int_inc(&callback_pending_reference);
+
+       test_user_data *user_data = (test_user_data *)cb_data;
+       user_data->callback_result = result;
+
+       if (result < 0) {
+               return result;
+       }
+
+       if (cb_data == NULL) {
+               return -EBADR;
+       }
+
+       return 0;
+}
+
+TEST(subsession_add_remove_user_test, APIAddRemoveUserTest) {
+
+       GMainLoop* loop = NULL;
+       loop = g_main_loop_new (NULL, FALSE);
+       g_atomic_int_set(&callback_pending_reference, 0);
+
+       test_user_data test_add_ud;
+       test_add_ud.callback_result = -1;
+       int add_user_res = subsession_add_user(1, 2, test_reply_adduser_callback, (void *)&test_add_ud);
+
+       test_user_data test_remove_ud;
+       test_remove_ud.callback_result = -1;
+       int remove_user_res = subsession_remove_user(1, 2, test_reply_removeuser_callback, (void *)&test_remove_ud);
+
+       ud_ctrl ud;
+       ud.loop = loop;
+
+       g_idle_add(callback_pending,(gpointer*)&ud);
+       g_main_loop_run(loop);
+
+       EXPECT_EQ(add_user_res, 0);
+       EXPECT_EQ(remove_user_res, 0);
+       EXPECT_EQ(0, test_add_ud.callback_result);
+       EXPECT_EQ(0, test_remove_ud.callback_result);
+
+}
diff --git a/libsessiond/target_test/test_api_add_remove_user_wait.cpp b/libsessiond/target_test/test_api_add_remove_user_wait.cpp
new file mode 100644 (file)
index 0000000..fc59a0e
--- /dev/null
@@ -0,0 +1,217 @@
+#include<iostream>
+#include <gtest/gtest.h>
+#include <gio/gio.h>
+#include <pthread.h>
+#include "sessiond.h"
+
+// Test
+
+typedef struct {
+       int callback_result;
+       int session_id;
+       int user_id;
+} test_user_data;
+
+typedef struct {
+       int user;
+       int session_id;
+} test_user_wait_data;
+
+typedef struct {
+               GMainLoop * loop;
+               test_user_data *user_data;
+}ud_ctrl;
+
+
+int callback_adduser_reference;
+int callback_removeuser_reference;
+int callback_adduserstarted_reference;
+int callback_removeuserstarted_reference;
+
+gboolean callback_pending(gpointer data) {
+
+       ud_ctrl *ud = (ud_ctrl*)data;
+       gboolean is_pending = g_main_context_pending(NULL);
+       gint callback_adduser_calls = g_atomic_int_get(&callback_adduser_reference);
+       gint callback_removeuser_calls = g_atomic_int_get(&callback_removeuser_reference);
+       gint callback_adduserstarted_calls = g_atomic_int_get(&callback_removeuserstarted_reference);
+
+       if(is_pending == TRUE) {
+               return TRUE;
+       }
+
+       bool loop_quit_ready =
+                       (callback_adduser_calls >= 1) &&
+                       (callback_removeuser_calls >= 1) &&
+                       (callback_adduserstarted_calls >= 1) &&
+                       (callback_adduserstarted_calls >= 1);
+
+       if(loop_quit_ready) {
+               g_main_loop_quit((GMainLoop*)ud->loop);
+       }
+  return TRUE;
+}
+
+int test_reply_adduser_callback (int result, void *cb_data) {
+
+       g_atomic_int_inc(&callback_adduser_reference);
+
+       test_user_data *user_data = (test_user_data *)cb_data;
+       user_data->callback_result = result;
+
+       if (result < 0) {
+               return result;
+       }
+
+       if (cb_data == NULL) {
+               return -EBADR;
+       }
+
+       return 0;
+}
+
+int test_reply_removeuser_callback (int result, void *cb_data) {
+
+       g_atomic_int_inc(&callback_removeuser_reference);
+
+       test_user_data *user_data = (test_user_data *)cb_data;
+       user_data->callback_result = result;
+
+       if (result < 0) {
+               return result;
+       }
+
+       if (cb_data == NULL) {
+               return -EBADR;
+       }
+
+       return 0;
+}
+typedef  int (*add_user_wait_callback) (int session_uid, int user, void *cb_data);
+
+int test_add_user_wait_callback(int session_uid, int user, void *cb_data) {
+
+       g_atomic_int_inc(&callback_adduserstarted_reference);
+
+       test_user_data *user_data = (test_user_data *)cb_data;
+
+       int result = 0;
+
+       if(session_uid < 0) {
+               user_data->callback_result = session_uid;
+               result = session_uid;
+               return result;
+       }
+
+       if(user < 0) {
+               user_data->callback_result = user;
+               result = user;
+               return result;
+       }
+
+       if (user_data->session_id != session_uid) {
+               result = session_uid;
+               user_data->callback_result = result;
+               return result;
+       }
+       user_data->user_id = user;
+       user_data->callback_result =subsession_add_user_wait_done(session_uid, user);
+
+       return result;
+}
+
+
+int test_remove_user_wait_callback(int session_uid, int user, void *cb_data) {
+
+       g_atomic_int_inc(&callback_removeuserstarted_reference);
+
+       test_user_data *user_data = (test_user_data *)cb_data;
+
+       int result = 0;
+
+       if(session_uid < 0) {
+               user_data->callback_result = session_uid;
+               result = session_uid;
+               return result;
+       }
+
+       if(user < 0) {
+               user_data->callback_result = user;
+               result = user;
+               return result;
+       }
+
+       if (user_data->session_id != session_uid) {
+               result = session_uid;
+               user_data->callback_result = result;
+               return result;
+       }
+       user_data->user_id = user;
+       user_data->callback_result =subsession_remove_user_wait_done(session_uid, user);
+
+       return result;
+}
+
+TEST(subsession_add_remove_user_wait_test, APIAddRemoveUserWaitTest) {
+
+       GMainLoop* loop = NULL;
+       loop = g_main_loop_new (NULL, FALSE);
+
+       g_atomic_int_set(&callback_adduser_reference, 0);
+       g_atomic_int_set(&callback_adduserstarted_reference, 0);
+       g_atomic_int_set(&callback_removeuser_reference, 0);
+       g_atomic_int_set(&callback_removeuserstarted_reference, 0);
+
+       test_user_data test_add_wait_1_2;
+       test_add_wait_1_2.session_id = 1;
+       test_add_wait_1_2.user_id = -3;
+       test_add_wait_1_2.callback_result = -1;
+       int add_user_wait_res_1_2 = subsession_add_user_wait_callback(test_add_wait_1_2.session_id,
+                test_add_user_wait_callback, (void *)&test_add_wait_1_2);
+
+       test_user_data test_add_1_2;
+       test_add_1_2.session_id = 1;
+       test_add_1_2.user_id = 2;
+       test_add_1_2.callback_result = -1;
+       int add_user_res_1_2 = subsession_add_user(test_add_1_2.session_id, test_add_1_2.user_id,
+                test_reply_adduser_callback, (void *)&test_add_1_2);
+
+
+       test_user_data test_remove_wait_1_2;
+       test_remove_wait_1_2.session_id = 1;
+       test_remove_wait_1_2.user_id = -3;
+       test_remove_wait_1_2.callback_result = -1;
+       int remove_user_wait_res_1_2 = subsession_remove_user_wait_callback(test_add_wait_1_2.session_id,
+                test_remove_user_wait_callback, (void *)&test_remove_wait_1_2);
+
+       test_user_data test_remove_1_2;
+       test_remove_1_2.session_id = 1;
+       test_remove_1_2.user_id = 2;
+       test_remove_1_2.callback_result = -1;
+       int remove_user_res_1_2 = subsession_remove_user(test_remove_1_2.session_id, test_remove_1_2.user_id,
+               test_reply_removeuser_callback, (void *)&test_remove_1_2);
+
+       ud_ctrl ud;
+       ud.loop = loop;
+
+       g_idle_add(callback_pending,(gpointer*)&ud);
+       g_main_loop_run(loop);
+
+       EXPECT_EQ(add_user_wait_res_1_2, 0);
+       EXPECT_EQ(add_user_res_1_2, 0);
+
+       EXPECT_EQ(remove_user_wait_res_1_2, 0);
+       EXPECT_EQ(remove_user_res_1_2, 0);
+
+
+       EXPECT_EQ(0, test_add_wait_1_2.callback_result);
+       EXPECT_EQ(2, test_add_wait_1_2.user_id);
+
+
+       EXPECT_EQ(0, test_remove_wait_1_2.callback_result);
+       EXPECT_EQ(2, test_remove_wait_1_2.user_id);
+
+       EXPECT_EQ(0, test_add_1_2.callback_result);
+       EXPECT_EQ(0, test_remove_1_2.callback_result);
+
+}
diff --git a/libsessiond/target_test/test_api_adduser.cpp b/libsessiond/target_test/test_api_adduser.cpp
new file mode 100644 (file)
index 0000000..ebc9085
--- /dev/null
@@ -0,0 +1,76 @@
+#include<iostream>
+#include <gtest/gtest.h>
+#include <gio/gio.h>
+#include <pthread.h>
+#include "sessiond.h"
+
+// Test
+
+typedef struct {
+       int callback_result;
+} test_user_data;
+
+typedef struct {
+               GMainLoop * loop;
+               test_user_data *user_data;
+}ud_ctrl;
+
+
+int callback_pending_reference;
+
+gboolean callback_pending(gpointer data) {
+
+       ud_ctrl *ud = (ud_ctrl*)data;
+       gboolean is_pending = g_main_context_pending(NULL);
+       gint ctrl_value = g_atomic_int_get(&callback_pending_reference);
+
+       if(is_pending == TRUE) {
+               return TRUE;
+       }
+
+       if(ctrl_value >= 0) {
+               g_main_loop_quit((GMainLoop*)ud->loop);
+       }
+  return TRUE;
+}
+
+int test_reply_callback (int result, void *cb_data) {
+
+       g_atomic_int_set(&callback_pending_reference, 1);
+
+       test_user_data *user_data = (test_user_data *)cb_data;
+       user_data->callback_result = result;
+
+       if (result < 0) {
+               return result;
+       }
+
+       if (cb_data == NULL) {
+               return -EBADR;
+       }
+
+       return 0;
+}
+
+TEST(subsession_add_user_test, APIAddUserTest) {
+
+       GMainLoop* loop = NULL;
+       loop = g_main_loop_new (NULL, FALSE);
+       g_atomic_int_set(&callback_pending_reference, 0);
+
+       test_user_data test_ud;
+       test_ud.callback_result = -1;
+
+       int add_user_res = subsession_add_user(1, 2, test_reply_callback, (void *)&test_ud);
+
+       ud_ctrl ud;
+       ud.loop = loop;
+       ud.user_data = &test_ud;
+
+       g_idle_add(callback_pending,(gpointer*)&ud);
+       g_main_loop_run(loop);
+
+       EXPECT_EQ(add_user_res, 0);
+       EXPECT_EQ(0, test_ud.callback_result);
+
+}
diff --git a/libsessiond/target_test/test_api_adduserwait.cpp b/libsessiond/target_test/test_api_adduserwait.cpp
new file mode 100644 (file)
index 0000000..d01f542
--- /dev/null
@@ -0,0 +1,168 @@
+#include<iostream>
+#include <gtest/gtest.h>
+#include <gio/gio.h>
+#include <pthread.h>
+#include "sessiond.h"
+
+// Test
+
+typedef struct {
+       int callback_result;
+       int session_id;
+       int user_id;
+} test_user_data;
+
+typedef struct {
+       int user;
+       int session_id;
+} test_user_wait_data;
+
+typedef struct {
+               GMainLoop * loop;
+               test_user_data *user_data;
+}ud_ctrl;
+
+
+int callback_adduser_reference;
+int callback_removeuser_reference;
+int callback_adduserstarted_reference;
+
+gboolean callback_pending(gpointer data) {
+
+       ud_ctrl *ud = (ud_ctrl*)data;
+       gboolean is_pending = g_main_context_pending(NULL);
+       gint callback_adduser_calls = g_atomic_int_get(&callback_adduser_reference);
+       gint callback_removeuser_calls = g_atomic_int_get(&callback_removeuser_reference);
+       gint callback_adduserstarted_calls = g_atomic_int_get(&callback_adduserstarted_reference);
+
+       if(is_pending == TRUE) {
+               return TRUE;
+       }
+
+       bool loop_quit_ready =
+                       (callback_adduser_calls >= 1) &&
+                       (callback_removeuser_calls >= 1) &&
+                       (callback_adduserstarted_calls >= 1) ;
+
+       if(loop_quit_ready) {
+               g_main_loop_quit((GMainLoop*)ud->loop);
+       }
+  return TRUE;
+}
+
+int test_reply_adduser_callback (int result, void *cb_data) {
+
+       g_atomic_int_inc(&callback_adduser_reference);
+
+       test_user_data *user_data = (test_user_data *)cb_data;
+       user_data->callback_result = result;
+
+       if (result < 0) {
+               return result;
+       }
+
+       if (cb_data == NULL) {
+               return -EBADR;
+       }
+
+       return 0;
+}
+
+int test_reply_removeuser_callback (int result, void *cb_data) {
+
+       g_atomic_int_inc(&callback_removeuser_reference);
+
+       test_user_data *user_data = (test_user_data *)cb_data;
+       user_data->callback_result = result;
+
+       if (result < 0) {
+               return result;
+       }
+
+       if (cb_data == NULL) {
+               return -EBADR;
+       }
+
+       return 0;
+}
+typedef  int (*add_user_wait_callback) (int session_uid, int user, void *cb_data);
+
+int test_add_user_wait_callback(int session_uid, int user, void *cb_data) {
+
+       g_atomic_int_inc(&callback_adduserstarted_reference);
+
+       test_user_data *user_data = (test_user_data *)cb_data;
+
+       int result = 0;
+
+       if(session_uid < 0) {
+               user_data->callback_result = session_uid;
+               result = session_uid;
+               return result;
+       }
+
+       if(user < 0) {
+               user_data->callback_result = user;
+               result = user;
+               return result;
+       }
+
+       if (user_data->session_id != session_uid) {
+               result = session_uid;
+               user_data->callback_result = result;
+               return result;
+       }
+       user_data->user_id = user;
+       user_data->callback_result =subsession_add_user_wait_done(session_uid, user);
+
+       return result;
+}
+
+TEST(subsession_add_user_wait_test, APIAddUserWaitTest) {
+
+       GMainLoop* loop = NULL;
+       loop = g_main_loop_new (NULL, FALSE);
+
+       g_atomic_int_set(&callback_adduser_reference, 0);
+       g_atomic_int_set(&callback_adduserstarted_reference, 0);
+       g_atomic_int_set(&callback_removeuser_reference, 0);
+
+       test_user_data test_add_wait_1_2;
+       test_add_wait_1_2.session_id = 1;
+       test_add_wait_1_2.user_id = -3;
+       test_add_wait_1_2.callback_result = -1;
+       int add_user_wait_res_1_2 = subsession_add_user_wait_callback(test_add_wait_1_2.session_id,
+                test_add_user_wait_callback, (void *)&test_add_wait_1_2);
+
+       test_user_data test_add_1_2;
+       test_add_1_2.session_id = 1;
+       test_add_1_2.user_id = 2;
+       test_add_1_2.callback_result = -1;
+       int add_user_res_1_2 = subsession_add_user(test_add_1_2.session_id, test_add_1_2.user_id,
+                test_reply_adduser_callback, (void *)&test_add_1_2);
+
+       test_user_data test_remove_1_2;
+       test_remove_1_2.session_id = 1;
+       test_remove_1_2.user_id = 2;
+       test_remove_1_2.callback_result = -1;
+       int remove_user_res_1_2 = subsession_remove_user(test_remove_1_2.session_id, test_remove_1_2.user_id,
+               test_reply_removeuser_callback, (void *)&test_remove_1_2);
+
+       ud_ctrl ud;
+       ud.loop = loop;
+
+       g_idle_add(callback_pending,(gpointer*)&ud);
+       g_main_loop_run(loop);
+
+       EXPECT_EQ(add_user_wait_res_1_2, 0);
+       EXPECT_EQ(add_user_res_1_2, 0);
+       EXPECT_EQ(remove_user_res_1_2, 0);
+
+
+       EXPECT_EQ(0, test_add_wait_1_2.callback_result);
+       EXPECT_EQ(2, test_add_wait_1_2.user_id);
+
+       EXPECT_EQ(0, test_add_1_2.callback_result);
+       EXPECT_EQ(0, test_remove_1_2.callback_result);
+
+}
diff --git a/libsessiond/target_test/test_api_removeuser.cpp b/libsessiond/target_test/test_api_removeuser.cpp
new file mode 100644 (file)
index 0000000..b67d2f5
--- /dev/null
@@ -0,0 +1,76 @@
+#include<iostream>
+#include <gtest/gtest.h>
+#include <gio/gio.h>
+#include <pthread.h>
+#include "sessiond.h"
+
+// Test
+
+typedef struct {
+       int callback_result;
+} test_user_data;
+
+typedef struct {
+               GMainLoop * loop;
+               test_user_data *user_data;
+}ud_ctrl;
+
+
+int callback_pending_reference;
+
+gboolean callback_pending(gpointer data) {
+
+       ud_ctrl *ud = (ud_ctrl*)data;
+       gboolean is_pending = g_main_context_pending(NULL);
+       gint ctrl_value = g_atomic_int_get(&callback_pending_reference);
+
+       if(is_pending == TRUE) {
+               return TRUE;
+       }
+
+       if(ctrl_value >= 0) {
+               g_main_loop_quit((GMainLoop*)ud->loop);
+       }
+  return TRUE;
+}
+
+int test_reply_callback (int result, void *cb_data) {
+
+       g_atomic_int_inc(&callback_pending_reference);
+
+       test_user_data *user_data = (test_user_data *)cb_data;
+       user_data->callback_result = result;
+
+       if (result < 0) {
+               return result;
+       }
+
+       if (cb_data == NULL) {
+               return -EBADR;
+       }
+
+       return 0;
+}
+
+TEST(subsession_remove_user_test, APIRemoveUserTest) {
+
+       GMainLoop* loop = NULL;
+       loop = g_main_loop_new (NULL, FALSE);
+       g_atomic_int_set(&callback_pending_reference, 0);
+
+       test_user_data test_ud;
+       test_ud.callback_result = -1;
+
+       int add_user_res = subsession_remove_user(1, 2, test_reply_callback, (void *)&test_ud);
+
+       ud_ctrl ud;
+       ud.loop = loop;
+       ud.user_data = &test_ud;
+
+       g_idle_add(callback_pending,(gpointer*)&ud);
+       g_main_loop_run(loop);
+
+       EXPECT_EQ(add_user_res, 0);
+       EXPECT_EQ(0, test_ud.callback_result);
+
+}
diff --git a/libsessiond/target_test/test_api_switchuser.cpp b/libsessiond/target_test/test_api_switchuser.cpp
new file mode 100644 (file)
index 0000000..5f5d058
--- /dev/null
@@ -0,0 +1,171 @@
+#include<iostream>
+#include <gtest/gtest.h>
+#include <gio/gio.h>
+#include <pthread.h>
+#include "sessiond.h"
+
+// Test
+
+typedef struct {
+       int callback_result;
+       int session_id;
+       int user_id;
+} test_user_data;
+
+
+typedef struct {
+       int callback_result;
+       int session_id;
+       int prev_user_id;
+       int next_user_id;
+} test_user_data_switch;
+
+typedef struct {
+               GMainLoop * loop;
+               test_user_data *user_data;
+}ud_ctrl;
+
+
+int callback_adduser_reference;
+int callback_removeuser_reference;
+int callback_switchuser_reference;
+
+gboolean callback_pending(gpointer data) {
+
+       ud_ctrl *ud = (ud_ctrl*)data;
+       gboolean is_pending = g_main_context_pending(NULL);
+       gint callback_adduser_calls = g_atomic_int_get(&callback_adduser_reference);
+       gint callback_removeuser_calls = g_atomic_int_get(&callback_removeuser_reference);
+       gint callback_switchuser_calls = g_atomic_int_get(&callback_switchuser_reference);
+
+
+       if(is_pending == TRUE) {
+               return TRUE;
+       }
+
+       bool loop_quit_ready =
+                       (callback_adduser_calls >= 2) &&
+                       (callback_removeuser_calls >= 2) &&
+                       (callback_switchuser_calls >= 1) ;
+
+       if(loop_quit_ready) {
+               g_main_loop_quit((GMainLoop*)ud->loop);
+       }
+  return TRUE;
+}
+
+int test_reply_adduser_callback (int result, void *cb_data) {
+
+       g_atomic_int_inc(&callback_adduser_reference);
+
+       test_user_data *user_data = (test_user_data *)cb_data;
+       user_data->callback_result = result;
+
+       if (result < 0) {
+               return result;
+       }
+
+       if (cb_data == NULL) {
+               return -EBADR;
+       }
+
+       return 0;
+}
+
+int test_reply_switchuser_callback (int result, void *cb_data) {
+
+       g_atomic_int_inc(&callback_switchuser_reference);
+
+       test_user_data_switch *user_data = (test_user_data_switch *)cb_data;
+       user_data->callback_result = result;
+
+       if (result < 0) {
+               return result;
+       }
+
+       if (cb_data == NULL) {
+               return -EBADR;
+       }
+
+       return 0;
+}
+
+int test_reply_removeuser_callback (int result, void *cb_data) {
+
+       g_atomic_int_inc(&callback_removeuser_reference);
+
+       test_user_data *user_data = (test_user_data *)cb_data;
+       user_data->callback_result = result;
+
+       if (result < 0) {
+               return result;
+       }
+
+       if (cb_data == NULL) {
+               return -EBADR;
+       }
+
+       return 0;
+}
+
+TEST(subsession_switch_user_test, APISwitchUserTest) {
+
+       GMainLoop* loop = NULL;
+       loop = g_main_loop_new (NULL, FALSE);
+       g_atomic_int_set(&callback_adduser_reference, 0);
+       g_atomic_int_set(&callback_switchuser_reference, 0);
+       g_atomic_int_set(&callback_removeuser_reference, 0);
+
+       test_user_data test_add_1_1;
+       test_add_1_1.session_id = 1;
+       test_add_1_1.user_id = 1;
+       test_add_1_1.callback_result = -1;
+       int add_user_res_1_1 = subsession_add_user(test_add_1_1.session_id, test_add_1_1.user_id, test_reply_adduser_callback, (void *)&test_add_1_1);
+
+       test_user_data test_add_1_2;
+       test_add_1_2.session_id = 1;
+       test_add_1_2.user_id = 2;
+       test_add_1_2.callback_result = -1;
+       int add_user_res_1_2 = subsession_add_user(test_add_1_2.session_id, test_add_1_2.user_id, test_reply_adduser_callback, (void *)&test_add_1_2);
+
+       test_user_data_switch test_switch_1_1_to_2;
+       test_switch_1_1_to_2.session_id = 1;
+       test_switch_1_1_to_2.prev_user_id = 1;
+       test_switch_1_1_to_2.next_user_id = 2;
+       test_switch_1_1_to_2.callback_result = -1;
+
+       int switch_user_res_1_1_to_2 = subsession_switch_user(test_switch_1_1_to_2.session_id,
+               test_switch_1_1_to_2.prev_user_id,
+               test_switch_1_1_to_2.next_user_id,
+               test_reply_switchuser_callback, (void *)&test_switch_1_1_to_2);
+
+       test_user_data test_remove_1_1;
+       test_remove_1_1.session_id = 1;
+       test_remove_1_1.user_id = 1;
+       test_remove_1_1.callback_result = -1;
+       int remove_user_res_1_1 = subsession_remove_user(test_remove_1_1.session_id, test_remove_1_1.user_id, test_reply_removeuser_callback, (void *)&test_remove_1_1);
+
+       test_user_data test_remove_1_2;
+       test_remove_1_2.session_id = 1;
+       test_remove_1_2.user_id = 2;
+       test_remove_1_2.callback_result = -1;
+       int remove_user_res_1_2 = subsession_remove_user(test_remove_1_2.session_id, test_remove_1_2.user_id, test_reply_removeuser_callback, (void *)&test_remove_1_2);
+
+       ud_ctrl ud;
+       ud.loop = loop;
+
+       g_idle_add(callback_pending,(gpointer*)&ud);
+       g_main_loop_run(loop);
+
+       EXPECT_EQ(add_user_res_1_1, 0);
+       EXPECT_EQ(add_user_res_1_2, 0);
+       EXPECT_EQ(switch_user_res_1_1_to_2, 0);
+       EXPECT_EQ(remove_user_res_1_1, 0);
+       EXPECT_EQ(remove_user_res_1_2, 0);
+
+       EXPECT_EQ(0, test_add_1_1.callback_result);
+       EXPECT_EQ(0, test_add_1_2.callback_result);
+       EXPECT_EQ(0, test_switch_1_1_to_2.callback_result);
+       EXPECT_EQ(0, test_remove_1_1.callback_result);
+       EXPECT_EQ(0, test_remove_1_2.callback_result);
+}
index 1271a0dba79fc796fda0401b0c3674b558b33a46..c6cb9c7b8d41b3a95319be55113cbb30a9e280d7 100644 (file)
@@ -8,6 +8,6 @@ function(add_libsd_mocked_test name wraps)
        target_link_libraries(test_${name} libsessiond_test gtest_main gtest ${wraps})
        gtest_discover_tests(test_${name})
 
-endfunction(add_libsd_mocked_test)
+       endfunction(add_libsd_mocked_test)
 
 add_libsd_mocked_test(h_lib  "")
index 419ed92e05947969a30d85b089183ad1d43eaf39..6b91562e981a35157a4c8ed49bceea0ede526de7 100644 (file)
@@ -30,6 +30,13 @@ Group:      Development/Libraries
 Requires:   libsessiond = %{version}-%{release}
 
 %description -n libsessiond-devel
+
+%package -n libsessiond-tests
+Summary:    TODO
+Group:      Development/Libraries
+Requires:   libsessiond = %{version}-%{release}
+
+%description -n libsessiond-tests
 TODO
 
 %prep
@@ -82,3 +89,9 @@ popd
 %{_libdir}/libsessiond.so
 %{_libdir}/pkgconfig/libsessiond.pc
 %{_includedir}/sessiond.h
+
+
+%files -n libsessiond-tests
+%manifest sessiond.manifest
+%license LICENSE.MIT
+%{_bindir}/test_*