diff options
author | Karol Lewandowski <k.lewandowsk@samsung.com> | 2022-07-21 21:20:20 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@review> | 2022-07-21 21:20:20 +0000 |
commit | db85cb357bd5886eb88221d6490f0fb1530c1dce (patch) | |
tree | 6f25d3c47a2dde1664f5ca549ea629dabb99aa69 | |
parent | 8dce09ba829c6581c9df5ce1938681634744861d (diff) | |
parent | 2d695b5718021f7561b64638c62b6b7b73aca673 (diff) | |
download | sessiond-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.cpp | 197 |
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, ®istered_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; |