Branch data Line data Source code
1 : : /* Unit tests for GPrivate and friends
2 : : * Copyright (C) 2011 Red Hat, Inc
3 : : * Author: Matthias Clasen
4 : : *
5 : : * SPDX-License-Identifier: LicenseRef-old-glib-tests
6 : : *
7 : : * This work is provided "as is"; redistribution and modification
8 : : * in whole or in part, in any medium, physical or electronic is
9 : : * permitted without restriction.
10 : : *
11 : : * This work is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 : : *
15 : : * In no event shall the authors or contributors be liable for any
16 : : * direct, indirect, incidental, special, exemplary, or consequential
17 : : * damages (including, but not limited to, procurement of substitute
18 : : * goods or services; loss of use, data, or profits; or business
19 : : * interruption) however caused and on any theory of liability, whether
20 : : * in contract, strict liability, or tort (including negligence or
21 : : * otherwise) arising in any way out of the use of this software, even
22 : : * if advised of the possibility of such damage.
23 : : */
24 : :
25 : : /* We are testing some deprecated APIs here */
26 : : #ifndef GLIB_DISABLE_DEPRECATION_WARNINGS
27 : : #define GLIB_DISABLE_DEPRECATION_WARNINGS
28 : : #endif
29 : :
30 : : #include <glib.h>
31 : :
32 : : /* test basics:
33 : : * - initial value is NULL
34 : : * - set/get work repeatedly
35 : : */
36 : : static void
37 : 1 : test_private1 (void)
38 : : {
39 : : static GPrivate private = G_PRIVATE_INIT (NULL);
40 : : gpointer value;
41 : :
42 : 1 : value = g_private_get (&private);
43 : 1 : g_assert (value == NULL);
44 : :
45 : 1 : g_private_set (&private, GINT_TO_POINTER(1));
46 : 1 : value = g_private_get (&private);
47 : 1 : g_assert_cmpint (GPOINTER_TO_INT (value), ==, 1);
48 : :
49 : 1 : g_private_set (&private, GINT_TO_POINTER(2));
50 : 1 : value = g_private_get (&private);
51 : 1 : g_assert_cmpint (GPOINTER_TO_INT (value), ==, 2);
52 : 1 : }
53 : :
54 : : static gint private2_destroy_count;
55 : :
56 : : static void
57 : 11 : private2_destroy (gpointer data)
58 : : {
59 : 11 : g_atomic_int_inc (&private2_destroy_count);
60 : 11 : }
61 : :
62 : : static GPrivate private2 = G_PRIVATE_INIT (private2_destroy);
63 : :
64 : : static gpointer
65 : 10 : private2_func (gpointer data)
66 : : {
67 : 10 : gint value = GPOINTER_TO_INT (data);
68 : : gint i;
69 : : gint v, v2;
70 : :
71 [ + + ]: 10010 : for (i = 0; i < 1000; i++)
72 : : {
73 : 10000 : v = value + (i % 5);
74 : 10000 : g_private_set (&private2, GINT_TO_POINTER (v));
75 : 10000 : g_usleep (1000);
76 : 10000 : v2 = GPOINTER_TO_INT (g_private_get (&private2));
77 : 10000 : g_assert_cmpint (v, ==, v2);
78 : : }
79 : :
80 [ + + ]: 10 : if (value % 2 == 0)
81 : 5 : g_thread_exit (NULL);
82 : :
83 : 5 : return NULL;
84 : : }
85 : :
86 : : /* test that
87 : : * - threads do not interfere with each other
88 : : * - destroy notifies are called for each thread exit
89 : : * - destroy notifies are called for g_thread_exit() too
90 : : * - destroy notifies are not called on g_private_set()
91 : : * - destroy notifies are called on g_private_replace()
92 : : */
93 : : static void
94 : 1 : test_private2 (void)
95 : : {
96 : : GThread *thread[10];
97 : : gint i;
98 : :
99 : 1 : g_private_set (&private2, GINT_TO_POINTER (234));
100 : 1 : g_private_replace (&private2, GINT_TO_POINTER (123));
101 : :
102 [ + + ]: 11 : for (i = 0; i < 10; i++)
103 : 10 : thread[i] = g_thread_create (private2_func, GINT_TO_POINTER (i), TRUE, NULL);
104 : :
105 [ + + ]: 11 : for (i = 0; i < 10; i++)
106 : 10 : g_thread_join (thread[i]);
107 : :
108 : 1 : g_assert_cmpint (private2_destroy_count, ==, 11);
109 : 1 : }
110 : :
111 : : static gboolean private3_freed;
112 : :
113 : : static void
114 : 1 : private3_free (gpointer data)
115 : : {
116 : 1 : g_assert (data == (void*) 0x1234);
117 : 1 : private3_freed = TRUE;
118 : 1 : }
119 : :
120 : : #ifdef G_OS_WIN32
121 : : #include <windows.h>
122 : : #include <process.h>
123 : :
124 : : static guint __stdcall
125 : : #else
126 : : #include <pthread.h>
127 : :
128 : : static gpointer
129 : : #endif
130 : 1 : private3_func (gpointer data)
131 : : {
132 : : static GPrivate key = G_PRIVATE_INIT (private3_free);
133 : :
134 : 1 : g_private_set (&key, (void *) 0x1234);
135 : :
136 : 1 : return 0;
137 : : }
138 : :
139 : : static void
140 : 1 : test_private3 (void)
141 : : {
142 : 1 : g_assert (!private3_freed);
143 : :
144 : : #ifdef G_OS_WIN32
145 : : {
146 : : HANDLE thread;
147 : : guint ignore;
148 : : thread = (HANDLE) _beginthreadex (NULL, 0, private3_func, NULL, 0, &ignore);
149 : : WaitForSingleObject (thread, INFINITE);
150 : : CloseHandle (thread);
151 : : }
152 : : #else
153 : : {
154 : : pthread_t thread;
155 : :
156 : 1 : pthread_create (&thread, NULL, private3_func, NULL);
157 : 1 : pthread_join (thread, NULL);
158 : : }
159 : : #endif
160 : 1 : g_assert (private3_freed);
161 : 1 : }
162 : :
163 : : /* test basics:
164 : : * - static initialization works
165 : : * - initial value is NULL
166 : : * - get/set works repeatedly
167 : : */
168 : : static GStaticPrivate sp1 = G_STATIC_PRIVATE_INIT;
169 : :
170 : : static void
171 : 1 : test_static_private1 (void)
172 : : {
173 : : gpointer value;
174 : :
175 : 1 : value = g_static_private_get (&sp1);
176 : 1 : g_assert (value == NULL);
177 : :
178 : 1 : g_static_private_set (&sp1, GINT_TO_POINTER(1), NULL);
179 : 1 : value = g_static_private_get (&sp1);
180 : 1 : g_assert_cmpint (GPOINTER_TO_INT(value), ==, 1);
181 : :
182 : 1 : g_static_private_set (&sp1, GINT_TO_POINTER(2), NULL);
183 : 1 : value = g_static_private_get (&sp1);
184 : 1 : g_assert_cmpint (GPOINTER_TO_INT(value), ==, 2);
185 : :
186 : 1 : g_static_private_free (&sp1);
187 : :
188 : 1 : value = g_static_private_get (&sp1);
189 : 1 : g_assert (value == NULL);
190 : 1 : }
191 : :
192 : : static gint sp2_destroy_count;
193 : :
194 : : static void
195 : 2 : sp2_destroy (gpointer data)
196 : : {
197 : 2 : sp2_destroy_count++;
198 : 2 : }
199 : :
200 : : static void
201 : 1 : sp2_destroy2 (gpointer data)
202 : : {
203 : 1 : gint value = GPOINTER_TO_INT (data);
204 : :
205 : 1 : g_assert_cmpint (value, ==, 2);
206 : 1 : }
207 : :
208 : : /* test that destroy notifies are called as expected
209 : : * and on the right values
210 : : */
211 : : static void
212 : 1 : test_static_private2 (void)
213 : : {
214 : : GStaticPrivate sp2;
215 : : gpointer value;
216 : :
217 : 1 : g_static_private_init (&sp2);
218 : :
219 : 1 : value = g_static_private_get (&sp2);
220 : 1 : g_assert (value == NULL);
221 : :
222 : 1 : g_static_private_set (&sp2, GINT_TO_POINTER(1), sp2_destroy);
223 : 1 : g_assert_cmpint (sp2_destroy_count, ==, 0);
224 : 1 : value = g_static_private_get (&sp2);
225 : 1 : g_assert_cmpint (GPOINTER_TO_INT(value), ==, 1);
226 : :
227 : 1 : g_static_private_set (&sp2, GINT_TO_POINTER(2), sp2_destroy2);
228 : 1 : g_assert_cmpint (sp2_destroy_count, ==, 1);
229 : 1 : value = g_static_private_get (&sp2);
230 : 1 : g_assert_cmpint (GPOINTER_TO_INT(value), ==, 2);
231 : :
232 : 1 : g_static_private_set (&sp2, GINT_TO_POINTER(3), sp2_destroy);
233 : 1 : g_assert_cmpint (sp2_destroy_count, ==, 1);
234 : 1 : value = g_static_private_get (&sp2);
235 : 1 : g_assert_cmpint (GPOINTER_TO_INT(value), ==, 3);
236 : :
237 : 1 : g_static_private_free (&sp2);
238 : :
239 : 1 : value = g_static_private_get (&sp2);
240 : 1 : g_assert (value == NULL);
241 : 1 : }
242 : :
243 : : /* test that freeing and reinitializing a static private
244 : : * drops previous value
245 : : */
246 : : static void
247 : 1 : test_static_private3 (void)
248 : : {
249 : : GStaticPrivate sp3;
250 : : gpointer value;
251 : :
252 : 1 : g_static_private_init (&sp3);
253 : :
254 : 1 : value = g_static_private_get (&sp3);
255 : 1 : g_assert (value == NULL);
256 : :
257 : 1 : g_static_private_set (&sp3, GINT_TO_POINTER(1), NULL);
258 : 1 : value = g_static_private_get (&sp3);
259 : 1 : g_assert_cmpint (GPOINTER_TO_INT(value), ==, 1);
260 : :
261 : 1 : g_static_private_free (&sp3);
262 : 1 : g_static_private_init (&sp3);
263 : :
264 : 1 : value = g_static_private_get (&sp3);
265 : 1 : g_assert (value == NULL);
266 : :
267 : 1 : g_static_private_set (&sp3, GINT_TO_POINTER(2), NULL);
268 : 1 : value = g_static_private_get (&sp3);
269 : 1 : g_assert_cmpint (GPOINTER_TO_INT(value), ==, 2);
270 : :
271 : 1 : g_static_private_free (&sp3);
272 : 1 : }
273 : :
274 : : static GStaticPrivate sp4 = G_STATIC_PRIVATE_INIT;
275 : :
276 : : static gpointer
277 : 10 : sp4_func (gpointer data)
278 : : {
279 : 10 : gint value = GPOINTER_TO_INT (data);
280 : : gint i;
281 : : gint v, v2;
282 : :
283 [ + + ]: 10010 : for (i = 0; i < 1000; i++)
284 : : {
285 : 10000 : v = value + (i % 5);
286 : 10000 : g_static_private_set (&sp4, GINT_TO_POINTER(v), NULL);
287 : 10000 : g_usleep (1000);
288 : 10000 : v2 = GPOINTER_TO_INT(g_static_private_get (&sp4));
289 : 10000 : g_assert_cmpint (v, ==, v2);
290 : : }
291 : :
292 [ + + ]: 10 : if (value % 2 == 0)
293 : 5 : g_thread_exit (NULL);
294 : :
295 : 5 : return NULL;
296 : : }
297 : :
298 : : /* test that threads do not interfere with each other
299 : : */
300 : : static void
301 : 1 : test_static_private4 (void)
302 : : {
303 : : GThread *thread[10];
304 : : gint i;
305 : :
306 [ + + ]: 11 : for (i = 0; i < 10; i++)
307 : 10 : thread[i] = g_thread_create (sp4_func, GINT_TO_POINTER (i), TRUE, NULL);
308 : :
309 [ + + ]: 11 : for (i = 0; i < 10; i++)
310 : 10 : g_thread_join (thread[i]);
311 : :
312 : 1 : g_static_private_free (&sp4);
313 : 1 : }
314 : :
315 : : static GStaticPrivate sp5 = G_STATIC_PRIVATE_INIT;
316 : : static GMutex m5;
317 : : static GCond c5a;
318 : : static GCond c5b;
319 : : static gint count5;
320 : :
321 : : static gpointer
322 : 10 : sp5_func (gpointer data)
323 : : {
324 : 10 : gint v = GPOINTER_TO_INT (data);
325 : : gpointer value;
326 : :
327 : 10 : value = g_static_private_get (&sp5);
328 : 10 : g_assert (value == NULL);
329 : :
330 : 10 : g_static_private_set (&sp5, GINT_TO_POINTER (v), NULL);
331 : 10 : value = g_static_private_get (&sp5);
332 : 10 : g_assert_cmpint (GPOINTER_TO_INT (value), ==, v);
333 : :
334 [ - + ]: 10 : if (g_test_verbose ())
335 : 0 : g_printerr ("thread %d set sp5\n", v);
336 : 10 : g_mutex_lock (&m5);
337 : 10 : g_atomic_int_inc (&count5);
338 : 10 : g_cond_signal (&c5a);
339 : 10 : g_cond_wait (&c5b, &m5);
340 : 10 : g_mutex_unlock (&m5);
341 : :
342 [ - + ]: 10 : if (g_test_verbose ())
343 : 0 : g_printerr ("thread %d get sp5\n", v);
344 : 10 : value = g_static_private_get (&sp5);
345 : 10 : g_assert (value == NULL);
346 : :
347 : 10 : return NULL;
348 : : }
349 : :
350 : : static void
351 : 1 : test_static_private5 (void)
352 : : {
353 : : GThread *thread[10];
354 : : gint i;
355 : :
356 : 1 : g_atomic_int_set (&count5, 0);
357 : :
358 [ + + ]: 11 : for (i = 0; i < 10; i++)
359 : 10 : thread[i] = g_thread_create (sp5_func, GINT_TO_POINTER (i), TRUE, NULL);
360 : :
361 : 1 : g_mutex_lock (&m5);
362 [ + + ]: 2 : while (g_atomic_int_get (&count5) < 10)
363 : 1 : g_cond_wait (&c5a, &m5);
364 : :
365 [ - + ]: 1 : if (g_test_verbose ())
366 : 0 : g_printerr ("sp5 gets nuked\n");
367 : :
368 : 1 : g_static_private_free (&sp5);
369 : :
370 : 1 : g_cond_broadcast (&c5b);
371 : 1 : g_mutex_unlock (&m5);
372 : :
373 [ + + ]: 11 : for (i = 0; i < 10; i++)
374 : 10 : g_thread_join (thread[i]);
375 : 1 : }
376 : :
377 : : int
378 : 1 : main (int argc, char *argv[])
379 : : {
380 : 1 : g_test_init (&argc, &argv, NULL);
381 : :
382 : 1 : g_test_add_func ("/thread/private1", test_private1);
383 : 1 : g_test_add_func ("/thread/private2", test_private2);
384 : 1 : g_test_add_func ("/thread/private3", test_private3);
385 : 1 : g_test_add_func ("/thread/staticprivate1", test_static_private1);
386 : 1 : g_test_add_func ("/thread/staticprivate2", test_static_private2);
387 : 1 : g_test_add_func ("/thread/staticprivate3", test_static_private3);
388 : 1 : g_test_add_func ("/thread/staticprivate4", test_static_private4);
389 : 1 : g_test_add_func ("/thread/staticprivate5", test_static_private5);
390 : :
391 : 1 : return g_test_run ();
392 : : }
|