5 static const gchar *test_file;
7 char *test_file_buffer;
9 static char async_read_buffer[8192];
12 read_data (GObject *source, GAsyncResult *result, gpointer loop)
14 GInputStream *in = G_INPUT_STREAM (source);
18 nread = g_input_stream_read_finish (in, result, &error);
19 g_assert_no_error (error);
21 g_assert_cmpint (nread, >, 0);
22 g_assert_cmpint (nread, <=, MIN(sizeof (async_read_buffer), test_file_size));
23 g_assert (memcmp (async_read_buffer, test_file_buffer, nread) == 0);
25 g_main_loop_quit (loop);
29 opened_for_read (GObject *source, GAsyncResult *result, gpointer loop)
31 GFile *file = G_FILE (source);
35 in = g_file_read_finish (file, result, &error);
36 g_assert_no_error (error);
38 memset (async_read_buffer, 0, sizeof (async_read_buffer));
39 g_input_stream_read_async (G_INPUT_STREAM (in),
40 async_read_buffer, sizeof (async_read_buffer),
41 G_PRIORITY_DEFAULT, NULL,
47 /* Test 1: Async I/O started in a thread with a thread-default context
48 * will stick to that thread, and will complete even if the default
49 * main loop is blocked. (NB: the last part would not be true if we
50 * were testing GFileMonitor!)
53 static gboolean idle_start_test1_thread (gpointer loop);
54 static gpointer test1_thread (gpointer user_data);
56 static gboolean test1_done;
57 static GCond test1_cond;
58 static GMutex test1_mutex;
61 test_thread_independence (void)
65 loop = g_main_loop_new (NULL, FALSE);
66 g_idle_add (idle_start_test1_thread, loop);
67 g_main_loop_run (loop);
68 g_main_loop_unref (loop);
72 idle_start_test1_thread (gpointer loop)
76 gboolean io_completed;
78 g_mutex_lock (&test1_mutex);
79 thread = g_thread_new ("test1", test1_thread, NULL);
81 time = g_get_monotonic_time () + 2 * G_TIME_SPAN_SECOND;
84 io_completed = g_cond_wait_until (&test1_cond, &test1_mutex, time);
85 g_assert (io_completed);
87 g_thread_join (thread);
89 g_mutex_unlock (&test1_mutex);
90 g_main_loop_quit (loop);
91 return G_SOURCE_REMOVE;
95 test1_thread (gpointer user_data)
97 GMainContext *context;
101 /* Wait for main thread to be waiting on test1_cond */
102 g_mutex_lock (&test1_mutex);
104 context = g_main_context_new ();
105 g_assert (g_main_context_get_thread_default () == NULL);
106 g_main_context_push_thread_default (context);
107 g_assert (g_main_context_get_thread_default () == context);
109 file = g_file_new_for_path (test_file);
110 g_assert (g_file_supports_thread_contexts (file));
112 loop = g_main_loop_new (context, FALSE);
113 g_file_read_async (file, G_PRIORITY_DEFAULT, NULL,
114 opened_for_read, loop);
115 g_object_unref (file);
116 g_main_loop_run (loop);
117 g_main_loop_unref (loop);
120 g_cond_signal (&test1_cond);
121 g_mutex_unlock (&test1_mutex);
123 g_main_context_pop_thread_default (context);
124 g_main_context_unref (context);
129 /* Test 2: If we push a thread-default context in the main thread, we
130 * can run async ops in that context without running the default
134 static gboolean test2_fail (gpointer user_data);
137 test_context_independence (void)
139 GMainContext *context;
142 guint default_timeout;
143 GSource *thread_default_timeout;
145 context = g_main_context_new ();
146 g_assert (g_main_context_get_thread_default () == NULL);
147 g_main_context_push_thread_default (context);
148 g_assert (g_main_context_get_thread_default () == context);
150 file = g_file_new_for_path (test_file);
151 g_assert (g_file_supports_thread_contexts (file));
153 /* Add a timeout to the main loop, to fail immediately if it gets run */
154 default_timeout = g_timeout_add_full (G_PRIORITY_HIGH, 0,
155 test2_fail, NULL, NULL);
156 /* Add a timeout to the alternate loop, to fail if the I/O *doesn't* run */
157 thread_default_timeout = g_timeout_source_new_seconds (2);
158 g_source_set_callback (thread_default_timeout, test2_fail, NULL, NULL);
159 g_source_attach (thread_default_timeout, context);
161 loop = g_main_loop_new (context, FALSE);
162 g_file_read_async (file, G_PRIORITY_DEFAULT, NULL,
163 opened_for_read, loop);
164 g_object_unref (file);
165 g_main_loop_run (loop);
166 g_main_loop_unref (loop);
168 g_source_remove (default_timeout);
169 g_source_destroy (thread_default_timeout);
170 g_source_unref (thread_default_timeout);
172 g_main_context_pop_thread_default (context);
173 g_main_context_unref (context);
177 test2_fail (gpointer user_data)
179 g_assert_not_reached ();
184 main (int argc, char **argv)
186 GError *error = NULL;
189 g_test_init (&argc, &argv, NULL);
191 test_file = g_test_build_filename (G_TEST_DISTED, "contexts.c", NULL);
192 g_file_get_contents (test_file, &test_file_buffer,
193 &test_file_size, &error);
194 g_assert_no_error (error);
196 g_test_add_func ("/gio/contexts/thread-independence", test_thread_independence);
197 g_test_add_func ("/gio/contexts/context-independence", test_context_independence);
201 g_free (test_file_buffer);