Event's callback registration 34/274734/5
authorArkadiusz Nowak <a.nowak3@samsung.com>
Tue, 26 Apr 2022 08:15:10 +0000 (10:15 +0200)
committerArkadiusz Nowak <a.nowak3@samsung.com>
Wed, 11 May 2022 05:53:21 +0000 (07:53 +0200)
Register callback for method - signal:
AddUserWait - AddUserStarted,
RemoveUserWait - RemoveUserStarted,
SwitchUserWait - SwitchUserStarted,
registered by API function:
subsession_register_event_callback
with tests.

API function subsession_switch_wait_done
(called by callback)

More descriptive error codes
Removed deprecated functions

Change-Id: I307fe0fc624292a9c3408169e6653e2eed07544b

libsessiond/include/sessiond.h
libsessiond/src/lib.c
libsessiond/target_test/CMakeLists.txt
libsessiond/target_test/test_api_adduserwait.cpp
libsessiond/target_test/test_api_removeuserwait.cpp [new file with mode: 0644]
libsessiond/target_test/test_api_switch_user_wait.cpp [new file with mode: 0644]
libsessiond/target_test/test_hlp.hpp [new file with mode: 0644]

index 9a08b31..a135a12 100644 (file)
@@ -80,11 +80,8 @@ int subsession_remove_user(int session_uid, int user, subsession_reply_callback
 int subsession_switch_user(int session_uid, int prev_user, int next_user, subsession_reply_callback cb, void *cb_data);
 
 int subsession_add_user_wait_done(int session_uid, int user);
-
 int subsession_remove_user_wait_done(int session_uid, int user);
 
-typedef int (*subsession_switch_wait_callback) (int session_uid, uint64_t switch_id, int prev_user, int next_user, void *cb_data);
-int subsession_switch_wait(int session_uid, subsession_switch_wait_callback cb, void *cb_data);
 int subsession_switch_wait_done(int session_uid, uint64_t switch_id);
 
 int subsession_get_user_list(int session_uid, int **user_list, int *user_count);
index 6cbf900..39a1dc3 100644 (file)
@@ -55,6 +55,7 @@ static struct {
        gchar * RemoveUserWait;
        gchar * RemoveUserDone;
        gchar * GetUserList;
+       gchar * SwitchUserDone;
 
 } dbus_method_call = {
        .AddUser = "AddUser",
@@ -64,7 +65,8 @@ static struct {
        .AddUserDone = "AddUserDone",
        .RemoveUserWait = "RemoveUserWait",
        .RemoveUserDone = "RemoveUserDone",
-       .GetUserList = "GetUserList"
+       .GetUserList = "GetUserList",
+       .SwitchUserDone = "SwitchUserDone"
 };
 
 static struct {
@@ -106,8 +108,6 @@ typedef struct {
        guint dbus_signal_subscribed;
 } client_callbacks_data_t;
 
-
-
 client_callbacks_data_t add_user_callbacks_data_mt = {
        .list = NULL,
 };
@@ -176,9 +176,12 @@ signal_client_data_t *make_new_signal_callback_client_data(void *client_callback
        return NULL;
 }
 
+#define COMPARATOR_RESULT_SAME_ 0
+#define COMPARATOR_RESULT_DIFFERENT_ -1
+
 //use when function return err value
 #define maybe_g_variant_get_int_(var, c_str_, args...) \
-       if (!g_variant_is_of_type(var, G_VARIANT_TYPE(c_str_) )) { return -1; } \
+       if (!g_variant_is_of_type(var, G_VARIANT_TYPE(c_str_) )) { return COMPARATOR_RESULT_DIFFERENT_ ; } \
        g_variant_get(var, c_str_, args)
 
 //use if function return void type
@@ -186,6 +189,7 @@ signal_client_data_t *make_new_signal_callback_client_data(void *client_callback
        if (!g_variant_is_of_type(var, G_VARIANT_TYPE(c_str_) )) { return; } \
        g_variant_get(var, c_str_, args)
 
+
 gint g_compare_user_params (  gconstpointer client_data,   gconstpointer parameters) {
 
        signal_client_data_t *signal_client_data = (signal_client_data_t*)client_data;
@@ -202,11 +206,10 @@ gint g_compare_user_params (  gconstpointer client_data,   gconstpointer paramet
        maybe_g_variant_get_int_(params, "(ii)", &params_session_uid, &params_user);
 
        if( client_session_uid == params_session_uid &&
-               client_user == params_user) {
-
-                       return 0;
-               }
-       return -1;
+       client_user == params_user) {
+               return COMPARATOR_RESULT_SAME_;
+       }
+       return COMPARATOR_RESULT_DIFFERENT_;
 }
 
 gint g_compare_session_uid_params (  gconstpointer client_data,   gconstpointer parameters) {
@@ -223,13 +226,59 @@ gint g_compare_session_uid_params (  gconstpointer client_data,   gconstpointer
        maybe_g_variant_get_int_(params, "(i)", &params_session_uid);
 
        if( client_session_uid == params_session_uid) {
+               return COMPARATOR_RESULT_SAME_;
+       }
+       return COMPARATOR_RESULT_DIFFERENT_;
+}
 
-                       return 0;
-               }
-       return -1;
+gint g_compare_session_uid_params_switch_wait (  gconstpointer client_data,   gconstpointer parameters) {
+
+       signal_client_data_t *signal_client_data = (signal_client_data_t*)client_data;
+
+       int client_session_uid = 0;
+       maybe_g_variant_get_int_(signal_client_data->params, "(i)", &client_session_uid);
+
+       GVariant *params = (GVariant *)parameters;
+
+       int params_session_uid = 0;
+       uint64_t params_switch_id = 0;
+       int params_prev_user = 0;
+       int params_next_user = 0;
+
+       maybe_g_variant_get_int_(params, "(ixii)",
+               &params_session_uid,
+               &params_switch_id,
+               &params_prev_user,
+               &params_next_user
+       );
+
+       if( client_session_uid == params_session_uid) {
+               return COMPARATOR_RESULT_SAME_;
+       }
+       return COMPARATOR_RESULT_DIFFERENT_;
 }
 
-signal_client_data_t *find_in_callbacks_data( client_callbacks_data_t *client_callbacks_data, gconstpointer parameters, GCompareFunc compare_user_params) {
+gint g_compare_session_uid_params_wait (gconstpointer client_data, gconstpointer parameters) {
+
+       signal_client_data_t *signal_client_data = (signal_client_data_t*)client_data;
+
+       int client_session_uid = 0;
+       maybe_g_variant_get_int_(signal_client_data->params, "(i)", &client_session_uid);
+
+       GVariant *params = (GVariant *)parameters;
+
+       int params_session_uid = 0;
+       int user_id = 0;
+
+       maybe_g_variant_get_int_(params, "(ii)", &params_session_uid, &user_id);
+
+       if( client_session_uid == params_session_uid) {
+               return COMPARATOR_RESULT_SAME_;
+       }
+       return COMPARATOR_RESULT_DIFFERENT_;
+}
+
+signal_client_data_t *take_from_callbacks_data_and_remove_from_list( client_callbacks_data_t *client_callbacks_data, gconstpointer parameters, GCompareFunc compare_user_params) {
 
        signal_client_data_t *signal_data = NULL;
 
@@ -238,13 +287,25 @@ signal_client_data_t *find_in_callbacks_data( client_callbacks_data_t *client_ca
                if (found_data != NULL) {
                        signal_data = (signal_client_data_t*)found_data->data;
                        client_callbacks_data->list = g_list_remove(client_callbacks_data->list, found_data->data);
-                       g_list_free (g_steal_pointer (&found_data));
                }
        g_mutex_unlock(&client_callbacks_data->mutex);
 
        return signal_data;
 }
 
+signal_client_data_t *find_in_callbacks_data( client_callbacks_data_t *client_callbacks_data, gconstpointer parameters, GCompareFunc compare_user_params) {
+
+       signal_client_data_t *signal_data = NULL;
+
+       g_mutex_lock(&client_callbacks_data->mutex);
+               GList *found_data = g_list_find_custom( client_callbacks_data->list, (gconstpointer) parameters, compare_user_params );
+               if (found_data != NULL) {
+                       signal_data = (signal_client_data_t*)found_data->data;
+               }
+       g_mutex_unlock(&client_callbacks_data->mutex);
+       return signal_data;
+}
+
 const int cb_result_ok = 0;
 
 void call_reply_callback(signal_client_data_t *signal_data, int ret_status) {
@@ -263,18 +324,19 @@ static void signal_user_ops_complete_handler(
        GVariant *parameters,
        gpointer client_data) {
 
-       if(client_data == NULL) {
+       if(client_data == NULL || parameters == NULL ) {
                return ;
        }
 
        client_callbacks_data_t *client_callbacks_data = (client_callbacks_data_t *)client_data;
 
-       signal_client_data_t *signal_data = find_in_callbacks_data(client_callbacks_data, parameters, g_compare_user_params);
-
-       if(signal_data == NULL) {
+       if(client_callbacks_data == NULL)  {
                return;
        }
-       if(signal_data->client_callback == NULL) {
+
+       signal_client_data_t *signal_data = take_from_callbacks_data_and_remove_from_list(client_callbacks_data, parameters, g_compare_user_params);
+
+       if(signal_data == NULL || signal_data->client_callback == NULL) {
                return ;
        }
 
@@ -282,9 +344,9 @@ static void signal_user_ops_complete_handler(
 
        g_variant_unref(signal_data->params);
        free(signal_data);
-       return;
 }
 
+
 #define signal_add_user_complete_handler signal_user_ops_complete_handler
 #define signal_remove_user_complete_handler signal_user_ops_complete_handler
 
@@ -311,10 +373,9 @@ gint g_compare_switch_user_params (  gconstpointer client_data,   gconstpointer
                                         (client_next_user == params_next_user);
 
        if( all_ok) {
-                       return 0;
+               return COMPARATOR_RESULT_SAME_;
        }
-
-       return -1;
+       return COMPARATOR_RESULT_DIFFERENT_;
 }
 
 static void signal_switch_user_complete_handler(
@@ -326,18 +387,19 @@ static void signal_switch_user_complete_handler(
        GVariant *parameters,
        gpointer client_data) {
 
+       if(parameters == NULL) {
+               return;
+       }
+
        client_callbacks_data_t *client_callbacks_data = &switch_user_callbacks_data_mt;
 
        if(client_callbacks_data->list == NULL) {
                return;
        }
 
-       signal_client_data_t *signal_data = find_in_callbacks_data(client_callbacks_data, parameters, g_compare_switch_user_params);
+       signal_client_data_t *signal_data = take_from_callbacks_data_and_remove_from_list(client_callbacks_data, parameters, g_compare_switch_user_params);
 
-       if(signal_data == NULL) {
-               return;
-       }
-       if(signal_data->client_callback == NULL) {
+       if(signal_data == NULL || signal_data->client_callback == NULL) {
                return ;
        }
 
@@ -357,18 +419,19 @@ static void signal_add_user_started_handler(GDBusConnection *connection,
        GVariant *parameters,
        gpointer client_data)
 {
-       if (parameters == NULL) {
+       if (parameters == NULL || client_data == NULL) {
                return;
        }
-       client_callbacks_data_t *client_callbacks_data = &switch_user_callbacks_data_mt;
+
+       client_callbacks_data_t *client_callbacks_data = (client_callbacks_data_t *)client_data;
 
        if(client_callbacks_data->list == NULL) {
                return;
        }
 
-       signal_client_data_t *signal_data = find_in_callbacks_data(client_callbacks_data, parameters, g_compare_session_uid_params);
+       signal_client_data_t *signal_data = find_in_callbacks_data(client_callbacks_data, parameters, g_compare_session_uid_params_wait);
 
-       if(signal_data == NULL || signal_data->client_callback == NULL) {
+       if(signal_data == NULL || signal_data->client_callback == NULL || signal_data->client_callback_data == NULL ) {
                return ;
        }
 
@@ -389,18 +452,23 @@ static void signal_remove_user_started_handler(GDBusConnection *connection,
        GVariant *parameters,
        gpointer client_data)
 {
-       if(parameters == NULL) {
+       if(parameters == NULL || client_data == NULL) {
                return;
        }
-       client_callbacks_data_t *client_callbacks_data = &switch_user_callbacks_data_mt;
+
+       client_callbacks_data_t *client_callbacks_data = (client_callbacks_data_t *)client_data;
 
        if(client_callbacks_data->list == NULL) {
                return;
        }
 
-       signal_client_data_t *signal_data = find_in_callbacks_data(client_callbacks_data, parameters, g_compare_session_uid_params);
+       signal_client_data_t *signal_data = find_in_callbacks_data(client_callbacks_data, parameters, g_compare_session_uid_params_wait);
 
-       if(signal_data == NULL || signal_data->client_callback == NULL) {
+       if(signal_data == NULL || signal_data->client_callback == NULL || signal_data->client_callback_data == NULL ) {
+               return ;
+       }
+
+       if(signal_data->client_callback_data == NULL) {
                return ;
        }
 
@@ -411,7 +479,6 @@ static void signal_remove_user_started_handler(GDBusConnection *connection,
 
        subsession_event_callback event_callback = signal_data->client_callback;
        event_callback(event_info, signal_data->client_callback_data);
-       return;
 }
 
 static void signal_switch_user_started_handler(GDBusConnection *connection,
@@ -422,23 +489,19 @@ static void signal_switch_user_started_handler(GDBusConnection *connection,
        GVariant *parameters,
        gpointer client_data)
 {
-       if (parameters == NULL ) {
+       if (parameters == NULL || client_data == NULL) {
                return;
        }
 
-       client_callbacks_data_t *client_callbacks_data = &switch_user_callbacks_data_mt;
-
-       if(client_callbacks_data->list == NULL ) {
-               return;
-       }
+       client_callbacks_data_t *client_callbacks_data = (client_callbacks_data_t *)client_data;
 
-       signal_client_data_t *signal_data = find_in_callbacks_data(client_callbacks_data, parameters, g_compare_session_uid_params);
+       signal_client_data_t *signal_data = find_in_callbacks_data(client_callbacks_data, parameters, g_compare_session_uid_params_switch_wait);
 
-       if(signal_data == NULL || signal_data->client_callback == NULL) {
+       if(signal_data == NULL || signal_data->client_callback == NULL || signal_data->client_callback_data == NULL) {
                return ;
        }
 
-       subsession_event_info event_info = {0};
+               subsession_event_info event_info = {0};
 
        event_info.switch_user.event = SUBSESSION_SWITCH_USER_WAIT;
        maybe_g_variant_get_void_(parameters, "(ixii)",
@@ -469,9 +532,9 @@ static void  signal_switch_user_completion_handler( GDBusConnection *connection,
                return;
        }
 
-       signal_client_data_t *signal_data = find_in_callbacks_data(client_callbacks_data, parameters, g_compare_session_uid_params);
+       signal_client_data_t *signal_data = take_from_callbacks_data_and_remove_from_list(client_callbacks_data, parameters, g_compare_session_uid_params);
 
-       if(signal_data == NULL || signal_data->client_callback == NULL) {
+       if(signal_data == NULL || signal_data->client_callback == NULL || signal_data->client_callback_data == NULL) {
                return ;
        }
 
@@ -513,7 +576,7 @@ int subscribe_and_call_method(gchar *method, GVariant *params, gchar *signal_nam
                session_connection_data.connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
                if(error != NULL) {
                        g_error_free(error);
-                       return -ENOTCONN;
+                       return SUBSESSION_ERROR_NOT_AVAILABLE;
                }
        }
 
@@ -547,7 +610,7 @@ int subscribe_and_call_method(gchar *method, GVariant *params, gchar *signal_nam
        }
        g_variant_unref(retgv);
 
-       return 0;
+       return SUBSESSION_ERROR_NONE;
 }
 
 int method_call_no_signal(gchar *method, GVariant *params) {
@@ -557,14 +620,18 @@ int method_call_no_signal(gchar *method, GVariant *params) {
        if (session_connection_data.connection == NULL) {
                session_connection_data.connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
                if(error != NULL) {
-                       return -ENOTCONN;
+                       g_error_free(error);
+                       return SUBSESSION_ERROR_NOT_AVAILABLE;
                }
        }
+       if(params == NULL) {
+               return  SUBSESSION_ERROR_INVALID_PARAMETER;
+       }
 
        GVariant *retgv = NULL;
        GError *call_sync_error = NULL;
 
-       retgv = g_dbus_connection_call_sync(
+       retgv  = g_dbus_connection_call_sync(
                conn_config_,
                method, params,
                NULL,
@@ -579,8 +646,9 @@ int method_call_no_signal(gchar *method, GVariant *params) {
                g_error_free(call_sync_error);
                return ret;
        }
+
        g_variant_unref(retgv);
-       return 0;
+       return SUBSESSION_ERROR_NONE;
 }
 
 int method_call_no_signal_return(gchar *method, GVariant *params, const GVariantType *out_type, GVariant **out) {
@@ -591,7 +659,7 @@ int method_call_no_signal_return(gchar *method, GVariant *params, const GVariant
        if (session_connection_data.connection == NULL) {
                session_connection_data.connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
                if(error != NULL) {
-                       return -ENOTCONN;
+                       return SUBSESSION_ERROR_NOT_AVAILABLE;
                }
        }
 
@@ -616,13 +684,13 @@ int method_call_no_signal_return(gchar *method, GVariant *params, const GVariant
        }
 
        *out = retgv;
-       return 0;
+       return SUBSESSION_ERROR_NONE;
 }
 
 void client_data_cleansweep_mt( signal_client_data_t *signal_client_data, client_callbacks_data_t *callbacks_data) {
 
        g_mutex_lock(&callbacks_data->mutex);
-               callbacks_data->list =  g_list_remove(callbacks_data->list, (gconstpointer) signal_client_data);
+               callbacks_data->list = g_list_remove(callbacks_data->list, (gconstpointer) signal_client_data);
        g_mutex_unlock(&callbacks_data->mutex);
 
        g_variant_unref(signal_client_data->params);
@@ -690,7 +758,7 @@ EXPORT_API int subsession_remove_user(int session_uid, int user, subsession_repl
                (gpointer) &remove_user_callbacks_data_mt);
 
        if (method_call_result == 0) {
-               return 0;
+               return SUBSESSION_ERROR_NONE;
        }
 
        cb(method_call_result, cb_data);
@@ -720,7 +788,9 @@ EXPORT_API int subsession_switch_user(int session_uid, int prev_user, int next_u
                signal_switch_user_complete_handler,
                NULL);
 
-       if (method_call_result == 0) { return 0; }
+       if (method_call_result == 0) {
+               return SUBSESSION_ERROR_NONE;
+       }
 
        cb(method_call_result, cb_data);
        client_data_cleansweep_mt(signal_client_data, &switch_user_callbacks_data_mt);
@@ -766,7 +836,7 @@ registered_signal_t subsession_register_event_in_list(client_callbacks_data_t *c
        return registered_signal;
 }
 
-#define default_wait_params_  g_variant_new("i", -1), params
+#define default_wait_params_  g_variant_new("(i)", -1), params
 
 #define dbus_data_(callbacks_data_mt, params) \
        callbacks_data_mt.dbus_method_call, \
@@ -774,6 +844,11 @@ registered_signal_t subsession_register_event_in_list(client_callbacks_data_t *c
        callbacks_data_mt.dbus_signal, \
        &callbacks_data_mt.dbus_signal_subscribed
 
+#define dbus_data_ptr(callbacks_data_mt, params) \
+       callbacks_data_mt->dbus_method_call, \
+       params, \
+       callbacks_data_mt->dbus_signal, \
+       &callbacks_data_mt->dbus_signal_subscribed
 
 int register_event_callback(client_callbacks_data_t *callbacks_data, GDBusSignalCallback signal_callback, int session_uid, subsession_event_callback cb, void * cb_data) {
 
@@ -782,15 +857,17 @@ int register_event_callback(client_callbacks_data_t *callbacks_data, GDBusSignal
        registered_signal_t registered_signal = subsession_register_event_in_list(callbacks_data, default_wait_params_, cb_data_ );
 
        if(registered_signal.is_registered) {
-               return 0;
+               return SUBSESSION_ERROR_NONE;
        }
 
        int method_call_result = subscribe_and_call_method(
-                               dbus_data_(add_user_wait_callbacks_data_mt, params),
+                               dbus_data_ptr(callbacks_data, params),
                                signal_callback,
-                               (gpointer) &add_user_wait_callbacks_data_mt);
+                               (gpointer) callbacks_data);
 
-       if (method_call_result == 0) { return 0;}
+       if (method_call_result == 0) {
+           return SUBSESSION_ERROR_NONE;
+       }
 
        client_data_cleansweep_mt(registered_signal.signal_client_data, callbacks_data);
 
@@ -804,7 +881,7 @@ int subscribe_only_callback(client_callbacks_data_t *callbacks_data, GDBusSignal
        registered_signal_t registered_signal = subsession_register_event_in_list(callbacks_data, default_wait_params_, cb_data_ );
 
        if(registered_signal.is_registered) {
-               return 0;
+               return SUBSESSION_ERROR_NONE;
        }
 
        GError *error = NULL;
@@ -814,7 +891,7 @@ int subscribe_only_callback(client_callbacks_data_t *callbacks_data, GDBusSignal
                if(error != NULL) {
                        g_error_free(error);
                        client_data_cleansweep_mt(registered_signal.signal_client_data, callbacks_data);
-                       return -ENOTCONN;
+                       return SUBSESSION_ERROR_NOT_AVAILABLE;
                }
        }
 
@@ -827,7 +904,7 @@ int subscribe_only_callback(client_callbacks_data_t *callbacks_data, GDBusSignal
                        callbacks_data,
                        signal_unsubscribed_callback);
        }
-       return 0;
+       return SUBSESSION_ERROR_NONE;
 }
 
 #define ret_if_err_(func_) \
@@ -854,20 +931,19 @@ EXPORT_API int subsession_register_event_callback(int session_uid, subsession_ev
 EXPORT_API int subsession_add_user_wait_done(int session_uid, int user) {
 
        GVariant * params = g_variant_new("(ii)", session_uid, user);
-
        return method_call_no_signal(dbus_method_call.AddUserDone, params);
 }
 
 EXPORT_API int subsession_remove_user_wait_done(int session_uid, int user) {
 
        GVariant * params = g_variant_new("(ii)", session_uid, user);
-
        return method_call_no_signal(dbus_method_call.RemoveUserDone, params);
 }
 
 EXPORT_API int subsession_switch_wait_done(int session_uid, uint64_t switch_id) {
 
-       return TIZEN_ERROR_ACCOUNT;
+       GVariant * params = g_variant_new("(ix)", session_uid, (gint64)switch_id);
+       return method_call_no_signal(dbus_method_call.SwitchUserDone, params);
 }
 
 EXPORT_API int subsession_get_user_list(int session_uid, int **user_list, int *user_count) {
@@ -877,7 +953,6 @@ EXPORT_API int subsession_get_user_list(int session_uid, int **user_list, int *u
                                               g_variant_new("(i)", session_uid),
                                               G_VARIANT_TYPE("(ai)"),
                                               &out);
-
        if (ret != 0)
                return ret;
 
index 8898d66..2450d50 100644 (file)
@@ -1,6 +1,7 @@
 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)
@@ -15,6 +16,8 @@ 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_adduserwait  "")
+add_libsd_target_test(api_removeuserwait  "")
+add_libsd_target_test(api_switch_user_wait  "")
 #add_libsd_target_test(api_add_remove_user_wait  "")
 add_libsd_target_test(api_get_user_list  "")
index b5f57b2..8734757 100644 (file)
@@ -2,53 +2,34 @@
 #include <gtest/gtest.h>
 #include <gio/gio.h>
 #include <pthread.h>
+
+#include <tuple>
+#include <utility>
+#include <iostream>
 #include "sessiond.h"
 
+#include "test_hlp.hpp"
+
 // Test
 
 typedef struct {
-       int callback_result;
-       int session_id;
+       int session_uid;
        int user_id;
-} test_user_data;
+       int callback_result;
+} test_user_data_t;
 
 typedef struct {
        int user;
-       int session_id;
-} test_user_wait_data;
-
-typedef struct {
-               GMainLoop * loop;
-               test_user_data *user_data;
-}ud_ctrl;
+       int session_uid;
+} test_user_wait_data_t;
 
+template <typename... Args>
+bool all_true(Args... args)
+{
+    return (... && args);
+}
 
 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) {
 
@@ -58,7 +39,7 @@ int test_reply_adduser_callback (int result, void *cb_data) {
                return -EBADR;
        }
 
-       test_user_data *user_data = (test_user_data *)cb_data;
+       test_user_data_t *user_data = (test_user_data_t *)cb_data;
        user_data->callback_result = result;
 
        if (result < 0) {
@@ -68,6 +49,8 @@ int test_reply_adduser_callback (int result, void *cb_data) {
        return 0;
 }
 
+int callback_removeuser_reference;
+
 int test_reply_removeuser_callback (int result, void *cb_data) {
 
        g_atomic_int_inc(&callback_removeuser_reference);
@@ -76,93 +59,85 @@ int test_reply_removeuser_callback (int result, void *cb_data) {
                return -EBADR;
        }
 
-       test_user_data *user_data = (test_user_data *)cb_data;
+       test_user_data_t *user_data = (test_user_data_t *)cb_data;
        user_data->callback_result = result;
 
-       if (result < 0) {
-               return result;
-       }
-
-       return 0;
+       return result;
 }
-typedef  int (*subsession_add_user_wait_callback) (int session_uid, int user, void *cb_data);
 
-int test_subsession_add_user_wait_callback(int session_uid, int user, void *cb_data) {
+//typedef int (*subsession_event_callback) (subsession_event_info info, void *cb_data);
+int callback_adduserstarted_reference;
 
-       g_atomic_int_inc(&callback_adduserstarted_reference);
+int test_subsession_add_user_wait_callback(subsession_event_info info, void *cb_data) {
 
-       test_user_data *user_data = (test_user_data *)cb_data;
 
-       int result = 0;
+       test_user_data_t *user_data = (test_user_data_t *)cb_data;
 
-       if(session_uid < 0) {
-               user_data->callback_result = session_uid;
-               result = session_uid;
-               return result;
-       }
+       if(cb_data == NULL) return -1;
 
-       if(user < 0) {
-               user_data->callback_result = user;
-               result = user;
-               return result;
-       }
+       user_data->user_id = info.add_user.user;
+       user_data->session_uid = info.add_user.session_uid;
 
-       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);
+       user_data->callback_result = subsession_add_user_wait_done(test_subsession_uid, 2);
+       g_atomic_int_inc(&callback_adduserstarted_reference);
 
-       return result;
+       return 0;
 }
 
+using ud_ = struct ud_ctrl_t<int*, int*, int*>;
+
 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 = 5001;
-       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(test_add_wait_1_2.session_id,
-                test_subsession_add_user_wait_callback, (void *)&test_add_wait_1_2);
-
-       test_user_data test_add_1_2;
-       test_add_1_2.session_id = 5001;
-       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,
+       ud_ ud = { .loop =  g_main_loop_new (NULL, FALSE),
+               .t = {
+                       &callback_adduser_reference,
+                       &callback_removeuser_reference,
+                       &callback_adduserstarted_reference,
+               }
+       };
+
+       std::apply([](auto... args){( (_set_0(args) ), ...); },  ud.t );
+
+       test_user_data_t test_add_wait_1_2  = {
+                                       .session_uid = -1,
+                                       .user_id = -3,
+                                       .callback_result = -1
+       };
+
+       //int subsession_register_event_callback(int session_uid, subsession_event_type_e event_bits, subsession_event_callback cb, void *cb_data);
+
+       int add_user_wait_res_1_2 = subsession_register_event_callback(test_subsession_uid, SUBSESSION_ADD_USER_WAIT ,test_subsession_add_user_wait_callback, (void*)&test_add_wait_1_2);
+
+       test_user_data_t test_add_1_2 = {
+               .session_uid = test_subsession_uid,
+               .user_id = 2,
+               .callback_result = -1,
+       };
+
+
+       int add_user_res_1_2 = subsession_add_user(test_add_1_2.session_uid, 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 = 5001;
-       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);
+       test_user_data_t test_remove_1_2 = {
+               .session_uid = test_subsession_uid,
+               .user_id = 2,
+               .callback_result = -1,
+       };
 
-       ud_ctrl ud;
-       ud.loop = loop;
+       int remove_user_res_1_2 = subsession_remove_user(test_remove_1_2.session_uid, test_remove_1_2.user_id,
+               test_reply_removeuser_callback, (void *)&test_remove_1_2);
 
-       g_idle_add(callback_pending,(gpointer*)&ud);
-       g_main_loop_run(loop);
+       g_idle_add(callback_pending<ud_>,(gpointer*)&ud);
+       g_main_loop_run(ud.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(test_subsession_uid, test_add_wait_1_2.session_uid);
 
        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_removeuserwait.cpp b/libsessiond/target_test/test_api_removeuserwait.cpp
new file mode 100644 (file)
index 0000000..a0d4b31
--- /dev/null
@@ -0,0 +1,145 @@
+#include<iostream>
+#include <gtest/gtest.h>
+#include <gio/gio.h>
+#include <pthread.h>
+
+#include <tuple>
+#include <utility>
+#include <iostream>
+#include "sessiond.h"
+
+#include "test_hlp.hpp"
+
+// Test
+
+typedef struct {
+       int session_uid;
+       int user_id;
+       int callback_result;
+} test_user_data_t;
+
+typedef struct {
+       int user;
+       int session_uid;
+} test_user_wait_data_t;
+
+template <typename... Args>
+bool all_true(Args... args)
+{
+    return (... && args);
+}
+
+int callback_adduser_reference;
+
+int test_reply_adduser_callback (int result, void *cb_data) {
+
+       g_atomic_int_inc(&callback_adduser_reference);
+
+       if (cb_data == NULL) {
+               return -EBADR;
+       }
+
+       test_user_data_t *user_data = (test_user_data_t *)cb_data;
+       user_data->callback_result = result;
+
+       if (result < 0) {
+               return result;
+       }
+
+       return 0;
+}
+
+int callback_removeuser_reference;
+
+int test_reply_removeuser_callback (int result, void *cb_data) {
+
+       g_atomic_int_inc(&callback_removeuser_reference);
+
+       if (cb_data == NULL) {
+               return -EBADR;
+       }
+
+       test_user_data_t *user_data = (test_user_data_t *)cb_data;
+       user_data->callback_result = result;
+
+       return result;
+}
+
+//typedef int (*subsession_event_callback) (subsession_event_info info, void *cb_data);
+int callback_remove_user_started_reference;
+
+int test_subsession_remove_user_wait_callback(subsession_event_info info, void *cb_data) {
+
+       test_user_data_t *user_data = (test_user_data_t *)cb_data;
+
+       if(cb_data == NULL) return -1;
+
+       user_data->user_id = info.remove_user.user;
+       user_data->session_uid = info.remove_user.session_uid;
+
+       user_data->callback_result = 0;
+
+       user_data->callback_result = subsession_remove_user_wait_done(user_data->session_uid, user_data->user_id);
+       g_atomic_int_inc(&callback_remove_user_started_reference);
+
+       return 0;
+}
+
+using ud_ = struct ud_ctrl_t<int*, int*, int*>;
+
+TEST(subsession_remove_user_wait_test, APIRemoveUserWaitTest) {
+
+       ud_ ud = { .loop =  g_main_loop_new (NULL, FALSE),
+               .t = {
+                       &callback_adduser_reference,
+                       &callback_removeuser_reference,
+                       &callback_remove_user_started_reference,
+               }
+       };
+
+       std::apply([](auto... args){( (_set_0(args) ), ...); },  ud.t );
+
+       test_user_data_t test_remove_wait_1_2  = {
+                                       .session_uid = -1,
+                                       .user_id = -3,
+                                       .callback_result = -1
+       };
+
+       //int subsession_register_event_callback(int session_uid, subsession_event_type_e event_bits, subsession_event_callback cb, void *cb_data);
+
+       int remove_user_wait_res_1_2 = subsession_register_event_callback(test_subsession_uid, SUBSESSION_REMOVE_USER_WAIT
+        ,test_subsession_remove_user_wait_callback, (void*)&test_remove_wait_1_2);
+
+       test_user_data_t test_add_1_2 = {
+               .session_uid = test_subsession_uid,
+               .user_id = 2,
+               .callback_result = -1,
+       };
+
+       int add_user_res_1_2 = subsession_add_user(test_add_1_2.session_uid, test_add_1_2.user_id,
+                test_reply_adduser_callback, (void *)&test_add_1_2);
+
+       test_user_data_t test_remove_1_2 = {
+               .session_uid = test_subsession_uid,
+               .user_id = 2,
+               .callback_result = -1,
+       };
+
+       int remove_user_res_1_2 = subsession_remove_user(test_remove_1_2.session_uid, test_remove_1_2.user_id,
+               test_reply_removeuser_callback, (void *)&test_remove_1_2);
+
+
+       g_idle_add(callback_pending<ud_>,(gpointer*)&ud);
+       g_main_loop_run(ud.loop);
+
+       EXPECT_EQ(remove_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_remove_wait_1_2.callback_result);
+       EXPECT_EQ(2, test_remove_wait_1_2.user_id);
+       EXPECT_EQ(test_subsession_uid, test_remove_wait_1_2.session_uid);
+
+       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_switch_user_wait.cpp b/libsessiond/target_test/test_api_switch_user_wait.cpp
new file mode 100644 (file)
index 0000000..09690cd
--- /dev/null
@@ -0,0 +1,155 @@
+#include<iostream>
+#include <gtest/gtest.h>
+#include <gio/gio.h>
+#include <pthread.h>
+
+#include <tuple>
+#include <utility>
+#include <iostream>
+#include "sessiond.h"
+
+#include "test_hlp.hpp"
+
+template <typename... Args>
+bool all_true(Args... args)
+{
+    return (... && args);
+}
+
+int test_reply_callback (int result, void *cb_data) {
+
+       test_user_data_cb_t *user_data = (test_user_data_cb_t *)cb_data;
+
+       user_data->callback_result = result;
+       g_atomic_int_inc(&user_data->callback_reference);
+
+       return result;
+}
+
+
+
+
+int tud_atomic_int_get(test_user_data_cb_t &arg) {
+       return g_atomic_int_get(&arg.callback_reference);
+}
+
+template<typename T>
+gboolean callback_pending_ud (gpointer data) {
+
+       T *ud = static_cast<T *>(data);
+
+       gboolean is_pending = g_main_context_pending(NULL);
+
+       if(is_pending == TRUE) {
+               return TRUE;
+       }
+
+       auto loop_quit_ready = std::apply([](auto &... args){
+               return ( ( tud_atomic_int_get(args)>=1 ) && ...  );
+       }, ud->t);
+
+       if(loop_quit_ready) {
+               g_main_loop_quit((GMainLoop*)ud->loop);
+       }
+
+       return TRUE;
+}
+
+int test_subsession_switch_user_wait_callback(subsession_event_info info, void *cb_data) {
+
+       test_user_data_cb_t *user_data = (test_user_data_cb_t *)cb_data;
+
+       user_data->session_uid = info.switch_user.session_uid;
+       user_data->switch_id = info.switch_user.switch_id;
+       user_data->user_id = info.switch_user.next_user;
+       user_data->prev_user_id = info.switch_user.prev_user;
+       user_data->callback_result = subsession_switch_wait_done(user_data->session_uid, user_data->switch_id);
+       g_atomic_int_inc(&user_data->callback_reference);
+
+       return 0;
+}
+
+const int user_1 = 1;
+const int user_2 = 2;
+
+enum {
+       add_user_1 = 0,
+       add_user_2,
+       remove_user_1,
+       remove_user_2,
+       switch_user,
+       switch_wait,
+};
+
+using tud_ = test_user_data_cb_t;
+using ud_ = struct ud_ctrl_t<tud_, tud_, tud_, tud_, tud_, tud_>;
+
+template<int N>
+int add_user_wrap(int user_id, subsession_reply_callback cb, ud_ &ud) {
+
+       std::get<N>(ud.t).user_id = user_id;
+       return  subsession_add_user(test_subsession_uid, std::get<N>(ud.t).user_id,
+               cb, (void *)&std::get<N>(ud.t));
+}
+
+template<int N>
+int remove_user_wrap(int user_id, subsession_reply_callback cb, ud_ &ud) {
+
+       std::get<N>(ud.t).user_id = user_id;
+       return  subsession_remove_user(test_subsession_uid, std::get<N>(ud.t).user_id,
+               cb, (void *)&std::get<N>(ud.t));
+}
+
+TEST(subsession_switch_user_wait, APISwitchUserStarted) {
+
+       ud_ ud = { .loop =  g_main_loop_new (NULL, FALSE),
+               .t = std::tuple<tud_, tud_, tud_, tud_, tud_, tud_>(),
+       };
+
+       std::apply([](auto &... args){( (init_user<tud_ &>(args) ), ...); },  ud.t );
+
+       std::get<switch_wait>(ud.t).session_uid = -1;
+       int switch_user_wait_res = subsession_register_event_callback(test_subsession_uid, SUBSESSION_SWITCH_USER_WAIT,
+       test_subsession_switch_user_wait_callback, (void *)&std::get<switch_wait>(ud.t) );
+
+       int add_user_res_1 = add_user_wrap<add_user_1>(user_1, test_reply_callback, ud);
+
+       int add_user_res_2 = add_user_wrap<add_user_2>(user_2, test_reply_callback, ud);
+
+       std::get<switch_user>(ud.t).prev_user_id = user_1;
+       std::get<switch_user>(ud.t).user_id = user_2;
+
+       int switch_user_res = subsession_switch_user(test_subsession_uid, std::get<switch_user>(ud.t).prev_user_id
+               , std::get<switch_user>(ud.t).user_id, test_reply_callback, (void *)&std::get<switch_user>(ud.t));
+
+       int remove_user_res_1 = remove_user_wrap<remove_user_1>(user_1, test_reply_callback, ud);
+
+       int remove_user_res_2 = remove_user_wrap<remove_user_2>(user_2, test_reply_callback, ud);
+
+
+       g_idle_add(callback_pending_ud<ud_>,(gpointer*)&ud);
+       g_main_loop_run(ud.loop);
+
+
+       EXPECT_EQ(switch_user_wait_res, 0);
+       EXPECT_EQ(add_user_res_1, 0);
+       EXPECT_EQ(remove_user_res_1, 0);
+       EXPECT_EQ(switch_user_res, 0);
+       EXPECT_EQ(add_user_res_2, 0);
+       EXPECT_EQ(remove_user_res_2, 0);
+
+       EXPECT_EQ(0, std::get<add_user_1>(ud.t).callback_result);
+       EXPECT_EQ(0, std::get<add_user_2>(ud.t).callback_result);
+       EXPECT_EQ(0, std::get<switch_user>(ud.t).callback_result);
+       EXPECT_EQ(0, std::get<remove_user_1>(ud.t).callback_result);
+       EXPECT_EQ(0, std::get<remove_user_2>(ud.t).callback_result);
+
+       auto &user_data_result = std::get<switch_wait>(ud.t);
+
+       EXPECT_EQ(0, user_data_result.callback_result);
+       EXPECT_EQ(user_data_result.session_uid, test_subsession_uid);
+       EXPECT_EQ(user_data_result.user_id, user_2);
+       EXPECT_EQ(user_data_result.prev_user_id, user_1);
+
+
+}
diff --git a/libsessiond/target_test/test_hlp.hpp b/libsessiond/target_test/test_hlp.hpp
new file mode 100644 (file)
index 0000000..13124cb
--- /dev/null
@@ -0,0 +1,87 @@
+#pragma once
+#include <iostream>
+#include <gio/gio.h>
+#include <pthread.h>
+
+const int test_subsession_uid = 5001;
+
+template<typename... Args>
+struct ud_ctrl_t{
+               GMainLoop * loop;
+               std::tuple<Args...> t;
+};
+
+typedef struct {
+       int session_uid;
+       int user_id;
+       uint64_t switch_id;
+       int callback_result;
+       int callback_reference;
+       int prev_user_id;
+       subsession_event_type_e event;
+} test_user_data_cb_t;
+
+
+int _atomic_int_get(int *value) {
+       return g_atomic_int_get(value);
+}
+
+template<typename T>
+void _set_0(T arg);
+
+template<>
+void _set_0(int* arg) {
+       g_atomic_int_set(arg, 0);
+}
+
+template<typename T>
+void atomic_set_0(T arg) {
+       _set_0(arg);
+       return;
+}
+
+
+template<typename T>
+void init_user(T arg);
+
+template<>
+void init_user(test_user_data_cb_t& arg) {
+       arg.session_uid =  test_subsession_uid;
+       arg.user_id = -1;
+       arg.callback_result = -1;
+       arg.event = SUBSESSION_EVENT_ALL;
+       arg.prev_user_id = -1;
+       arg.switch_id = -1;
+       _set_0(&arg.callback_reference);
+}
+
+
+/*
+template<typename T, typename... V>
+void atomic_set_0(T arg, V... args) {
+       _set_0(arg);
+       atomic_set_0(args...);
+       return;
+}
+*/
+template<typename T>
+gboolean callback_pending(gpointer data) {
+
+       T *ud = static_cast<T *>(data);
+
+       gboolean is_pending = g_main_context_pending(NULL);
+
+       if(is_pending == TRUE) {
+               return TRUE;
+       }
+
+       auto loop_quit_ready = std::apply([](auto... args){
+               return ( ( _atomic_int_get(args)>=1 ) && ...  );
+       }, ud->t);
+
+       if(loop_quit_ready) {
+               g_main_loop_quit((GMainLoop*)ud->loop);
+       }
+
+       return TRUE;
+}