Moving files to packaging and extracing new tarball.
[profile/ivi/glib2.git] / glib / tests / private.c
1 /* Unit tests for GPrivate and friends
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 #define GLIB_DISABLE_DEPRECATION_WARNINGS
25
26 #include <glib.h>
27
28 /* test basics:
29  * - initial value is NULL
30  * - set/get work repeatedly
31  */
32 static void
33 test_private1 (void)
34 {
35   GPrivate *private1;
36   gpointer value;
37
38   private1 = g_private_new (NULL);
39
40   value = g_private_get (private1);
41   g_assert (value == NULL);
42
43   g_private_set (private1, GINT_TO_POINTER(1));
44   value = g_private_get (private1);
45   g_assert_cmpint (GPOINTER_TO_INT (value), ==, 1);
46
47   g_private_set (private1, GINT_TO_POINTER(2));
48   value = g_private_get (private1);
49   g_assert_cmpint (GPOINTER_TO_INT (value), ==, 2);
50 }
51
52 static GPrivate *private2;
53 static gint private2_destroy_count;
54
55 static void
56 private2_destroy (gpointer data)
57 {
58   g_atomic_int_inc (&private2_destroy_count);
59 }
60
61 static gpointer
62 private2_func (gpointer data)
63 {
64   gint value = GPOINTER_TO_INT (data);
65   gint i;
66   gint v, v2;
67
68   for (i = 0; i < 1000; i++)
69     {
70       v = value + (i % 5);
71       g_private_set (private2, GINT_TO_POINTER(v));
72       g_usleep (1000);
73       v2 = GPOINTER_TO_INT(g_private_get (private2));
74       g_assert_cmpint (v, ==, v2);
75     }
76
77   if (value % 2 == 0)
78     g_thread_exit (NULL);
79
80   return NULL;
81 }
82
83 /* test that
84  * - threads do not interfere with each other
85  * - destroy notifies are called for each thread exit
86  * - destroy notifies are called for g_thread_exit() too
87  * - destroy notifies are not called on g_private_set()
88  */
89 static void
90 test_private2 (void)
91 {
92   GThread *thread[10];
93   gint i;
94
95   private2 = g_private_new (private2_destroy);
96
97   for (i = 0; i < 10; i++)
98     thread[i] = g_thread_create (private2_func, GINT_TO_POINTER (i), TRUE, NULL);
99
100   for (i = 0; i < 10; i++)
101     g_thread_join (thread[i]);
102
103   g_assert_cmpint (private2_destroy_count, ==, 10);
104 }
105
106 static gboolean private3_freed;
107
108 static void
109 private3_free (gpointer data)
110 {
111   g_assert (data == (void*) 0x1234);
112   private3_freed = TRUE;
113 }
114
115 #ifdef G_OS_WIN32
116 #include <windows.h>
117 #include <process.h>
118
119 static guint __stdcall
120 #else
121 #include <pthread.h>
122
123 static gpointer
124 #endif
125 private3_func (gpointer data)
126 {
127   static GPrivate key = G_PRIVATE_INIT (private3_free);
128
129   g_private_set (&key, (void *) 0x1234);
130
131   return 0;
132 }
133
134 static void
135 test_private3 (void)
136 {
137   g_assert (!private3_freed);
138
139 #ifdef G_OS_WIN32
140   {
141     HANDLE thread;
142     guint ignore;
143     thread = (HANDLE) _beginthreadex (NULL, 0, private3_func, NULL, 0, &ignore);
144     WaitForSingleObject (thread, INFINITE);
145     CloseHandle (thread);
146   }
147 #else
148   {
149     pthread_t thread;
150
151     pthread_create (&thread, NULL, private3_func, NULL);
152     pthread_join (thread, NULL);
153   }
154 #endif
155   g_assert (private3_freed);
156 }
157
158 /* test basics:
159  * - static initialization works
160  * - initial value is NULL
161  * - get/set works repeatedly
162  */
163 static GStaticPrivate sp1 = G_STATIC_PRIVATE_INIT;
164
165 static void
166 test_static_private1 (void)
167 {
168   gpointer value;
169
170   value = g_static_private_get (&sp1);
171   g_assert (value == NULL);
172
173   g_static_private_set (&sp1, GINT_TO_POINTER(1), NULL);
174   value = g_static_private_get (&sp1);
175   g_assert_cmpint (GPOINTER_TO_INT(value), ==, 1);
176
177   g_static_private_set (&sp1, GINT_TO_POINTER(2), NULL);
178   value = g_static_private_get (&sp1);
179   g_assert_cmpint (GPOINTER_TO_INT(value), ==, 2);
180
181   g_static_private_free (&sp1);
182
183   value = g_static_private_get (&sp1);
184   g_assert (value == NULL);
185 }
186
187 static gint sp2_destroy_count;
188
189 static void
190 sp2_destroy (gpointer data)
191 {
192   sp2_destroy_count++;
193 }
194
195 static void
196 sp2_destroy2 (gpointer data)
197 {
198   gint value = GPOINTER_TO_INT (data);
199
200   g_assert_cmpint (value, ==, 2);
201 }
202
203 /* test that destroy notifies are called as expected
204  * and on the right values
205  */
206 static void
207 test_static_private2 (void)
208 {
209   GStaticPrivate sp2;
210   gpointer value;
211
212   g_static_private_init (&sp2);
213
214   value = g_static_private_get (&sp2);
215   g_assert (value == NULL);
216
217   g_static_private_set (&sp2, GINT_TO_POINTER(1), sp2_destroy);
218   g_assert_cmpint (sp2_destroy_count, ==, 0);
219   value = g_static_private_get (&sp2);
220   g_assert_cmpint (GPOINTER_TO_INT(value), ==, 1);
221
222   g_static_private_set (&sp2, GINT_TO_POINTER(2), sp2_destroy2);
223   g_assert_cmpint (sp2_destroy_count, ==, 1);
224   value = g_static_private_get (&sp2);
225   g_assert_cmpint (GPOINTER_TO_INT(value), ==, 2);
226
227   g_static_private_set (&sp2, GINT_TO_POINTER(3), sp2_destroy);
228   g_assert_cmpint (sp2_destroy_count, ==, 1);
229   value = g_static_private_get (&sp2);
230   g_assert_cmpint (GPOINTER_TO_INT(value), ==, 3);
231
232   g_static_private_free (&sp2);
233
234   value = g_static_private_get (&sp2);
235   g_assert (value == NULL);
236 }
237
238 /* test that freeing and reinitializing a static private
239  * drops previous value
240  */
241 static void
242 test_static_private3 (void)
243 {
244   GStaticPrivate sp3;
245   gpointer value;
246
247   g_static_private_init (&sp3);
248
249   value = g_static_private_get (&sp3);
250   g_assert (value == NULL);
251
252   g_static_private_set (&sp3, GINT_TO_POINTER(1), NULL);
253   value = g_static_private_get (&sp3);
254   g_assert_cmpint (GPOINTER_TO_INT(value), ==, 1);
255
256   g_static_private_free (&sp3);
257   g_static_private_init (&sp3);
258
259   value = g_static_private_get (&sp3);
260   g_assert (value == NULL);
261
262   g_static_private_set (&sp3, GINT_TO_POINTER(2), NULL);
263   value = g_static_private_get (&sp3);
264   g_assert_cmpint (GPOINTER_TO_INT(value), ==, 2);
265
266   g_static_private_free (&sp3);
267 }
268
269 static GStaticPrivate sp4 = G_STATIC_PRIVATE_INIT;
270
271 static gpointer
272 sp4_func (gpointer data)
273 {
274   gint value = GPOINTER_TO_INT (data);
275   gint i;
276   gint v, v2;
277
278   for (i = 0; i < 1000; i++)
279     {
280       v = value + (i % 5);
281       g_static_private_set (&sp4, GINT_TO_POINTER(v), NULL);
282       g_usleep (1000);
283       v2 = GPOINTER_TO_INT(g_static_private_get (&sp4));
284       g_assert_cmpint (v, ==, v2);
285     }
286
287   if (value % 2 == 0)
288     g_thread_exit (NULL);
289
290   return NULL;
291 }
292
293 /* test that threads do not interfere with each other
294  */
295 static void
296 test_static_private4 (void)
297 {
298   GThread *thread[10];
299   gint i;
300
301   for (i = 0; i < 10; i++)
302     thread[i] = g_thread_create (sp4_func, GINT_TO_POINTER (i), TRUE, NULL);
303
304   for (i = 0; i < 10; i++)
305     g_thread_join (thread[i]);
306
307   g_static_private_free (&sp4);
308 }
309
310 static GStaticPrivate sp5 = G_STATIC_PRIVATE_INIT;
311 static GMutex m5;
312 static GCond c5a;
313 static GCond c5b;
314 static gint count5;
315
316 static gpointer
317 sp5_func (gpointer data)
318 {
319   gint v = GPOINTER_TO_INT (data);
320   gpointer value;
321
322   value = g_static_private_get (&sp5);
323   g_assert (value == NULL);
324
325   g_static_private_set (&sp5, GINT_TO_POINTER (v), NULL);
326   value = g_static_private_get (&sp5);
327   g_assert_cmpint (GPOINTER_TO_INT (value), ==, v);
328
329   if (g_test_verbose ())
330     g_print ("thread %d set sp5\n", v);
331   g_mutex_lock (&m5);
332   g_atomic_int_inc (&count5);
333   g_cond_signal (&c5a);
334   g_cond_wait (&c5b, &m5);
335   g_mutex_unlock (&m5);
336
337   if (g_test_verbose ())
338     g_print ("thread %d get sp5\n", v);
339   value = g_static_private_get (&sp5);
340   g_assert (value == NULL);
341
342   return NULL;
343 }
344
345 static void
346 test_static_private5 (void)
347 {
348   GThread *thread[10];
349   gint i;
350
351   g_atomic_int_set (&count5, 0);
352
353   for (i = 0; i < 10; i++)
354     thread[i] = g_thread_create (sp5_func, GINT_TO_POINTER (i), TRUE, NULL);
355
356   g_mutex_lock (&m5);
357   while (g_atomic_int_get (&count5) < 10)
358     g_cond_wait (&c5a, &m5);
359
360   if (g_test_verbose ())
361     g_print ("sp5 gets nuked\n");
362
363   g_static_private_free (&sp5);
364
365   g_cond_broadcast (&c5b);
366   g_mutex_unlock (&m5);
367
368   for (i = 0; i < 10; i++)
369     g_thread_join (thread[i]);
370
371   g_mutex_clear (&m5);
372   g_cond_clear (&c5a);
373   g_cond_clear (&c5b);
374 }
375
376 int
377 main (int argc, char *argv[])
378 {
379   g_test_init (&argc, &argv, NULL);
380
381   g_test_add_func ("/thread/private1", test_private1);
382   g_test_add_func ("/thread/private2", test_private2);
383   g_test_add_func ("/thread/private3", test_private3);
384   g_test_add_func ("/thread/staticprivate1", test_static_private1);
385   g_test_add_func ("/thread/staticprivate2", test_static_private2);
386   g_test_add_func ("/thread/staticprivate3", test_static_private3);
387   g_test_add_func ("/thread/staticprivate4", test_static_private4);
388   g_test_add_func ("/thread/staticprivate5", test_static_private5);
389
390   return g_test_run ();
391 }