Tests with errors 76/275476/5
authorArkadiusz Nowak <a.nowak3@samsung.com>
Mon, 23 May 2022 08:20:53 +0000 (10:20 +0200)
committerArkadiusz Nowak <a.nowak3@samsung.com>
Thu, 2 Jun 2022 12:59:43 +0000 (14:59 +0200)
Sending incorrect values to sessiond
server and takes back error codes

for:
 subsession_add_user
 subsession_remove_user
 subsession_switch_user

Removed test_api_adduser.cpp.
Removed test_api_removeuser.cpp
Tests from theese files are moved to test_api_addremove_user.cpp

Fixed errors in libsessiond  detected by tests

subsession_add_user,
subsession_remove_user,
subsession_switch_user will not call callback if error

Validation macros partially moved to lib.h
Validation macros are more generic

Change-Id: Ide27b2cfd8ffc6d31813230f3a43bafb6079584c

14 files changed:
libsessiond/src/lib.c
libsessiond/src/lib.h
libsessiond/target_test/CMakeLists.txt
libsessiond/target_test/test_api_add_remove_user.cpp
libsessiond/target_test/test_api_add_remove_user_err.cpp [new file with mode: 0644]
libsessiond/target_test/test_api_adduser.cpp [deleted file]
libsessiond/target_test/test_api_reg_unreg_add_user_wait.cpp
libsessiond/target_test/test_api_removeuser.cpp [deleted file]
libsessiond/target_test/test_api_removeuserwait.cpp
libsessiond/target_test/test_api_switch_user_completion.cpp
libsessiond/target_test/test_api_switch_user_wait.cpp
libsessiond/target_test/test_api_switchuser.cpp
libsessiond/target_test/test_api_switchuser_err.cpp [new file with mode: 0644]
libsessiond/target_test/test_hlp.hpp

