1/* Unit tests for GAsyncQueue
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/* We are testing some deprecated APIs here */
24#ifndef GLIB_DISABLE_DEPRECATION_WARNINGS
25#define GLIB_DISABLE_DEPRECATION_WARNINGS
26#endif
27
28#include <glib.h>
29
30static gint
31compare_func (gconstpointer d1, gconstpointer d2, gpointer data)
32{
33 gint i1, i2;
34
35 i1 = GPOINTER_TO_INT (d1);
36 i2 = GPOINTER_TO_INT (d2);
37
38 return i1 - i2;
39}
40
41static
42void test_async_queue_sort (void)
43{
44 GAsyncQueue *q;
45
46 q = g_async_queue_new ();
47
48 g_async_queue_push (queue: q, GINT_TO_POINTER (10));
49 g_async_queue_push (queue: q, GINT_TO_POINTER (2));
50 g_async_queue_push (queue: q, GINT_TO_POINTER (7));
51
52 g_async_queue_sort (queue: q, func: compare_func, NULL);
53
54 g_async_queue_push_sorted (queue: q, GINT_TO_POINTER (1), func: compare_func, NULL);
55 g_async_queue_push_sorted (queue: q, GINT_TO_POINTER (8), func: compare_func, NULL);
56
57 g_assert_cmpint (GPOINTER_TO_INT (g_async_queue_pop (q)), ==, 1);
58 g_assert_cmpint (GPOINTER_TO_INT (g_async_queue_pop (q)), ==, 2);
59 g_assert_cmpint (GPOINTER_TO_INT (g_async_queue_pop (q)), ==, 7);
60 g_assert_cmpint (GPOINTER_TO_INT (g_async_queue_pop (q)), ==, 8);
61 g_assert_cmpint (GPOINTER_TO_INT (g_async_queue_pop (q)), ==, 10);
62
63 g_assert_null (g_async_queue_try_pop (q));
64
65 g_async_queue_unref (queue: q);
66}
67
68static gint destroy_count;
69
70static void
71destroy_notify (gpointer item)
72{
73 destroy_count++;
74}
75
76static void
77test_async_queue_destroy (void)
78{
79 GAsyncQueue *q;
80
81 q = g_async_queue_new_full (item_free_func: destroy_notify);
82
83 g_assert_cmpint (destroy_count, ==, 0);
84
85 g_async_queue_push (queue: q, GINT_TO_POINTER (1));
86 g_async_queue_push (queue: q, GINT_TO_POINTER (1));
87 g_async_queue_push (queue: q, GINT_TO_POINTER (1));
88 g_async_queue_push (queue: q, GINT_TO_POINTER (1));
89
90 g_assert_cmpint (g_async_queue_length (q), ==, 4);
91
92 g_async_queue_unref (queue: q);
93
94 g_assert_cmpint (destroy_count, ==, 4);
95}
96
97static GAsyncQueue *q;
98
99static GThread *threads[10];
100static gint counts[10];
101static gint sums[10];
102static gint total;
103
104static gpointer
105thread_func (gpointer data)
106{
107 gint pos = GPOINTER_TO_INT (data);
108 gint value;
109
110 while (1)
111 {
112 value = GPOINTER_TO_INT (g_async_queue_pop (q));
113
114 if (value == -1)
115 break;
116
117 counts[pos]++;
118 sums[pos] += value;
119
120 g_usleep (microseconds: 1000);
121 }
122
123 return NULL;
124}
125
126static void
127test_async_queue_threads (void)
128{
129 gint i, j;
130 gint s, c;
131 gint value;
132
133 q = g_async_queue_new ();
134
135 for (i = 0; i < 10; i++)
136 threads[i] = g_thread_new (name: "test", func: thread_func, GINT_TO_POINTER (i));
137
138 for (i = 0; i < 100; i++)
139 {
140 g_async_queue_lock (queue: q);
141 for (j = 0; j < 10; j++)
142 {
143 value = g_random_int_range (begin: 1, end: 100);
144 total += value;
145 g_async_queue_push_unlocked (queue: q, GINT_TO_POINTER (value));
146 }
147 g_async_queue_unlock (queue: q);
148
149 g_usleep (microseconds: 1000);
150 }
151
152 for (i = 0; i < 10; i++)
153 g_async_queue_push (queue: q, GINT_TO_POINTER(-1));
154
155 for (i = 0; i < 10; i++)
156 g_thread_join (thread: threads[i]);
157
158 g_assert_cmpint (g_async_queue_length (q), ==, 0);
159
160 s = c = 0;
161
162 for (i = 0; i < 10; i++)
163 {
164 g_assert_cmpint (sums[i], >, 0);
165 g_assert_cmpint (counts[i], >, 0);
166 s += sums[i];
167 c += counts[i];
168 }
169
170 g_assert_cmpint (s, ==, total);
171 g_assert_cmpint (c, ==, 1000);
172
173 g_async_queue_unref (queue: q);
174}
175
176static void
177test_async_queue_timed (void)
178{
179 GAsyncQueue *q;
180 GTimeVal tv;
181 gint64 start, end, diff;
182 gpointer val;
183
184 q = g_async_queue_new ();
185
186 start = g_get_monotonic_time ();
187 val = g_async_queue_timeout_pop (queue: q, G_USEC_PER_SEC / 10);
188 g_assert_null (val);
189
190 end = g_get_monotonic_time ();
191 diff = end - start;
192 g_assert_cmpint (diff, >=, G_USEC_PER_SEC / 10);
193 /* diff should be only a little bit more than G_USEC_PER_SEC/10, but
194 * we have to leave some wiggle room for heavily-loaded machines...
195 */
196 g_assert_cmpint (diff, <, 2 * G_USEC_PER_SEC);
197
198 start = end;
199 g_get_current_time (result: &tv);
200 g_time_val_add (time_: &tv, G_USEC_PER_SEC / 10);
201 val = g_async_queue_timed_pop (queue: q, end_time: &tv);
202 g_assert_null (val);
203
204 end = g_get_monotonic_time ();
205 diff = end - start;
206 g_assert_cmpint (diff, >=, G_USEC_PER_SEC / 10);
207 g_assert_cmpint (diff, <, 2 * G_USEC_PER_SEC);
208
209 start = end;
210 g_get_current_time (result: &tv);
211 g_time_val_add (time_: &tv, G_USEC_PER_SEC / 10);
212 g_async_queue_lock (queue: q);
213 val = g_async_queue_timed_pop_unlocked (queue: q, end_time: &tv);
214 g_async_queue_unlock (queue: q);
215 g_assert_null (val);
216
217 end = g_get_monotonic_time ();
218 diff = end - start;
219 g_assert_cmpint (diff, >=, G_USEC_PER_SEC / 10);
220 g_assert_cmpint (diff, <, 2 * G_USEC_PER_SEC);
221
222 g_async_queue_unref (queue: q);
223}
224
225static void
226test_async_queue_remove (void)
227{
228 GAsyncQueue *q;
229
230 q = g_async_queue_new ();
231
232 g_async_queue_push (queue: q, GINT_TO_POINTER (10));
233 g_async_queue_push (queue: q, GINT_TO_POINTER (2));
234 g_async_queue_push (queue: q, GINT_TO_POINTER (7));
235 g_async_queue_push (queue: q, GINT_TO_POINTER (1));
236
237 g_async_queue_remove (queue: q, GINT_TO_POINTER (7));
238
239 g_assert_cmpint (GPOINTER_TO_INT (g_async_queue_pop (q)), ==, 10);
240 g_assert_cmpint (GPOINTER_TO_INT (g_async_queue_pop (q)), ==, 2);
241 g_assert_cmpint (GPOINTER_TO_INT (g_async_queue_pop (q)), ==, 1);
242
243 g_assert_null (g_async_queue_try_pop (q));
244
245 g_async_queue_unref (queue: q);
246}
247
248static void
249test_async_queue_push_front (void)
250{
251 GAsyncQueue *q;
252
253 q = g_async_queue_new ();
254
255 g_async_queue_push (queue: q, GINT_TO_POINTER (10));
256 g_async_queue_push (queue: q, GINT_TO_POINTER (2));
257 g_async_queue_push (queue: q, GINT_TO_POINTER (7));
258
259 g_async_queue_push_front (queue: q, GINT_TO_POINTER (1));
260
261 g_assert_cmpint (GPOINTER_TO_INT (g_async_queue_pop (q)), ==, 1);
262 g_assert_cmpint (GPOINTER_TO_INT (g_async_queue_pop (q)), ==, 10);
263 g_assert_cmpint (GPOINTER_TO_INT (g_async_queue_pop (q)), ==, 2);
264 g_assert_cmpint (GPOINTER_TO_INT (g_async_queue_pop (q)), ==, 7);
265
266 g_assert_null (g_async_queue_try_pop (q));
267
268 g_async_queue_unref (queue: q);
269}
270
271int
272main (int argc, char *argv[])
273{
274 g_test_init (argc: &argc, argv: &argv, NULL);
275
276 g_test_add_func (testpath: "/asyncqueue/sort", test_func: test_async_queue_sort);
277 g_test_add_func (testpath: "/asyncqueue/destroy", test_func: test_async_queue_destroy);
278 g_test_add_func (testpath: "/asyncqueue/threads", test_func: test_async_queue_threads);
279 g_test_add_func (testpath: "/asyncqueue/timed", test_func: test_async_queue_timed);
280 g_test_add_func (testpath: "/asyncqueue/remove", test_func: test_async_queue_remove);
281 g_test_add_func (testpath: "/asyncqueue/push_front", test_func: test_async_queue_push_front);
282
283 return g_test_run ();
284}
285

source code of gtk/subprojects/glib/glib/tests/asyncqueue.c