summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarol Lewandowski <k.lewandowsk@samsung.com>2022-07-21 21:20:20 +0000
committerGerrit Code Review <gerrit@review>2022-07-21 21:20:20 +0000
commitdb85cb357bd5886eb88221d6490f0fb1530c1dce (patch)
tree6f25d3c47a2dde1664f5ca549ea629dabb99aa69
parent8dce09ba829c6581c9df5ce1938681634744861d (diff)
parent2d695b5718021f7561b64638c62b6b7b73aca673 (diff)
downloadsessiond-db85cb357bd5886eb88221d6490f0fb1530c1dce.tar.gz
sessiond-db85cb357bd5886eb88221d6490f0fb1530c1dce.tar.bz2
sessiond-db85cb357bd5886eb88221d6490f0fb1530c1dce.zip
Merge "clientExample: proper clean-up in case of subsession errors" into tizen
-rw-r--r--clientExample/app/main.cpp197
1 files changed, 164 insertions, 33 deletions
diff --git a/clientExample/app/main.cpp b/clientExample/app/main.cpp
index 69c1cb9..97b9428 100644
--- a/clientExample/app/main.cpp
+++ b/clientExample/app/main.cpp
@@ -2,6 +2,7 @@
#include <iostream>
#include <gio/gio.h>
#include <cassert>
+#include <memory>
#include <stdlib.h>
#include "sessiond.h"
@@ -70,9 +71,17 @@ gboolean callback_pending(gpointer data)
if (is_pending == TRUE)
return TRUE;
- // N.B. There are `noOfUsers` add and remove operations. Each add/remove
- // increments the value of the `callback_pending_reference` variable.
- if ((unsigned)ctrl_value >= usernames.size() * 2) {
+ /*
+ * N.B. There are `usernames.size()` add, remove and switch operations.
+ * Each add/remove/switch user increments the value of the
+ * `callback_pending_reference` variable. The last `+3`
+ * is
+ * for the three extra switches:
+ * - setting user to the initial one before starting the switch user test
+ * - setting user to the initial one before removing users
+ * - setting user to the beginning one at the end of tests.
+ */
+ if ((unsigned)ctrl_value >= usernames.size() * 3 + 3) {
g_main_loop_quit(loop);
g_main_loop_unref(loop);
}
@@ -125,6 +134,8 @@ void test_reply_switchuser_callback(int result, void *cb_data)
{
g_mutex_lock(&mutex);
+ g_atomic_int_inc(&callback_pending_reference);
+
test_user_data *user_data = (test_user_data *)cb_data;
user_data->callback_result = result;
@@ -212,6 +223,86 @@ void wait_for_all_pending_callbacks(GMainLoop *loop, GThread *loop_thread)
g_thread_join(loop_thread);
}
+int get_user_list(subsession_user_t **userlist = NULL)
+{
+ int count;
+
+ if (int r = subsession_get_user_list(SESSION_UID, userlist, &count); r != SUBSESSION_ERROR_NONE) {
+ printf("Error getting initial user list: %d\n", r);
+ return -1;
+ }
+
+ return count;
+}
+
+bool remove_all_test_users(bool ignore_errors = false)
+{
+ bool all_removed = true;
+
+ for (auto user : usernames) {
+ test_user_data test_remove_ud;
+ test_remove_ud.callback_result = -1;
+ int remove_user_res = subsession_remove_user(SESSION_UID, user,
+ test_reply_removeuser_callback, (void *)&test_remove_ud);
+ if (remove_user_res != SUBSESSION_ERROR_NONE && !ignore_errors) {
+ printf("removing user %s failed code: %d\n", user, remove_user_res);
+ all_removed = false;
+ }
+ }
+
+ return all_removed;
+}
+
+bool check_user_name_collisions(subsession_user_t *userlist, int number_of_users)
+{
+ for (int i = 0; i < number_of_users; ++i)
+ for (auto user : usernames)
+ if (strncmp(userlist[i], user, SUBSESSION_USER_MAXLEN) == 0)
+ return true;
+
+ return false;
+}
+
+void final_cleanup()
+{
+ g_mutex_clear(&mutex);
+ g_cond_clear(&cond);
+}
+
+bool switch_to_first_chosen_user(subsession_user_t first_user)
+{
+ test_user_data test_switch_ud;
+ test_switch_ud.callback_result = CALLBACK_DATA_MAGIC;
+
+ int switch_user_res = subsession_switch_user(SESSION_UID, first_user,
+ test_reply_switchuser_callback, (void *)&test_switch_ud);
+ if (switch_user_res != 0) {
+ printf("Error subsession_switch_user res is%d\n", switch_user_res);
+ return false;
+ }
+
+ return true;
+}
+
+void cleanup_after_failure(subsession_user_t first_user)
+{
+ switch_to_first_chosen_user(first_user);
+ remove_all_test_users(true);
+ final_cleanup();
+}
+
+template <typename F> struct generic_destructor {
+ F f;
+ bool finalize;
+
+ generic_destructor(F _f) : f(std::move(_f)), finalize(true) {}
+ ~generic_destructor() { if (finalize) f(); };
+};
+
+struct subsession_user_deleter {
+ void operator() (subsession_user_t *p) { free(p); }
+};
+
int main(int argc, char *argv[])
{
g_cond_init(&cond);
@@ -221,8 +312,39 @@ int main(int argc, char *argv[])
GThread *loop_thread = g_thread_new("mainloop thread", (GThreadFunc) g_main_loop_run, loop);
///===================================///
- printf("Test program start\nCreating test users...");
+ printf("Test program start\nGetting initial user list... ");
+
+ /*
+ * First get the initial user list. We're doing this for two reasons:
+ * 1) to ensure proper calculations taking into account previously registered users
+ * 2) to ensure no name collisions are taking place
+ *
+ */
+ subsession_user_t *initial_userlist_raw;
+ int initial_number_of_users = get_user_list(&initial_userlist_raw);
+ if (initial_number_of_users == -1)
+ return EXIT_FAILURE;
+ std::unique_ptr<subsession_user_t[], subsession_user_deleter> initial_userlist { initial_userlist_raw };
+
+ if (check_user_name_collisions(initial_userlist.get(), initial_number_of_users)) {
+ printf("User name collisions detected. Test interrupted. Consider manual clean-up before re-running.\n");
+ // N.B. Since we've detected name collisions, we deliberately choose not to remove any users.
+ final_cleanup();
+ return EXIT_FAILURE;
+ }
+ green_print("done");
+ subsession_user_t first_user;
+ int r = subsession_get_current_user(SESSION_UID, first_user);
+ if (r != SUBSESSION_ERROR_NONE) {
+ printf("Error: subsession_get_current_user result is %d\n", r);
+ final_cleanup();
+ return EXIT_FAILURE;
+ }
+
+ generic_destructor failure_finalizer ([&]() { cleanup_after_failure(first_user); } );
+
+ printf("Creating test users... ");
for (size_t i = 0; i < usernames.size(); ++i)
{
g_mutex_lock(&mutex);
@@ -245,32 +367,44 @@ int main(int argc, char *argv[])
}
green_print("done");
- int registered_users;
- subsession_user_t *userlist;
- ///===================================///
- int r = subsession_get_user_list(SESSION_UID, &userlist, &registered_users);
- if (r != SUBSESSION_ERROR_NONE) {
- printf("Error getting user list: %d\n", r);
+ printf("Setting user to the initial one... ");
+ if (!switch_user_test(SUBSESSION_INITIAL_SID)) {
+ printf("Error setting user to starting\n");
return EXIT_FAILURE;
}
+ green_print("done");
+
+ subsession_user_t *userlist_raw;
+ int registered_users = get_user_list(&userlist_raw);
+ if (registered_users == -1)
+ return EXIT_FAILURE;
+ std::unique_ptr<subsession_user_t[], subsession_user_deleter> userlist { userlist_raw };
- printf("No of users [%zu]...", usernames.size());
- if (usernames.size() == (unsigned) (registered_users-1))
+ printf("No of test users [%zu]... ", usernames.size());
+ if (usernames.size() + initial_number_of_users == (unsigned) (registered_users))
green_print("ok");
else
{
- printf("Failed to register some users (%zu expected, got %d)\n", usernames.size(), registered_users);
+ printf("Failed to register some users: %zu expected (%d initial + %zu ours), got %d"
+ , usernames.size() + initial_number_of_users
+ , initial_number_of_users
+ , usernames.size()
+ , registered_users
+ );
return EXIT_FAILURE;
+
}
/* NB: the order of users as returned by get_user_list is unspecified
* and does not need to match the one in the original array above. */
- for (int i = 0; i < registered_users; ++i)
- printf("%s\n", userlist[i]);
+ for (int i = 0; i < registered_users; ++i) {
+ for (auto user : usernames)
+ if (strncmp(userlist[i], user, SUBSESSION_USER_MAXLEN) == 0)
+ printf("%s\n", userlist[i]);
+ }
///===================================///
- printf("Switching users test...");
-
+ printf("Switching users test... ");
callbackCount = 0;
test_user_data_cb_t data;
@@ -282,11 +416,11 @@ int main(int argc, char *argv[])
}
if (!switch_to_each_user_to_generate_events()
- || !check_callbacks_called((registered_users-1)))
+ || !check_callbacks_called(usernames.size()))
return EXIT_FAILURE;
///===================================///
- printf("Subsession unregister event callback test...");
+ printf("Subsession unregister event callback test... ");
callbackCount = 0;
r = subsession_unregister_event_callback(SESSION_UID, SUBSESSION_SWITCH_USER_COMPLETION);
@@ -300,28 +434,25 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
///======================================///
- printf("Removing users...");
+ printf("Removing users... ");
if (!switch_user_test(SUBSESSION_INITIAL_SID)) {
printf("Error setting user to starting\n");
return EXIT_FAILURE;
}
- for (auto user : usernames) {
- test_user_data test_remove_ud;
- test_remove_ud.callback_result = -1;
- int remove_user_res = subsession_remove_user(SESSION_UID, user,
- test_reply_removeuser_callback, (void *)&test_remove_ud);
- if (remove_user_res != SUBSESSION_ERROR_NONE)
- {
- printf("removing user %s failed code: %d\n", user, remove_user_res);
- return EXIT_FAILURE;
- }
- }
+
+ failure_finalizer.finalize = false;
+
+ if (!remove_all_test_users())
+ return EXIT_FAILURE;
+
green_print("done");
+ if (!switch_to_first_chosen_user(first_user))
+ return EXIT_FAILURE;
+
wait_for_all_pending_callbacks(loop, loop_thread);
- g_mutex_clear(&mutex);
- g_cond_clear(&cond);
+ final_cleanup();
printf("Test program end\n");
return EXIT_SUCCESS;