index 1cfc4ab..cc34aa2 100644 (file)
@@ -193,19 +193,6 @@ 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 COMPARATOR_RESULT_DIFFERENT_ ; } \
-       g_variant_get(var, c_str_, args)
-
-//use if function return void type
-#define maybe_g_variant_get_void_(var, c_str_, args...) \
-       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) {
 
@@ -215,15 +202,22 @@ gint g_compare_user_params (  gconstpointer client_data,   gconstpointer paramet
        int client_user = 0;
        maybe_g_variant_get_int_(signal_client_data->params, "(ii)", &client_session_uid, &client_user);
 
+       maybe_not_compared_if(
+               not_valid(client_session_uid,
+               not_valid(client_user)))
+
        GVariant *params = (GVariant *)parameters;
 
        int params_session_uid = 0;
        int params_user = 0;
-
        maybe_g_variant_get_int_(params, "(ii)", &params_session_uid, &params_user);
 
+       maybe_not_compared_if(
+               not_valid(params_session_uid,
+               not_valid(params_user)))
+
        if( client_session_uid == params_session_uid &&
-       client_user == params_user) {
+               client_user == params_user) {
                return COMPARATOR_RESULT_SAME_;
        }
        return COMPARATOR_RESULT_DIFFERENT_;
@@ -236,12 +230,18 @@ gint g_compare_session_uid_params (  gconstpointer client_data,   gconstpointer
        int client_session_uid = 0;
        maybe_g_variant_get_int_(signal_client_data->params, "(i)", &client_session_uid);
 
+       maybe_not_compared_if(
+               not_valid(client_session_uid))
+
        GVariant *params = (GVariant *)parameters;
 
        int params_session_uid = 0;
 
        maybe_g_variant_get_int_(params, "(i)", &params_session_uid);
 
+       maybe_not_compared_if(
+               not_valid(params_session_uid))
+
        if( client_session_uid == params_session_uid) {
                return COMPARATOR_RESULT_SAME_;
        }
@@ -255,6 +255,9 @@ gint g_compare_session_uid_params_switch_wait (  gconstpointer client_data,   gc
        int client_session_uid = 0;
        maybe_g_variant_get_int_(signal_client_data->params, "(i)", &client_session_uid);
 
+       maybe_not_compared_if(
+               not_valid(client_session_uid))
+
        GVariant *params = (GVariant *)parameters;
 
        int params_session_uid = 0;
@@ -269,6 +272,12 @@ gint g_compare_session_uid_params_switch_wait (  gconstpointer client_data,   gc
                &params_next_user
        );
 
+       maybe_not_compared_if(
+               not_valid(params_session_uid,
+               not_valid(params_switch_id,
+               not_valid(params_prev_user,
+               not_valid(params_next_user)))))
+
        if( client_session_uid == params_session_uid) {
                return COMPARATOR_RESULT_SAME_;
        }
@@ -282,6 +291,9 @@ gint g_compare_session_uid_params_wait (gconstpointer client_data, gconstpointer
        int client_session_uid = 0;
        maybe_g_variant_get_int_(signal_client_data->params, "(i)", &client_session_uid);
 
+       maybe_not_compared_if(
+               not_valid(client_session_uid))
+
        GVariant *params = (GVariant *)parameters;
 
        int params_session_uid = 0;
@@ -289,6 +301,10 @@ gint g_compare_session_uid_params_wait (gconstpointer client_data, gconstpointer
 
        maybe_g_variant_get_int_(params, "(ii)", &params_session_uid, &user_id);
 
+       maybe_not_compared_if(
+               not_valid(params_session_uid,
+               not_valid(user_id)))
+
        if( client_session_uid == params_session_uid) {
                return COMPARATOR_RESULT_SAME_;
        }
@@ -376,8 +392,13 @@ gint g_compare_switch_user_params (  gconstpointer client_data,   gconstpointer
 
        int client_session_uid = 0;
        int client_next_user = 0;
+
        maybe_g_variant_get_int_(signal_client_data->params, "(ii)", &client_session_uid, &client_next_user);
 
+       maybe_not_compared_if(
+               not_valid(client_session_uid,
+               not_valid(client_next_user)))
+
        GVariant *params = (GVariant *)parameters;
 
        int params_session_uid = 0;
@@ -387,6 +408,12 @@ gint g_compare_switch_user_params (  gconstpointer client_data,   gconstpointer
 
        maybe_g_variant_get_int_(params, "(ixii)", &params_session_uid, &params_switch_id, &params_prev_user, &params_next_user);
 
+       maybe_not_compared_if(
+               not_valid(params_session_uid,
+               not_valid(params_switch_id,
+               not_valid(params_prev_user,
+               not_valid(params_next_user)))))
+
        gboolean all_ok = (client_session_uid == params_session_uid) &&
                                        (client_next_user == params_next_user);
 
@@ -434,8 +461,7 @@ static void signal_add_user_started_handler(GDBusConnection *connection,
        const gchar *interface_name,
        const gchar *signal_name,
        GVariant *parameters,
-       gpointer client_data)
-{
+       gpointer client_data) {
 
        if (parameters == NULL || client_data == NULL) {
                return;
@@ -518,7 +544,6 @@ static void signal_switch_user_started_handler(GDBusConnection *connection,
        if(signal_data == NULL || signal_data->client_callback == NULL || signal_data->client_callback_data == NULL) {
                return ;
        }
-
        subsession_event_info event_info = {0};
 
        event_info.switch_user.event = SUBSESSION_SWITCH_USER_WAIT;
@@ -716,10 +741,18 @@ void init_callbacks_list(client_callbacks_data_t *callbacks_data, GVariant *para
 #define callbacks_data_append_to_list(callback_data, data) \
        callback_data.list = g_list_append(callback_data.list, data)
 
+#define return_invalid_param_if(a) error_if(a, SUBSESSION_ERROR_INVALID_PARAMETER)
 
+#define return_invalid_if_input_params_are_wrong \
+       return_invalid_param_if( \
+       not_valid(session_uid, \
+       not_valid(user, \
+       not_valid(cb, \
+       not_valid(cb_data)))))
 
 EXPORT_API int subsession_add_user(int session_uid, int user, subsession_reply_callback cb, void *cb_data) {
 
+       return_invalid_if_input_params_are_wrong
 
        g_mutex_lock (&add_user_callbacks_data_mt.mutex);
 
@@ -741,7 +774,6 @@ EXPORT_API int subsession_add_user(int session_uid, int user, subsession_reply_c
 
        if (method_call_result == 0) { return SUBSESSION_ERROR_NONE; }
 
-       cb(method_call_result, cb_data);
        client_data_cleansweep_mt(signal_client_data, &add_user_callbacks_data_mt);
 
        return method_call_result;
@@ -749,6 +781,8 @@ EXPORT_API int subsession_add_user(int session_uid, int user, subsession_reply_c
 
 EXPORT_API int subsession_remove_user(int session_uid, int user, subsession_reply_callback cb, void *cb_data) {
 
+       return_invalid_if_input_params_are_wrong
+
        g_mutex_lock (&remove_user_callbacks_data_mt.mutex);
 
        init_callbacks_list(&remove_user_callbacks_data_mt, g_variant_new("(ii)", -1, -1));
@@ -771,7 +805,6 @@ EXPORT_API int subsession_remove_user(int session_uid, int user, subsession_repl
                return SUBSESSION_ERROR_NONE;
        }
 
-       cb(method_call_result, cb_data);
        client_data_cleansweep_mt(signal_client_data, &remove_user_callbacks_data_mt);
 
        return method_call_result;
@@ -779,6 +812,12 @@ EXPORT_API int subsession_remove_user(int session_uid, int user, subsession_repl
 
 EXPORT_API int subsession_switch_user(int session_uid, int next_user, subsession_reply_callback cb, void *cb_data) {
 
+       return_invalid_param_if(
+               not_valid(session_uid,
+               not_valid(next_user,
+               not_valid(cb,
+               not_valid(cb_data)))))
+
        g_mutex_lock (&switch_user_callbacks_data_mt.mutex);
 
        init_callbacks_list(&switch_user_callbacks_data_mt,  g_variant_new("(ii)", -1, -1));
@@ -802,7 +841,6 @@ EXPORT_API int subsession_switch_user(int session_uid, int next_user, subsession
                return SUBSESSION_ERROR_NONE;
        }
 
-       cb(method_call_result, cb_data);
        client_data_cleansweep_mt(signal_client_data, &switch_user_callbacks_data_mt);
 
        return method_call_result;
@@ -815,8 +853,10 @@ typedef struct {
        int is_registered;
 } registered_signal_t;
 
+
 registered_signal_t subsession_register_event_in_list(client_callbacks_data_t *callbacks_data, GVariant *init_params, GVariant *params, subsession_event_callback cb, void *cb_data) {
 
+
        g_mutex_lock(&callbacks_data->mutex);
 
        init_callbacks_list(callbacks_data, init_params);
index 7cc01e3..98f740d 100644 (file)
@@ -26,7 +26,9 @@ extern "C" {
 #endif
 
 #include <gio/gio.h>
-
+#include <stdint.h>
+#include <tizen.h>
+#include "sessiond.h"
 
 typedef struct {
        GDBusConnection *connection;
@@ -35,6 +37,53 @@ typedef struct {
        gchar * interface;
 } session_connection_data_t;
 
+#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 COMPARATOR_RESULT_DIFFERENT_ ; } \
+       g_variant_get(var, c_str_, args)
+
+//use if function return void type
+#define maybe_g_variant_get_void_(var, c_str_, args...) \
+       if (!g_variant_is_of_type(var, G_VARIANT_TYPE(c_str_) )) { return; } \
+       g_variant_get(var, c_str_, args)
+
+#define not_valid_g(X) _Generic((X), \
+       int : not_valid_int, \
+       uint64_t : not_valid_uint64_t, \
+       subsession_reply_callback : not_valid_subsession_reply_callback, \
+       void* : not_valid_void_ptr, \
+       int* : not_valid_int_ptr \
+       )(X)
+
+#define not_valid(a, ...) || (not_valid_g(a)) __VA_ARGS__
+
+#define error_if(a, error) if ( (0) a ) { return error; }
+
+#define maybe_not_compared_if(a) error_if(a, COMPARATOR_RESULT_DIFFERENT_)
+
+int not_valid_int_ptr(int *a) {
+       return a == NULL;
+}
+
+int not_valid_uint64_t(uint64_t a) {
+       return a < 0;
+}
+
+int not_valid_int(int a) {
+       return a < 0;
+}
+
+int not_valid_subsession_reply_callback (subsession_reply_callback cb) {
+       return cb == NULL;
+}
+
+int not_valid_void_ptr(void *data) {
+       return data == NULL;
+}
+
 #ifdef __cplusplus
 }
 #endif
index b872f81..7c15b43 100644 (file)
@@ -12,10 +12,11 @@ function(add_libsd_target_test name 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_add_remove_user_err  "")
 add_libsd_target_test(api_switchuser  "")
+add_libsd_target_test(api_switchuser_err  "")
 add_libsd_target_test(api_adduserwait  "")
 add_libsd_target_test(api_removeuserwait  "")
 add_libsd_target_test(api_switch_user_wait  "")
index 0f3d3f3..324e66e 100644 (file)
@@ -1,8 +1,12 @@
 #include<iostream>
+#include<string>
+#include<algorithm>
+
 #include <gtest/gtest.h>
 #include <gio/gio.h>
 #include <pthread.h>
 #include "sessiond.h"
+#include "test_hlp.hpp"
 
 // Test
 
@@ -18,7 +22,7 @@ typedef struct {
 
 int callback_pending_reference;
 
-gboolean callback_pending(gpointer data) {
+gboolean callback_pending_o(gpointer data) {
 
        ud_ctrl *ud = (ud_ctrl*)data;
        gboolean is_pending = g_main_context_pending(NULL);
@@ -34,7 +38,7 @@ gboolean callback_pending(gpointer data) {
   return TRUE;
 }
 
-int test_reply_adduser_callback (int result, void *cb_data) {
+int test_reply_adduser_callback_o (int result, void *cb_data) {
 
        g_atomic_int_inc(&callback_pending_reference);
 
@@ -52,10 +56,9 @@ int test_reply_adduser_callback (int result, void *cb_data) {
        return 0;
 }
 
-int test_reply_removeuser_callback (int result, void *cb_data) {
+int test_reply_removeuser_callback_o (int result, void *cb_data) {
 
        g_atomic_int_inc(&callback_pending_reference);
-
        if (cb_data == NULL) {
                return -EBADR;
        }
@@ -72,27 +75,32 @@ int test_reply_removeuser_callback (int result, void *cb_data) {
 
 TEST(subsession_add_remove_user_test, APIAddRemoveUserTest) {
 
-       GMainLoop* loop = NULL;
-       loop = g_main_loop_new (NULL, FALSE);
+       ud_ctrl ud_o;
+       ud_o.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(5001, 2, test_reply_adduser_callback, (void *)&test_add_ud);
+       test_user_data test_add_ud_o;
+       test_add_ud_o.callback_result = -1;
+
+       std::cout << head_ << "Add: subsession: ," << test_subsession_uid << "user: " << TestUser::user_2 << std::endl;
+       int add_user_res = subsession_add_user(test_subsession_uid, TestUser::user_2, test_reply_adduser_callback_o, (void *)&test_add_ud_o);
 
-       test_user_data test_remove_ud;
-       test_remove_ud.callback_result = -1;
-       int remove_user_res = subsession_remove_user(5001, 2, test_reply_removeuser_callback, (void *)&test_remove_ud);
+       test_user_data test_remove_ud_o;
+       test_remove_ud_o.callback_result = -1;
+       std::cout << head_ << "Remove: subsession: ," <<  test_subsession_uid << "user: " << TestUser::user_2 << std::endl;
+       int remove_user_res = subsession_remove_user(test_subsession_uid, TestUser::user_2, test_reply_removeuser_callback_o, (void *)&test_remove_ud_o);
 
-       ud_ctrl ud;
-       ud.loop = loop;
+       guint idle_id = g_idle_add(callback_pending_o,(gpointer*)&ud_o);
 
-       g_idle_add(callback_pending,(gpointer*)&ud);
-       g_main_loop_run(loop);
+       g_main_loop_run(ud_o.loop);
+       g_source_remove(idle_id);
+       g_main_loop_unref(ud_o.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);
+       EXPECT_EQ(0, test_add_ud_o.callback_result);
+       EXPECT_EQ(0, test_remove_ud_o.callback_result);
 
+       //EXPECT_EQ(0,1);
 }
diff --git a/libsessiond/target_test/test_api_add_remove_user_err.cpp b/libsessiond/target_test/test_api_add_remove_user_err.cpp
new file mode 100644 (file)
index 0000000..168bb5a
--- /dev/null
@@ -0,0 +1,103 @@
+#include<iostream>
+#include<string>
+#include<algorithm>
+
+#include <gtest/gtest.h>
+#include <gio/gio.h>
+#include <pthread.h>
+#include "sessiond.h"
+#include "test_hlp.hpp"
+
+using tud_ = test_user_data_cb_t;
+using ud_add_user_fail = struct ud_ctrl_t<tud_, tud_, tud_, tud_, tud_>;
+
+struct add_user_fail {
+    enum action {
+               add_user_0 = 0,
+               add_user_minus_1,
+               add_user_1,
+               add_user_1_again,
+               remove_user_1,
+               action_items,
+       };
+};
+
+TEST(subsession_add_remove_test, FailAtAddUser) {
+
+       ud_add_user_fail ud = { .loop = g_main_loop_new(NULL, FALSE),
+               .t = ud_add_user_fail::the_tuple(),
+       };
+
+       std::apply([](auto &... args){( (init_user_s<tud_ &, subsession_5002>(args) ), ...); },  ud.t );
+
+       std::array<res_t, add_user_fail::action_items> results {
+               res_t{ add_user_wrap<ud_add_user_fail, add_user_fail::add_user_0>(TestUser::user_0, test_reply_callback_default, ud),
+                       SUBSESSION_ERROR_INVALID_PARAMETER, "Check if adding user 0 returns error" },
+
+               res_t{ add_user_wrap<ud_add_user_fail, add_user_fail::add_user_minus_1>( -(TestUser::user_1), test_reply_callback_default, ud),
+                       SUBSESSION_ERROR_INVALID_PARAMETER, "Check if adding user -1 returns error" },
+
+               res_t{ add_user_wrap<ud_add_user_fail, add_user_fail::add_user_1>( (TestUser::user_1), test_reply_callback_default, ud),
+                       SUBSESSION_ERROR_NONE, "Check if adding user 1 returns no error" },
+
+               res_t{ add_user_wrap<ud_add_user_fail, add_user_fail::add_user_1_again>( (TestUser::user_1), test_reply_callback_default, ud),
+                       SUBSESSION_ERROR_ALREADY_EXISTS, "Check if adding user 1 again returns error" },
+
+               res_t{ remove_user_wrap<ud_add_user_fail, add_user_fail::remove_user_1>( (TestUser::user_1), test_reply_callback_default, ud),
+                       SUBSESSION_ERROR_NONE, "Check if removing user 1 returns no error" },
+       };
+
+       loop_run_for_test(callback_pending_ud<ud_add_user_fail>,(gpointer*)&ud, ud.loop);
+
+       summarize_results<add_user_fail::action_items>(results);
+}
+
+using ud_remove_user_fail = struct ud_ctrl_t<tud_, tud_, tud_, tud_, tud_, tud_> ;
+
+struct remove_user_fail {
+    enum action {
+               remove_user_0 = 0,
+               remove_user_1,
+               remove_user_minus_1,
+               add_user_1,
+               remove_user_1_existing,
+               remove_user_1_again,
+               action_items,
+       };
+};
+
+TEST(subsession_add_remove_test, FailAtRemoveUser)  {
+
+       ud_remove_user_fail ud = { .loop = g_main_loop_new(NULL, FALSE),
+
+               .t = ud_remove_user_fail::the_tuple(),
+       };
+
+       std::apply([](auto &... args){( (init_user_s<tud_ &, subsession_5003>(args) ), ...); },  ud.t );
+
+       std::array<res_t, remove_user_fail::action_items> results {
+
+               res_t{ remove_user_wrap<ud_remove_user_fail, remove_user_fail::remove_user_0>( (TestUser::user_0), test_reply_callback_default, ud),
+                       SUBSESSION_ERROR_INVALID_PARAMETER, "Check if removing user 0 returns error" },
+
+               res_t{ remove_user_wrap<ud_remove_user_fail, remove_user_fail::remove_user_1>( (TestUser::user_1), test_reply_callback_default, ud),
+                       SUBSESSION_ERROR_NOT_AVAILABLE, "Check if removing non existing user 1 returns error" },
+
+               res_t{ remove_user_wrap<ud_remove_user_fail, remove_user_fail::remove_user_minus_1>( -(TestUser::user_1), test_reply_callback_default, ud),
+                       SUBSESSION_ERROR_INVALID_PARAMETER, "Check if removing non existing user 1 returns error" },
+
+               res_t{ add_user_wrap<ud_remove_user_fail, remove_user_fail::add_user_1>( TestUser::user_1, test_reply_callback_default, ud),
+                       SUBSESSION_ERROR_NONE, "Check if adding non existing user 1 returns no error" },
+
+               res_t{ remove_user_wrap<ud_remove_user_fail, remove_user_fail::remove_user_1_existing>( TestUser::user_1, test_reply_callback_default, ud),
+                       SUBSESSION_ERROR_NONE, "Check if removing  1 returns no error" },
+
+               res_t{ remove_user_wrap<ud_remove_user_fail, remove_user_fail::remove_user_1_again>( TestUser::user_1, test_reply_callback_default, ud),
+                       SUBSESSION_ERROR_NOT_AVAILABLE, "Check if removing  1 again returns error" },
+       };
+
+       loop_run_for_test(callback_pending_ud<ud_remove_user_fail>,(gpointer*)&ud, ud.loop);
+
+       summarize_results<remove_user_fail::action_items>(results);
+
+}
diff --git a/libsessiond/target_test/test_api_adduser.cpp b/libsessiond/target_test/test_api_adduser.cpp
deleted file mode 100644 (file)
index 8971912..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-#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_subsession_reply_callback (int result, void *cb_data) {
-
-       g_atomic_int_set(&callback_pending_reference, 1);
-
-       if (cb_data == NULL) {
-               return -EBADR;
-       }
-
-       test_user_data *user_data = (test_user_data *)cb_data;
-       user_data->callback_result = result;
-
-       if (result < 0) {
-               return result;
-       }
-
-       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(5001, 2, test_subsession_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);
-
-}
index 0d87674..b115167 100644 (file)
@@ -23,12 +23,6 @@ typedef struct {
        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) {
@@ -70,7 +64,6 @@ int callback_adduserstarted_reference;
 
 int test_subsession_add_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;
diff --git a/libsessiond/target_test/test_api_removeuser.cpp b/libsessiond/target_test/test_api_removeuser.cpp
deleted file mode 100644 (file)
index 71dd00b..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-#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_subsession_reply_callback (int result, void *cb_data) {
-
-       g_atomic_int_inc(&callback_pending_reference);
-
-       if (cb_data == NULL) {
-               return -EBADR;
-       }
-
-       test_user_data *user_data = (test_user_data *)cb_data;
-       user_data->callback_result = result;
-
-       if (result < 0) {
-               return result;
-       }
-
-       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(5001, 2, test_subsession_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);
-
-}
index a0d4b31..c61d94e 100644 (file)
@@ -23,12 +23,6 @@ typedef struct {
        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) {
index 3075dc0..21266b1 100644 (file)
 
 #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 test_switch_callback(int result, void *cb_data) {
 
        //std::cout << " test_switch_callback" << std::endl;
@@ -39,36 +22,6 @@ int test_switch_callback(int result, void *cb_data) {
        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;
-}
-
-const int user_1 = 1;
-const int user_2 = 2;
-
-
 int test_subsession_switch_user_completion_callback(subsession_event_info info, void *cb_data) {
 
        test_user_data_cb_t *user_data = (test_user_data_cb_t *)cb_data;
@@ -78,7 +31,7 @@ int test_subsession_switch_user_completion_callback(subsession_event_info info,
        user_data->prev_user_id = info.switch_user.prev_user;
        user_data->callback_result = -1;
 
-       if(user_data->user_id == user_2 ){
+       if(user_data->user_id == TestUser::user_2 || user_data->user_id == TestUser::user_0){
                user_data->callback_result = 0;
                g_atomic_int_inc(&user_data->callback_reference);
        }
@@ -86,7 +39,6 @@ int test_subsession_switch_user_completion_callback(subsession_event_info info,
        return 0;
 }
 
-
 enum {
        add_user_1 = 0,
        add_user_2,
@@ -94,32 +46,17 @@ enum {
        remove_user_2,
        switch_user_to_1,
        switch_user_to_2,
+       switch_user_to_0,
        switch_completion,
 };
 
 using tud_ = test_user_data_cb_t;
-using ud_ = struct ud_ctrl_t<tud_, 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));
-}
+using ud_ = struct ud_ctrl_t<tud_, tud_, tud_, tud_, tud_, tud_, tud_, tud_>;
 
 TEST(subsession_switch_user_completion, APISwitchUserCompletion) {
 
        ud_ ud = { .loop =  g_main_loop_new (NULL, FALSE),
-               .t = std::tuple<tud_, tud_, tud_, tud_, tud_, tud_, tud_>(),
+               .t = std::tuple<tud_, tud_, tud_, tud_, tud_, tud_, tud_, tud_>(),
        };
 
        std::apply([](auto &... args){( (init_user<tud_ &>(args) ), ...); },  ud.t );
@@ -128,23 +65,26 @@ TEST(subsession_switch_user_completion, APISwitchUserCompletion) {
        int switch_user_completion_res = subsession_register_event_callback(test_subsession_uid, SUBSESSION_SWITCH_USER_COMPLETION,
        test_subsession_switch_user_completion_callback, (void *)&std::get<switch_completion>(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);
+       int add_user_res_1 = add_user_wrap<ud_, add_user_1>(TestUser::user_1, test_reply_callback_default, ud);
+       int add_user_res_2 = add_user_wrap<ud_, add_user_2>(TestUser::user_2, test_reply_callback_default, ud);
 
-       std::get<switch_user_to_1>(ud.t).prev_user_id = user_1;
-       std::get<switch_user_to_1>(ud.t).user_id = user_1;
+       std::get<switch_user_to_1>(ud.t).prev_user_id = TestUser::user_1;
+       std::get<switch_user_to_1>(ud.t).user_id = TestUser::user_1;
 
        int switch_user_res_to_1 = subsession_switch_user(test_subsession_uid, std::get<switch_user_to_1>(ud.t).user_id, test_switch_callback, (void *)&std::get<switch_user_to_1>(ud.t));
 
-
-       std::get<switch_user_to_2>(ud.t).prev_user_id = user_1;
-       std::get<switch_user_to_2>(ud.t).user_id = user_2;
+       std::get<switch_user_to_2>(ud.t).prev_user_id = TestUser::user_1;
+       std::get<switch_user_to_2>(ud.t).user_id = TestUser::user_2;
 
        int switch_user_res_to_2 = subsession_switch_user(test_subsession_uid, std::get<switch_user_to_2>(ud.t).user_id, test_switch_callback, (void *)&std::get<switch_user_to_2>(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);
+       std::get<switch_user_to_0>(ud.t).prev_user_id = TestUser::user_2;
+       std::get<switch_user_to_0>(ud.t).user_id = TestUser::user_0;
+
+       int switch_user_res_to_0 = subsession_switch_user(test_subsession_uid, std::get<switch_user_to_0>(ud.t).user_id, test_switch_callback, (void *)&std::get<switch_user_to_0>(ud.t));
 
+       int remove_user_res_1 = remove_user_wrap<ud_, remove_user_1>(TestUser::user_1, test_reply_callback_default, ud);
+       int remove_user_res_2 = remove_user_wrap<ud_, remove_user_2>(TestUser::user_2, test_reply_callback_default, ud);
 
        g_idle_add(callback_pending_ud<ud_>,(gpointer*)&ud);
        g_main_loop_run(ud.loop);
@@ -154,6 +94,7 @@ TEST(subsession_switch_user_completion, APISwitchUserCompletion) {
        EXPECT_EQ(remove_user_res_1, 0);
        EXPECT_EQ(switch_user_res_to_1, 0);
        EXPECT_EQ(switch_user_res_to_2, 0);
+       EXPECT_EQ(switch_user_res_to_0, 0);
        EXPECT_EQ(add_user_res_2, 0);
        EXPECT_EQ(remove_user_res_2, 0);
 
@@ -168,7 +109,7 @@ TEST(subsession_switch_user_completion, APISwitchUserCompletion) {
 
        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);
+       EXPECT_EQ(user_data_result.user_id, TestUser::user_0);
+       EXPECT_EQ(user_data_result.prev_user_id, TestUser::user_2);
 
 }
index 518b991..d1793f2 100644 (file)
 
 #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;
-}
-
-const int user_1 = 1;
-const int user_2 = 2;
+//const int user_1 = 1;
+//const int user_2 = 2;
 
 int test_subsession_switch_user_wait_callback(subsession_event_info info, void *cb_data) {
 
@@ -63,10 +21,12 @@ int test_subsession_switch_user_wait_callback(subsession_event_info info, void *
        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);
-       if (user_data->user_id == user_2) {
-               g_atomic_int_inc(&user_data->callback_reference);
+       user_data->callback_result = subsession_switch_wait_done( info.switch_user.session_uid, info.switch_user.switch_id);
+
+       if (user_data->user_id == TestUser::user_0 || user_data->user_id == TestUser::user_2) {
+               g_atomic_int_inc(&user_data->callback_reference);
        }
+
        return 0;
 }
 
@@ -77,32 +37,17 @@ enum {
        remove_user_2,
        switch_user_to_1,
        switch_user_to_2,
+       switch_user_to_0,
        switch_wait,
 };
 
 using tud_ = test_user_data_cb_t;
-using ud_ = struct ud_ctrl_t<tud_, 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));
-}
+using ud_ = struct ud_ctrl_t<tud_, tud_, tud_, tud_, tud_, tud_, tud_, tud_>;
 
 TEST(subsession_switch_user_wait, APISwitchUserStarted) {
 
        ud_ ud = { .loop =  g_main_loop_new (NULL, FALSE),
-               .t = std::tuple<tud_, tud_, tud_, tud_, tud_, tud_, tud_>(),
+               .t = std::tuple<tud_, tud_, tud_, tud_, tud_, tud_, tud_, tud_>(),
        };
 
        std::apply([](auto &... args){( (init_user<tud_ &>(args) ), ...); },  ud.t );
@@ -111,23 +56,26 @@ TEST(subsession_switch_user_wait, APISwitchUserStarted) {
        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);
+       int add_user_res_1 = add_user_wrap<ud_, add_user_1>(TestUser::user_1, test_reply_callback_default, ud);
+       int add_user_res_2 = add_user_wrap<ud_, add_user_2>(TestUser::user_2, test_reply_callback_default, ud);
 
-       std::get<switch_user_to_1>(ud.t).prev_user_id = user_1;
-       std::get<switch_user_to_1>(ud.t).user_id = user_1;
+       std::get<switch_user_to_1>(ud.t).prev_user_id = TestUser::user_1;
+       std::get<switch_user_to_1>(ud.t).user_id = TestUser::user_1;
 
-       int switch_user_res_to_1 = subsession_switch_user(test_subsession_uid, std::get<switch_user_to_1>(ud.t).user_id, test_reply_callback, (void *)&std::get<switch_user_to_1>(ud.t));
+       int switch_user_res_to_1 = subsession_switch_user(test_subsession_uid, std::get<switch_user_to_1>(ud.t).user_id, test_reply_callback_default, (void *)&std::get<switch_user_to_1>(ud.t));
 
+       std::get<switch_user_to_2>(ud.t).prev_user_id = TestUser::user_1;
+       std::get<switch_user_to_2>(ud.t).user_id = TestUser::user_2;
 
-       std::get<switch_user_to_2>(ud.t).prev_user_id = user_1;
-       std::get<switch_user_to_2>(ud.t).user_id = user_2;
+       int switch_user_res_to_2 = subsession_switch_user(test_subsession_uid, std::get<switch_user_to_2>(ud.t).user_id, test_reply_callback_default, (void *)&std::get<switch_user_to_2>(ud.t));
 
-       int switch_user_res_to_2 = subsession_switch_user(test_subsession_uid, std::get<switch_user_to_2>(ud.t).user_id, test_reply_callback, (void *)&std::get<switch_user_to_2>(ud.t));
+       std::get<switch_user_to_0>(ud.t).prev_user_id = TestUser::user_2;
+       std::get<switch_user_to_0>(ud.t).user_id = TestUser::user_0;
 
-       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);
+       int switch_user_res_to_0 = subsession_switch_user(test_subsession_uid, std::get<switch_user_to_0>(ud.t).user_id, test_reply_callback_default, (void *)&std::get<switch_user_to_0>(ud.t));
 
+       int remove_user_res_1 = remove_user_wrap<ud_, remove_user_1>(TestUser::user_1, test_reply_callback_default, ud);
+       int remove_user_res_2 = remove_user_wrap<ud_, remove_user_2>(TestUser::user_2, test_reply_callback_default, ud);
 
        g_idle_add(callback_pending_ud<ud_>,(gpointer*)&ud);
        g_main_loop_run(ud.loop);
@@ -137,6 +85,7 @@ TEST(subsession_switch_user_wait, APISwitchUserStarted) {
        EXPECT_EQ(remove_user_res_1, 0);
        EXPECT_EQ(switch_user_res_to_1, 0);
        EXPECT_EQ(switch_user_res_to_2, 0);
+       EXPECT_EQ(switch_user_res_to_0, 0);
        EXPECT_EQ(add_user_res_2, 0);
        EXPECT_EQ(remove_user_res_2, 0);
 
@@ -144,15 +93,15 @@ TEST(subsession_switch_user_wait, APISwitchUserStarted) {
        EXPECT_EQ(0, std::get<add_user_2>(ud.t).callback_result);
        EXPECT_EQ(0, std::get<switch_user_to_1>(ud.t).callback_result);
        EXPECT_EQ(0, std::get<switch_user_to_2>(ud.t).callback_result);
+       EXPECT_EQ(0, std::get<switch_user_to_0>(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);
-
-
+       EXPECT_EQ(user_data_result.user_id, TestUser::user_0);
+       EXPECT_EQ(user_data_result.prev_user_id, TestUser::user_2);
 }
index 0df3e87..1821864 100644 (file)
@@ -144,6 +144,16 @@ TEST(subsession_switch_user_test, APISwitchUserTest) {
 
        int get_curr_user_res = subsession_get_current_user(test_session_id, &got_current_user);
 
+       test_user_data_switch test_switch_1_2_to_0;
+       test_switch_1_2_to_0.session_id = test_session_id;
+       test_switch_1_2_to_0.prev_user_id = 2;
+       test_switch_1_2_to_0.next_user_id = 0;
+       test_switch_1_2_to_0.callback_result = -1;
+
+       int switch_user_res_1_2_to_0 = subsession_switch_user(test_switch_1_2_to_0.session_id,
+               test_switch_1_2_to_0.next_user_id,
+               test_reply_switchuser_callback, (void *)&test_switch_1_2_to_0);
+
        test_user_data test_remove_1_1;
        test_remove_1_1.session_id = test_session_id;
        test_remove_1_1.user_id = 1;
@@ -164,7 +174,11 @@ TEST(subsession_switch_user_test, APISwitchUserTest) {
 
        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(switch_user_res_1_2_to_0, 0);
+       EXPECT_EQ(switch_user_res_1_2_to_0, 0);
+
        EXPECT_EQ(remove_user_res_1_1, 0);
        EXPECT_EQ(remove_user_res_1_2, 0);
        EXPECT_EQ(get_curr_user_res, 0);
@@ -174,6 +188,7 @@ TEST(subsession_switch_user_test, APISwitchUserTest) {
        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_switch_1_2_to_0.callback_result);
        EXPECT_EQ(0, test_remove_1_1.callback_result);
        EXPECT_EQ(0, test_remove_1_2.callback_result);
 }
diff --git a/libsessiond/target_test/test_api_switchuser_err.cpp b/libsessiond/target_test/test_api_switchuser_err.cpp
new file mode 100644 (file)
index 0000000..1244f01
--- /dev/null
@@ -0,0 +1,69 @@
+#include<iostream>
+#include <gtest/gtest.h>
+#include <gio/gio.h>
+#include <pthread.h>
+#include "sessiond.h"
+#include "test_hlp.hpp"
+
+using tud_ = test_user_data_cb_t;
+using ud_switch_user_fail = struct ud_ctrl_t<tud_, tud_, tud_, tud_, tud_, tud_, tud_, tud_, tud_, tud_>;
+
+struct switch_user_fail {
+    enum action {
+               switch_user_0 = 0,
+               switch_non_existing_user_1,
+               switch_user_minus_1,
+               add_user_1,
+               add_user_2,
+               switch_to_user_2,
+               remove_switched_user_2,
+               switch_to_user_0_again,
+               remove_user_1,
+               remove_user_2,
+               action_items
+       };
+};
+
+TEST(subsession_switch_user_test, FailAtSwitchUser) {
+
+       ud_switch_user_fail ud = { .loop = g_main_loop_new(NULL, FALSE),
+               .t = ud_switch_user_fail::the_tuple(),
+       };
+       std::apply([](auto &... args){( (init_user_s<tud_ &, subsession_5001>(args) ), ...); },  ud.t );
+
+       std::array<res_t, switch_user_fail::action_items> results {
+               res_t{ switch_user_wrap<ud_switch_user_fail, switch_user_fail::switch_user_0>(TestUser::user_0, test_reply_callback_default, ud),
+                               SUBSESSION_ERROR_NONE, "Check if switching to user 0 returns no error" },
+
+               res_t{ switch_user_wrap<ud_switch_user_fail, switch_user_fail::switch_non_existing_user_1>(TestUser::user_1, test_reply_callback_default, ud),
+                               SUBSESSION_ERROR_NOT_AVAILABLE, "Check if switching non_existing user 1 returns error" },
+
+               res_t{ switch_user_wrap<ud_switch_user_fail, switch_user_fail::switch_user_minus_1>( -(TestUser::user_1), test_reply_callback_default, ud),
+                               SUBSESSION_ERROR_INVALID_PARAMETER, "Check if switching to user -1 returns error" },
+
+               res_t{ add_user_wrap<ud_switch_user_fail, switch_user_fail::add_user_1>( TestUser::user_1, test_reply_callback_default, ud),
+                               SUBSESSION_ERROR_NONE, "Check if adding user 1 returns no error" },
+
+               res_t{ add_user_wrap<ud_switch_user_fail, switch_user_fail::add_user_2>( TestUser::user_2, test_reply_callback_default, ud),
+                               SUBSESSION_ERROR_NONE, "Check if adding user 2 returns no  error" },
+
+               res_t{ switch_user_wrap<ud_switch_user_fail, switch_user_fail::switch_to_user_2>( TestUser::user_2, test_reply_callback_default, ud),
+                               SUBSESSION_ERROR_NONE, "Check if switching to user 2 returns no error" },
+
+               res_t{ remove_user_wrap<ud_switch_user_fail, switch_user_fail::remove_switched_user_2>( TestUser::user_2, test_reply_callback_default, ud),
+                               SUBSESSION_ERROR_RESOURCE_BUSY, "Check if removing user 2 returns error" },
+
+               res_t{ switch_user_wrap<ud_switch_user_fail, switch_user_fail::switch_to_user_0_again>( TestUser::user_0, test_reply_callback_default, ud),
+                               SUBSESSION_ERROR_NONE, "Check if switching to user 0 returns no error" },
+
+               res_t{ remove_user_wrap<ud_switch_user_fail, switch_user_fail::remove_user_1>( TestUser::user_1, test_reply_callback_default, ud),
+                               SUBSESSION_ERROR_NONE, "Check if removing user 1 returns no  error" },
+
+               res_t{ remove_user_wrap<ud_switch_user_fail, switch_user_fail::remove_user_2>( TestUser::user_2, test_reply_callback_default, ud),
+                               SUBSESSION_ERROR_NONE, "Check if removing user 2 returns no  error" },
+       };
+
+       loop_run_for_test(callback_pending_ud<ud_switch_user_fail>,(gpointer*)&ud, ud.loop);
+
+       summarize_results<switch_user_fail::action_items>(results);
+}
index 13124cb..f4bb714 100644 (file)
@@ -4,11 +4,27 @@
 #include <pthread.h>
 
 const int test_subsession_uid = 5001;
+struct TestUser {
+       enum user {
+               user_0 = 0,
+               user_1,
+               user_2,
+               user_3,
+               user_4,
+               user_5
+       };
+};
+
+
+const int got = 0;
+const int expected = 1;
+const int desc = 2;
 
 template<typename... Args>
 struct ud_ctrl_t{
                GMainLoop * loop;
-               std::tuple<Args...> t;
+               using the_tuple = std::tuple<Args...>;
+               the_tuple t;
 };
 
 typedef struct {
@@ -19,13 +35,17 @@ typedef struct {
        int callback_reference;
        int prev_user_id;
        subsession_event_type_e event;
-} test_user_data_cb_t;
+       } test_user_data_cb_t;
 
 
 int _atomic_int_get(int *value) {
        return g_atomic_int_get(value);
 }
 
+int tud_atomic_int_get(test_user_data_cb_t &arg) {
+       return g_atomic_int_get(&arg.callback_reference);
+}
+
 template<typename T>
 void _set_0(T arg);
 
@@ -55,7 +75,46 @@ void init_user(test_user_data_cb_t& arg) {
        _set_0(&arg.callback_reference);
 }
 
+struct subsession_5001 {
+       static int constexpr subsession_uid() { return 5001; };
+};
+struct subsession_5002 {
+       static int constexpr subsession_uid() { return 5002; };
+};
+struct subsession_5003 {
+       static int constexpr subsession_uid() { return 5003; };
+};
+struct subsession_5004 {
+       static int constexpr subsession_uid() { return 5004; };
+};
 
+template<typename T, typename S>
+void init_user_s(T arg);
+
+template<typename T = test_user_data_cb_t& , typename S>
+void init_user_s(test_user_data_cb_t& arg) {
+       arg.session_uid = S::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 = test_user_data_cb_t, typename S>
+void init_user_s(test_user_data_cb_t& arg) {
+       arg.session_uid = S::session_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) {
@@ -64,6 +123,16 @@ void atomic_set_0(T arg, V... args) {
        return;
 }
 */
+int test_reply_callback_default (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;
+}
+
 template<typename T>
 gboolean callback_pending(gpointer data) {
 
@@ -85,3 +154,73 @@ gboolean callback_pending(gpointer data) {
 
        return TRUE;
 }
+
+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;
+}
+
+template<typename T, int N>
+int add_user_wrap(int user_id, subsession_reply_callback cb, T &ud) {
+
+       std::get<N>(ud.t).user_id = user_id;
+       int res = subsession_add_user(test_subsession_uid, std::get<N>(ud.t).user_id,
+               cb, (void *)&std::get<N>(ud.t));
+       if ( res != SUBSESSION_ERROR_NONE ) { g_atomic_int_inc(&std::get<N>(ud.t).callback_reference); }
+       return res;
+}
+
+template<typename T, int N>
+int remove_user_wrap(int user_id, subsession_reply_callback cb, T &ud) {
+
+       std::get<N>(ud.t).user_id = user_id;
+       int res = subsession_remove_user(test_subsession_uid, std::get<N>(ud.t).user_id,
+               cb, (void *)&std::get<N>(ud.t));
+       if ( res != SUBSESSION_ERROR_NONE ) { g_atomic_int_inc(&std::get<N>(ud.t).callback_reference); }
+       return res;
+}
+
+template<typename T, int N>
+int switch_user_wrap(int user_id, subsession_reply_callback cb, T &ud) {
+
+       std::get<N>(ud.t).user_id = user_id;
+       int res =  subsession_switch_user(test_subsession_uid, std::get<N>(ud.t).user_id,
+               cb, (void *)&std::get<N>(ud.t));
+       if ( res != SUBSESSION_ERROR_NONE ) { g_atomic_int_inc(&std::get<N>(ud.t).callback_reference); }
+       return res;
+}
+
+const char * head_{ "\033[1;32m[          ]\033[0m "};
+
+void loop_run_for_test(GSourceFunc f, gpointer data, GMainLoop *loop) {
+       guint idle_id = g_idle_add(f, data);
+       g_main_loop_run(loop);
+       g_source_remove(idle_id);
+       g_main_loop_unref(loop);
+}
+
+using res_t = std::tuple<int, int, std::string>;
+
+template<int N>
+void summarize_results(std::array<res_t, N> &results) {
+       std::for_each(results.begin(), results.end(), [=](res_t &res) {
+               std::cout << head_ << std::get<desc>(res) << std::endl;
+               EXPECT_EQ(std::get<expected>(res), std::get<got>(res));
+       });
+}