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