glib/tests: mainloop - fix a mem leak.
[platform/upstream/glib.git] / glib / tests / mainloop.c
1 /* Unit tests for GMainLoop
2  * Copyright (C) 2011 Red Hat, Inc
3  * Author: Matthias Clasen
4  *
5  * This work is provided "as is"; redistribution and modification
6  * in whole or in part, in any medium, physical or electronic is
7  * permitted without restriction.
8  *
9  * This work is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * In no event shall the authors or contributors be liable for any
14  * direct, indirect, incidental, special, exemplary, or consequential
15  * damages (including, but not limited to, procurement of substitute
16  * goods or services; loss of use, data, or profits; or business
17  * interruption) however caused and on any theory of liability, whether
18  * in contract, strict liability, or tort (including negligence or
19  * otherwise) arising in any way out of the use of this software, even
20  * if advised of the possibility of such damage.
21  */
22
23 #include <glib.h>
24
25 static gboolean cb (gpointer data)
26 {
27   return FALSE;
28 }
29
30 static gboolean prepare (GSource *source, gint *time)
31 {
32   return FALSE;
33 }
34 static gboolean check (GSource *source)
35 {
36   return FALSE;
37 }
38 static gboolean dispatch (GSource *source, GSourceFunc cb, gpointer date)
39 {
40   return FALSE;
41 }
42
43 GSourceFuncs funcs = {
44   prepare,
45   check,
46   dispatch,
47   NULL
48 };
49
50 static void
51 test_maincontext_basic (void)
52 {
53   GMainContext *ctx;
54   GSource *source;
55   guint id;
56   gpointer data = &funcs;
57
58   ctx = g_main_context_new ();
59
60   g_assert (!g_main_context_pending (ctx));
61   g_assert (!g_main_context_iteration (ctx, FALSE));
62
63   source = g_source_new (&funcs, sizeof (GSource));
64   g_assert (g_source_get_priority (source) == G_PRIORITY_DEFAULT);
65   g_assert (!g_source_is_destroyed (source));
66
67   g_assert (!g_source_get_can_recurse (source));
68   g_assert (g_source_get_name (source) == NULL);
69
70   g_source_set_can_recurse (source, TRUE);
71   g_source_set_name (source, "d");
72
73   g_assert (g_source_get_can_recurse (source));
74   g_assert_cmpstr (g_source_get_name (source), ==, "d");
75
76   g_assert (g_main_context_find_source_by_user_data (ctx, NULL) == NULL);
77   g_assert (g_main_context_find_source_by_funcs_user_data (ctx, &funcs, NULL) == NULL);
78
79   id = g_source_attach (source, ctx);
80   g_source_unref (source);
81   g_assert_cmpint (g_source_get_id (source), ==, id);
82   g_assert (g_main_context_find_source_by_id (ctx, id) == source);
83
84   g_source_set_priority (source, G_PRIORITY_HIGH);
85   g_assert (g_source_get_priority (source) == G_PRIORITY_HIGH);
86
87   g_source_destroy (source);
88   g_main_context_unref (ctx);
89
90   ctx = g_main_context_default ();
91   source = g_source_new (&funcs, sizeof (GSource));
92   g_source_set_funcs (source, &funcs);
93   g_source_set_callback (source, cb, data, NULL);
94   id = g_source_attach (source, ctx);
95   g_source_unref (source);
96   g_source_set_name_by_id (id, "e");
97   g_assert_cmpstr (g_source_get_name (source), ==, "e");
98   g_assert (g_source_get_context (source) == ctx);
99   g_assert (g_source_remove_by_funcs_user_data (&funcs, data));
100 }
101
102 static void
103 test_mainloop_basic (void)
104 {
105   GMainLoop *loop;
106   GMainContext *ctx;
107
108   loop = g_main_loop_new (NULL, FALSE);
109
110   g_assert (!g_main_loop_is_running (loop));
111
112   g_main_loop_ref (loop);
113
114   ctx = g_main_loop_get_context (loop);
115   g_assert (ctx == g_main_context_default ());
116
117   g_main_loop_unref (loop);
118
119   g_assert (g_main_depth () == 0);
120
121   g_main_loop_unref (loop);
122 }
123
124 static gint a;
125 static gint b;
126 static gint c;
127
128 static gboolean
129 count_calls (gpointer data)
130 {
131   gint *i = data;
132
133   (*i)++;
134
135   return TRUE;
136 }
137
138 static void
139 test_timeouts (void)
140 {
141   GMainContext *ctx;
142   GMainLoop *loop;
143   GSource *source;
144
145   a = b = c = 0;
146
147   ctx = g_main_context_new ();
148   loop = g_main_loop_new (ctx, FALSE);
149
150   source = g_timeout_source_new (100);
151   g_source_set_callback (source, count_calls, &a, NULL);
152   g_source_attach (source, ctx);
153   g_source_unref (source);
154
155   source = g_timeout_source_new (250);
156   g_source_set_callback (source, count_calls, &b, NULL);
157   g_source_attach (source, ctx);
158   g_source_unref (source);
159
160   source = g_timeout_source_new (330);
161   g_source_set_callback (source, count_calls, &c, NULL);
162   g_source_attach (source, ctx);
163   g_source_unref (source);
164
165   source = g_timeout_source_new (1050);
166   g_source_set_callback (source, (GSourceFunc)g_main_loop_quit, loop, NULL);
167   g_source_attach (source, ctx);
168   g_source_unref (source);
169
170   g_main_loop_run (loop);
171
172   g_assert (a == 10);
173   g_assert (b == 4);
174   g_assert (c == 3);
175
176   g_main_loop_unref (loop);
177   g_main_context_unref (ctx);
178 }
179
180 static void
181 test_priorities (void)
182 {
183   GMainContext *ctx;
184   GSource *sourcea;
185   GSource *sourceb;
186
187   a = b = c = 0;
188
189   ctx = g_main_context_new ();
190
191   sourcea = g_idle_source_new ();
192   g_source_set_callback (sourcea, count_calls, &a, NULL);
193   g_source_set_priority (sourcea, 1);
194   g_source_attach (sourcea, ctx);
195   g_source_unref (sourcea);
196
197   sourceb = g_idle_source_new ();
198   g_source_set_callback (sourceb, count_calls, &b, NULL);
199   g_source_set_priority (sourceb, 0);
200   g_source_attach (sourceb, ctx);
201   g_source_unref (sourceb);
202
203   g_assert (g_main_context_pending (ctx));
204   g_assert (g_main_context_iteration (ctx, FALSE));
205   g_assert (a == 0);
206   g_assert (b == 1);
207
208   g_assert (g_main_context_iteration (ctx, FALSE));
209   g_assert (a == 0);
210   g_assert (b == 2);
211
212   g_source_destroy (sourceb);
213
214   g_assert (g_main_context_iteration (ctx, FALSE));
215   g_assert (a == 1);
216   g_assert (b == 2);
217
218   g_assert (g_main_context_pending (ctx));
219   g_source_destroy (sourcea);
220   g_assert (!g_main_context_pending (ctx));
221
222   g_main_context_unref (ctx);
223 }
224
225 static gint count;
226
227 static gboolean
228 func (gpointer data)
229 {
230   if (data != NULL)
231     g_assert (data == g_thread_self ());
232
233   count++;
234
235   return FALSE;
236 }
237
238 static gboolean
239 call_func (gpointer data)
240 {
241   func (g_thread_self ());
242
243   return G_SOURCE_REMOVE;
244 }
245
246 static gpointer
247 thread_func (gpointer data)
248 {
249   GMainContext *ctx = data;
250   GSource *source;
251
252   g_main_context_push_thread_default (ctx);
253
254   source = g_timeout_source_new (500);
255   g_source_set_callback (source, (GSourceFunc)g_thread_exit, NULL, NULL);
256   g_source_attach (source, ctx);
257   g_source_unref (source);
258
259   while (TRUE)
260     g_main_context_iteration (ctx, TRUE);
261
262   return NULL;
263 }
264
265 static void
266 test_invoke (void)
267 {
268   GMainContext *ctx;
269   GThread *thread;
270
271   count = 0;
272
273   /* this one gets invoked directly */
274   g_main_context_invoke (NULL, func, g_thread_self ());
275   g_assert (count == 1);
276
277   /* invoking out of an idle works too */
278   g_idle_add (call_func, NULL);
279   g_main_context_iteration (g_main_context_default (), FALSE);
280   g_assert (count == 2);
281
282   /* test thread-default forcing the invocation to go
283    * to another thread
284    */
285   ctx = g_main_context_new ();
286   thread = g_thread_new ("worker", thread_func, ctx);
287
288   g_usleep (1000); /* give some time to push the thread-default */
289
290   g_main_context_invoke (ctx, func, thread);
291   g_assert (count == 2);
292
293   g_thread_join (thread);
294   g_assert (count == 3);
295 }
296
297 int
298 main (int argc, char *argv[])
299 {
300   g_test_init (&argc, &argv, NULL);
301
302   g_test_add_func ("/maincontext/basic", test_maincontext_basic);
303   g_test_add_func ("/mainloop/basic", test_mainloop_basic);
304   g_test_add_func ("/mainloop/timeouts", test_timeouts);
305   g_test_add_func ("/mainloop/priorities", test_priorities);
306   g_test_add_func ("/mainloop/invoke", test_invoke);
307
308   return g_test_run ();
309 }