tests: add nmtstc_client_new() helper

This commit is contained in:
Thomas Haller 2019-11-02 14:15:48 +01:00
parent ec39498fc6
commit 8def37dd65
2 changed files with 149 additions and 0 deletions

View file

@ -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);

View file

@ -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);
}