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 | |
30 | static gint |
31 | compare_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 | |
41 | static |
42 | void 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 | |
68 | static gint destroy_count; |
69 | |
70 | static void |
71 | destroy_notify (gpointer item) |
72 | { |
73 | destroy_count++; |
74 | } |
75 | |
76 | static void |
77 | test_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 | |
97 | static GAsyncQueue *q; |
98 | |
99 | static GThread *threads[10]; |
100 | static gint counts[10]; |
101 | static gint sums[10]; |
102 | static gint total; |
103 | |
104 | static gpointer |
105 | thread_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 | |
126 | static void |
127 | test_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 | |
176 | static void |
177 | test_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 | |
225 | static void |
226 | test_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 | |
248 | static void |
249 | test_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 | |
271 | int |
272 | main (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 | |