summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorOlivier Crête <olivier.crete@collabora.com>2014-02-24 23:03:42 -0500
committerOlivier Crête <olivier.crete@collabora.com>2014-02-25 00:51:31 -0500
commit00e91acecc338d4ff3822384650912cfd7b68f7e (patch)
treeddfc23b43e56025d3c1d43694bcc0d0c83e29347 /tests
parentee18973272b06e43eb146b72f41e6cc9a201b410 (diff)
downloadlibnice-00e91acecc338d4ff3822384650912cfd7b68f7e.tar.gz
test: Use a less racy way to know if the test is ready to start
Also, keep a pointer to the other structure for tests to use
Diffstat (limited to 'tests')
-rw-r--r--tests/test-io-stream-common.c66
-rw-r--r--tests/test-io-stream-common.h8
2 files changed, 61 insertions, 13 deletions
diff --git a/tests/test-io-stream-common.c b/tests/test-io-stream-common.c
index b74e9d9..5856d69 100644
--- a/tests/test-io-stream-common.c
+++ b/tests/test-io-stream-common.c
@@ -45,6 +45,10 @@
#include <unistd.h>
#endif
+GMutex start_mutex;
+GCond start_cond;
+gboolean started;
+
static gboolean timer_cb (gpointer pointer)
{
g_debug ("test-thread:%s: %p", G_STRFUNC, pointer);
@@ -54,6 +58,17 @@ static gboolean timer_cb (gpointer pointer)
exit (-1);
}
+static void
+wait_for_start (TestIOStreamThreadData *data)
+{
+ g_mutex_lock (data->start_mutex);
+ (*data->start_count)--;
+ g_cond_broadcast (data->start_cond);
+ while (*data->start_count > 0)
+ g_cond_wait (data->start_cond, data->start_mutex);
+ g_mutex_unlock (data->start_mutex);
+}
+
static gpointer
write_thread_cb (gpointer user_data)
{
@@ -65,7 +80,7 @@ write_thread_cb (gpointer user_data)
g_main_context_push_thread_default (main_context);
/* Synchronise thread starting. */
- while (!g_main_loop_is_running (data->error_loop));
+ wait_for_start (data);
/* Wait for the stream to be writeable. */
g_mutex_lock (&data->write_mutex);
@@ -94,7 +109,7 @@ read_thread_cb (gpointer user_data)
g_main_context_push_thread_default (main_context);
/* Synchronise thread starting. */
- while (!g_main_loop_is_running (data->error_loop));
+ wait_for_start (data);
if (data->reliable)
input_stream = g_io_stream_get_input_stream (data->io_stream);
@@ -114,7 +129,7 @@ main_thread_cb (gpointer user_data)
g_main_context_push_thread_default (data->main_context);
/* Synchronise thread starting. */
- while (!g_main_loop_is_running (data->error_loop));
+ wait_for_start (data);
/* Run the main context. */
g_main_loop_run (data->main_loop);
@@ -316,14 +331,6 @@ spawn_thread (const gchar *thread_name, GThreadFunc thread_func,
return thread;
}
-static void
-join_main_loop (GMainLoop *main_loop)
-{
- while (!g_main_loop_is_running (main_loop));
- while (g_main_loop_is_running (main_loop))
- g_main_loop_quit (main_loop);
-}
-
void
run_io_stream_test (guint deadlock_timeout, gboolean reliable,
const TestIOStreamCallbacks *callbacks,
@@ -334,6 +341,12 @@ run_io_stream_test (guint deadlock_timeout, gboolean reliable,
GThread *l_main_thread, *r_main_thread;
GThread *l_write_thread, *l_read_thread, *r_write_thread, *r_read_thread;
TestIOStreamThreadData l_data, r_data;
+ GMutex mutex;
+ GCond cond;
+ guint start_count = 6;
+
+ g_mutex_init (&mutex);
+ g_cond_init (&cond);
error_loop = g_main_loop_new (NULL, FALSE);
@@ -348,6 +361,9 @@ run_io_stream_test (guint deadlock_timeout, gboolean reliable,
g_mutex_init (&l_data.write_mutex);
l_data.stream_open = FALSE;
l_data.stream_ready = FALSE;
+ l_data.start_mutex = &mutex;
+ l_data.start_cond = &cond;
+ l_data.start_count = &start_count;
r_data.reliable = reliable;
r_data.error_loop = error_loop;
@@ -359,6 +375,12 @@ run_io_stream_test (guint deadlock_timeout, gboolean reliable,
g_mutex_init (&r_data.write_mutex);
r_data.stream_open = FALSE;
r_data.stream_ready = FALSE;
+ r_data.start_mutex = &mutex;
+ r_data.start_cond = &cond;
+ r_data.start_count = &start_count;
+
+ l_data.other = &r_data;
+ r_data.other = &l_data;
/* Create the L and R agents. */
l_data.agent = create_agent (TRUE, &l_data,
@@ -387,6 +409,11 @@ run_io_stream_test (guint deadlock_timeout, gboolean reliable,
l_write_thread = spawn_thread ("libnice L write", write_thread_cb, &l_data);
r_write_thread = spawn_thread ("libnice R write", write_thread_cb, &r_data);
} else {
+ g_mutex_lock (&mutex);
+ start_count -= 2;
+ g_cond_broadcast (&cond);
+ g_mutex_unlock (&mutex);
+
l_write_thread = NULL;
r_write_thread = NULL;
}
@@ -395,8 +422,8 @@ run_io_stream_test (guint deadlock_timeout, gboolean reliable,
g_main_loop_run (error_loop);
/* Clean up the main loops and threads. */
- join_main_loop (l_data.main_loop);
- join_main_loop (r_data.main_loop);
+ stop_main_loop (l_data.main_loop);
+ stop_main_loop (r_data.main_loop);
g_thread_join (l_read_thread);
g_thread_join (r_read_thread);
@@ -434,6 +461,9 @@ run_io_stream_test (guint deadlock_timeout, gboolean reliable,
g_main_context_unref (l_data.main_context);
g_main_loop_unref (error_loop);
+
+ g_mutex_clear (&mutex);
+ g_cond_clear (&cond);
}
/* Once we’ve received all the expected bytes, wait to finish sending all bytes,
@@ -485,3 +515,13 @@ check_for_termination (TestIOStreamThreadData *data, gsize *recv_count,
g_main_loop_quit (data->error_loop);
}
}
+
+void
+stop_main_loop (GMainLoop *loop)
+{
+ GSource *src = g_idle_source_new ();
+ g_source_set_callback (src, (GSourceFunc) g_main_loop_quit,
+ g_main_loop_ref (loop), (GDestroyNotify) g_main_loop_unref);
+ g_source_attach (src, g_main_loop_get_context (loop));
+ g_source_unref (src);
+}
diff --git a/tests/test-io-stream-common.h b/tests/test-io-stream-common.h
index afc6495..8f7bac1 100644
--- a/tests/test-io-stream-common.h
+++ b/tests/test-io-stream-common.h
@@ -79,6 +79,8 @@ struct _TestIOStreamThreadData {
gpointer user_data;
GDestroyNotify user_data_free;
+ TestIOStreamThreadData *other;
+
/*< private >*/
const TestIOStreamCallbacks *callbacks;
@@ -87,6 +89,10 @@ struct _TestIOStreamThreadData {
gboolean stream_ready;
GCond write_cond;
GMutex write_mutex;
+
+ GMutex *start_mutex;
+ GCond *start_cond;
+ guint *start_count;
};
GThread *spawn_thread (const gchar *thread_name, GThreadFunc thread_func,
@@ -97,3 +103,5 @@ void run_io_stream_test (guint deadlock_timeout, gboolean reliable,
gpointer r_user_data, GDestroyNotify r_user_data_free);
void check_for_termination (TestIOStreamThreadData *data, gsize *recv_count,
gsize *other_recv_count, gsize *send_count, gsize expected_recv_count);
+
+void stop_main_loop (GMainLoop *loop);