gkdbus: Fix underflow and unreachable code bug
[platform/upstream/glib.git] / gobject / tests / qdata.c
1 /*
2  * Copyright 2012 Red Hat, Inc.
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * See the included COPYING file for more information.
12  */
13
14 #include <glib-object.h>
15
16 gboolean fail;
17
18 #define THREADS 10
19 #define ROUNDS 10000
20
21 GObject *object;
22 gint bucket[THREADS];  /* accessed from multiple threads, but should never be contested due to the sequence of thread operations */
23
24 static gpointer
25 thread_func (gpointer data)
26 {
27   gint idx = GPOINTER_TO_INT (data);
28   gint i;
29   gint d;
30   gint value;
31   gint new_value;
32
33   for (i = 0; i < ROUNDS; i++)
34     {
35       d = g_random_int_range (-10, 100);
36       bucket[idx] += d;
37 retry:
38       value = GPOINTER_TO_INT (g_object_get_data (object, "test"));
39       new_value = value + d;
40       if (fail)
41         g_object_set_data (object, "test", GINT_TO_POINTER (new_value));
42       else
43         {
44           if (!g_object_replace_data (object, "test",
45                                       GINT_TO_POINTER (value),
46                                       GINT_TO_POINTER (new_value),
47                                       NULL, NULL))
48             goto retry;
49         }
50       g_thread_yield ();
51     }
52
53   return NULL;
54 }
55
56 static void
57 test_qdata_threaded (void)
58 {
59   gint sum;
60   gint i;
61   GThread *threads[THREADS];
62   gint result;
63
64   object = g_object_new (G_TYPE_OBJECT, NULL);
65   g_object_set_data (object, "test", GINT_TO_POINTER (0));
66
67   for (i = 0; i < THREADS; i++)
68     bucket[i] = 0;
69
70   for (i = 0; i < THREADS; i++)
71     threads[i] = g_thread_new ("qdata", thread_func, GINT_TO_POINTER (i));
72
73   for (i = 0; i < THREADS; i++)
74     g_thread_join (threads[i]);
75
76   sum = 0;
77   for (i = 0; i < THREADS; i++)
78     sum += bucket[i];
79
80   result = GPOINTER_TO_INT (g_object_get_data (object, "test"));
81
82   g_assert_cmpint (sum, ==, result);
83
84   g_object_unref (object);
85 }
86
87 static void
88 test_qdata_dup (void)
89 {
90   gchar *s, *s2;
91   GQuark quark;
92   gboolean b;
93
94   quark = g_quark_from_static_string ("test");
95   object = g_object_new (G_TYPE_OBJECT, NULL);
96   s = g_strdup ("s");
97   g_object_set_qdata_full (object, quark, s, g_free);
98
99   s2 = g_object_dup_qdata (object, quark, (GDuplicateFunc)g_strdup, NULL);
100
101   g_assert_cmpstr (s, ==, s2);
102   g_assert (s != s2);
103
104   g_free (s2);
105
106   b = g_object_replace_qdata (object, quark, s, "s2", NULL, NULL);
107   g_assert (b);
108
109   g_free (s);
110
111   g_object_unref (object);
112 }
113
114 int
115 main (int argc, char **argv)
116 {
117   g_test_init (&argc, &argv, NULL);
118
119   fail = !!g_getenv ("FAIL");
120
121   g_test_add_func ("/qdata/threaded", test_qdata_threaded);
122   g_test_add_func ("/qdata/dup", test_qdata_dup);
123
124   return g_test_run ();
125 }