1 /* refcount.c: Tests for reference counting types
2 *
3 * Copyright 2018 Emmanuele Bassi
4 *
5 * SPDX-License-Identifier: LGPL-2.1-or-later
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <stdlib.h>
22 #include <glib.h>
23
24 /* test_grefcount: test the behavior of the grefcount API */
25 static void
26 test_grefcount (void)
27 {
28 grefcount a, b;
29
30 /* init(a): 1 */
31 g_ref_count_init (&a);
32 if (g_test_verbose ())
33 g_test_message ("init(a) := %d\n", (int) a);
34 g_assert_true (g_ref_count_compare (&a, 1));
35
36 /* inc(a): 2 */
37 g_ref_count_inc (&a);
38 if (g_test_verbose ())
39 g_test_message ("inc(a) := %d\n", (int) a);
40 g_assert_false (g_ref_count_compare (&a, 1));
41 g_assert_false (g_ref_count_compare (&a, G_MAXINT));
42
43 /* b = a = 2 */
44 b = a;
45 if (g_test_verbose ())
46 g_test_message ("a := %d, b := %d\n", (int) a, (int) b);
47
48 /* inc(a): 3 */
49 g_ref_count_inc (&a);
50 if (g_test_verbose ())
51 g_test_message ("inc(a) := %d\n", (int) a);
52
53 /* dec(b) = 1 */
54 if (g_test_verbose ())
55 g_test_message ("dec(b) := %d + 1\n", (int) b);
56 g_assert_false (g_ref_count_dec (&b));
57
58 /* dec(a) = 2 */
59 if (g_test_verbose ())
60 g_test_message ("dec(a) := %d + 1\n", (int) a);
61 g_assert_false (g_ref_count_dec (&a));
62
63 /* dec(b) = 0 */
64 if (g_test_verbose ())
65 g_test_message ("dec(b) := %d + 1\n", (int) b);
66 g_assert_true (g_ref_count_dec (&b));
67
68 /* dec(a) = 1 */
69 if (g_test_verbose ())
70 g_test_message ("dec(a) := %d + 1\n", (int) a);
71 g_assert_false (g_ref_count_dec (&a));
72
73 /* dec(a) = 0 */
74 if (g_test_verbose ())
75 g_test_message ("dec(a) := %d + 1\n", (int) a);
76 g_assert_true (g_ref_count_dec (&a));
77 }
78
79 /* test_grefcount_saturation: Saturating a grefcount counter
80 * does not cause an overflow; additionally, if we're building
81 * with checks enabled or with non-GCC compilers, it'll cause a
82 * warning
83 */
84 static void
85 test_grefcount_saturation (void)
86 {
87 if (g_test_subprocess ())
88 {
89 grefcount a;
90
91 /* We're breaking abstraction here for convenience */
92 a = G_MININT + 1;
93
94 g_ref_count_inc (&a);
95 g_assert_true (a == G_MININT);
96
97 g_ref_count_inc (&a);
98 g_assert_true (a == G_MININT);
99
100 exit (0);
101 }
102
103 g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
104
105 #if defined (G_DISABLE_CHECKS) && defined (__GNUC__)
106 /* With checks disabled we don't get any warning */
107 g_test_trap_assert_passed ();
108 #else
109 /* Ensure that we got a warning when building with checks or with
110 * non-GCC compilers; the test will fail because of the critical
111 * warning being caught by GTest
112 */
113 g_test_trap_assert_failed ();
114 g_test_trap_assert_stderr ("*saturation*");
115 #endif
116 }
117
118 /* test_gatomicrefcount: test the behavior of the gatomicrefcount API */
119 static void
120 test_gatomicrefcount (void)
121 {
122 gatomicrefcount a, b;
123
124 /* init(a): 1 */
125 g_atomic_ref_count_init (&a);
126 if (g_test_verbose ())
127 g_test_message ("init(a) := %d\n", (int) a);
128 g_assert_true (g_atomic_ref_count_compare (&a, 1));
129
130 /* inc(a): 2 */
131 g_atomic_ref_count_inc (&a);
132 if (g_test_verbose ())
133 g_test_message ("inc(a) := %d\n", (int) a);
134 g_assert_false (g_atomic_ref_count_compare (&a, 1));
135 g_assert_false (g_atomic_ref_count_compare (&a, G_MAXINT));
136
137 /* b = a = 2 */
138 b = a;
139 if (g_test_verbose ())
140 g_test_message ("a := %d, b := %d\n", (int) a, (int) b);
141
142 /* inc(a): 3 */
143 g_atomic_ref_count_inc (&a);
144 if (g_test_verbose ())
145 g_test_message ("inc(a) := %d\n", (int) a);
146
147 /* dec(b) = 1 */
148 if (g_test_verbose ())
149 g_test_message ("dec(b) := %d + 1\n", (int) b);
150 g_assert_false (g_atomic_ref_count_dec (&b));
151
152 /* dec(a) = 2 */
153 if (g_test_verbose ())
154 g_test_message ("dec(a) := %d + 1\n", (int) a);
155 g_assert_false (g_atomic_ref_count_dec (&a));
156
157 /* dec(b) = 0 */
158 if (g_test_verbose ())
159 g_test_message ("dec(b) := %d + 1\n", (int) b);
160 g_assert_true (g_atomic_ref_count_dec (&b));
161
162 /* dec(a) = 1 */
163 if (g_test_verbose ())
164 g_test_message ("dec(a) := %d + 1\n", (int) a);
165 g_assert_false (g_atomic_ref_count_dec (&a));
166
167 /* dec(a) = 0 */
168 if (g_test_verbose ())
169 g_test_message ("dec(a) := %d + 1\n", (int) a);
170 g_assert_true (g_atomic_ref_count_dec (&a));
171 }
172
173 /* test_gatomicrefcount_saturation: Saturating a gatomicrefcount counter
174 * does not cause an overflow; additionally, if we're building with
175 * checks enabled or with non-GCC compilers, it'll cause a warning
176 */
177 static void
178 test_gatomicrefcount_saturation (void)
179 {
180 if (g_test_subprocess ())
181 {
182 gatomicrefcount a;
183
184 /* We're breaking abstraction here for convenience */
185 a = G_MAXINT - 1;
186
187 g_atomic_ref_count_inc (&a);
188 g_assert_true (a == G_MAXINT);
189
190 g_atomic_ref_count_inc (&a);
191 g_assert_true (a == G_MAXINT);
192
193 exit (0);
194 }
195
196 g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
197
198 #if defined (G_DISABLE_CHECKS) && defined (__GNUC__)
199 /* With checks disabled we don't get any warning */
200 g_test_trap_assert_passed ();
201 #else
202 /* Ensure that we got a warning when building with checks or with
203 * non-GCC compilers; the test will fail because of the critical
204 * warning being caught by GTest
205 */
206 g_test_trap_assert_failed ();
207 g_test_trap_assert_stderr ("*saturation*");
208 #endif
209 }
210
211 int
212 main (int argc,
213 char *argv[])
214 {
215 g_test_init (&argc, &argv, NULL);
216
217 g_test_add_func ("/refcount/grefcount", test_grefcount);
218 g_test_add_func ("/refcount/grefcount/saturation", test_grefcount_saturation);
219
220 g_test_add_func ("/refcount/gatomicrefcount", test_gatomicrefcount);
221 g_test_add_func ("/refcount/gatomicrefcount/saturation", test_gatomicrefcount_saturation);
222
223 return g_test_run ();
224 }