diff options
author | Thomas Haller <thaller@redhat.com> | 2019-11-02 14:15:48 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2019-11-06 17:36:57 +0100 |
commit | 81eec85c594990c070edd802e4f6eb1e04d5882b (patch) | |
tree | d54ff2cc17ea28aa78b67eab9126ad80642cea0e | |
parent | f00ca9885f02384f10a647a761318f2f029b34e9 (diff) | |
download | NetworkManager-81eec85c594990c070edd802e4f6eb1e04d5882b.tar.gz |
tests: add nmtstc_client_new() helper
-rw-r--r-- | shared/nm-test-libnm-utils.h | 1 | ||||
-rw-r--r-- | shared/nm-test-utils-impl.c | 148 |
2 files changed, 149 insertions, 0 deletions
diff --git a/shared/nm-test-libnm-utils.h b/shared/nm-test-libnm-utils.h index 76e2a2158c..63e3b4c72c 100644 --- a/shared/nm-test-libnm-utils.h +++ b/shared/nm-test-libnm-utils.h @@ -67,3 +67,4 @@ void nmtstc_service_update_connection_variant (NMTstcServiceInfo *sinfo, GVariant *connection, gboolean verify_connection); +NMClient *nmtstc_client_new (gboolean allow_iterate_main_context); diff --git a/shared/nm-test-utils-impl.c b/shared/nm-test-utils-impl.c index 39f0a08325..bbe74a9656 100644 --- a/shared/nm-test-utils-impl.c +++ b/shared/nm-test-utils-impl.c @@ -406,3 +406,151 @@ nmtstc_service_update_connection_variant (NMTstcServiceInfo *sinfo, g_assert (g_variant_is_of_type (result, G_VARIANT_TYPE ("()"))); g_variant_unref (result); } + +/*****************************************************************************/ + +typedef struct { + GMainLoop *loop; + NMClient *client; +} NMTstcClientNewData; + +static void +_nmtstc_client_new_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + NMTstcClientNewData *d = user_data; + gs_free_error GError *error = NULL; + + g_assert (!d->client); + + d->client = nm_client_new_finish (res, + nmtst_get_rand_bool () ? &error : NULL); + + nmtst_assert_success (NM_IS_CLIENT (d->client), error); + + g_main_loop_quit (d->loop); +} + +static NMClient * +_nmtstc_client_new (gboolean sync) +{ + gs_free GError *error = NULL; + NMClient *client; + + /* Create a NMClient instance synchronously, and arbitrarily use either + * the sync or async constructor. + * + * Note that the sync and async construct differ in one important aspect: + * the async constructor iterates the current g_main_context_get_thread_default(), + * while the sync constructor does not! Aside from that, both should behave + * pretty much the same way. */ + + if (sync) { + nm_auto_destroy_and_unref_gsource GSource *source = NULL; + + if (nmtst_get_rand_bool ()) { + /* the current main context must not be iterated! */ + source = g_idle_source_new (); + g_source_set_callback (source, nmtst_g_source_assert_not_called, NULL, NULL); + g_source_attach (source, g_main_context_get_thread_default ()); + } + + if (nmtst_get_rand_bool ()) { + gboolean success; + + client = g_object_new (NM_TYPE_CLIENT, NULL); + g_assert (NM_IS_CLIENT (client)); + + success = g_initable_init (G_INITABLE (client), + NULL, + nmtst_get_rand_bool () ? &error : NULL); + nmtst_assert_success (success, error); + } else { + client = nm_client_new (NULL, + nmtst_get_rand_bool () ? &error : NULL); + } + } else { + nm_auto_unref_gmainloop GMainLoop *loop = NULL; + NMTstcClientNewData d = { .loop = NULL, }; + + loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE); + + d.loop = loop; + nm_client_new_async (NULL, + _nmtstc_client_new_cb, + &d); + g_main_loop_run (loop); + g_assert (NM_IS_CLIENT (d.client)); + client = d.client; + } + + nmtst_assert_success (NM_IS_CLIENT (client), error); + return client; +} + +typedef struct { + GMainLoop *loop; + NMClient *client; + bool sync; +} NewSyncInsideDispatchedData; + +static gboolean +_nmtstc_client_new_inside_loop_do (gpointer user_data) +{ + NewSyncInsideDispatchedData *d = user_data; + + g_assert (d->loop); + g_assert (!d->client); + + d->client = nmtstc_client_new (d->sync); + g_main_loop_quit (d->loop); + return G_SOURCE_CONTINUE; +} + +static NMClient * +_nmtstc_client_new_inside_loop (gboolean sync) +{ + GMainContext *context = g_main_context_get_thread_default (); + nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new (context, FALSE); + NewSyncInsideDispatchedData d = { + .sync = sync, + .loop = loop, + }; + nm_auto_destroy_and_unref_gsource GSource *source = NULL; + + source = g_idle_source_new (); + g_source_set_callback (source, _nmtstc_client_new_inside_loop_do, &d, NULL); + g_source_attach (source, context); + + g_main_loop_run (loop); + g_assert (NM_IS_CLIENT (d.client)); + return d.client; +} + +NMClient * +nmtstc_client_new (gboolean allow_iterate_main_context) +{ + gboolean inside_loop; + gboolean sync; + + if (!allow_iterate_main_context) { + sync = TRUE; + inside_loop = FALSE; + } else { + /* The caller allows to iterate the main context. That that point, + * we can both use the synchronous and the asynchronous initialization, + * both should yield the same result. Choose one randomly. */ + sync = nmtst_get_rand_bool (); + inside_loop = ((nmtst_get_rand_uint32 () % 3) == 0); + } + + if (inside_loop) { + /* Create the client on an idle handler of the current context. + * In practice, it should make no difference, which this check + * tries to prove. */ + return _nmtstc_client_new_inside_loop (sync); + } + + return _nmtstc_client_new (sync); +} |